mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-12-27 11:59:40 -08:00
parent
632e495141
commit
1e797acf77
|
@ -397,7 +397,7 @@ func (env *ShellEnvironment) RunCommand(command string, args ...string) (string,
|
||||||
env.log(Error, "RunCommand", errorStr)
|
env.log(Error, "RunCommand", errorStr)
|
||||||
return output, cmdErr
|
return output, cmdErr
|
||||||
}
|
}
|
||||||
output := strings.TrimSuffix(out.String(), "\n")
|
output := strings.TrimSpace(out.String())
|
||||||
env.log(Debug, "RunCommand", output)
|
env.log(Debug, "RunCommand", output)
|
||||||
return output, nil
|
return output, nil
|
||||||
}
|
}
|
||||||
|
@ -418,6 +418,10 @@ func (env *ShellEnvironment) HasCommand(command string) bool {
|
||||||
env.cmdCache.set(command, path)
|
env.cmdCache.set(command, path)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if path, err := env.LookWinAppPath(command); err == nil {
|
||||||
|
env.cmdCache.set(command, path)
|
||||||
|
return true
|
||||||
|
}
|
||||||
env.log(Error, "HasCommand", err.Error())
|
env.log(Error, "HasCommand", err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,3 +119,7 @@ func (env *ShellEnvironment) ConvertToLinuxPath(path string) string {
|
||||||
func (env *ShellEnvironment) WifiNetwork() (*WifiInfo, error) {
|
func (env *ShellEnvironment) WifiNetwork() (*WifiInfo, error) {
|
||||||
return nil, errors.New("not implemented")
|
return nil, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *ShellEnvironment) LookWinAppPath(file string) (string, error) {
|
||||||
|
return "", errors.New("not relevant")
|
||||||
|
}
|
||||||
|
|
|
@ -116,6 +116,19 @@ func (env *ShellEnvironment) CachePath() string {
|
||||||
return env.Home()
|
return env.Home()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *ShellEnvironment) LookWinAppPath(file string) (string, error) {
|
||||||
|
winAppPath := env.Home() + `\AppData\Local\Microsoft\WindowsApps\`
|
||||||
|
command := file + ".exe"
|
||||||
|
isWinStoreApp := func() bool {
|
||||||
|
return env.HasFilesInDir(winAppPath, command)
|
||||||
|
}
|
||||||
|
if isWinStoreApp() {
|
||||||
|
commandFile := winAppPath + command
|
||||||
|
return readWinAppLink(commandFile)
|
||||||
|
}
|
||||||
|
return "", errors.New("no Windows Store App")
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Takes a registry path to a key like
|
// Takes a registry path to a key like
|
||||||
// "HKLM\Software\Microsoft\Windows NT\CurrentVersion\EditionID"
|
// "HKLM\Software\Microsoft\Windows NT\CurrentVersion\EditionID"
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
package environment
|
package environment
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"oh-my-posh/regex"
|
"oh-my-posh/regex"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
|
@ -199,3 +201,83 @@ func getHKEYHandleFromAbbrString(abbr string) windows.Handle {
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type REPARSE_DATA_BUFFER struct { // nolint: revive
|
||||||
|
ReparseTag uint32
|
||||||
|
ReparseDataLength uint16
|
||||||
|
Reserved uint16
|
||||||
|
DUMMYUNIONNAME byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenericDataBuffer struct {
|
||||||
|
DataBuffer [1]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type AppExecLinkReparseBuffer struct {
|
||||||
|
Version uint32
|
||||||
|
StringList [1]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rb *AppExecLinkReparseBuffer) Path() string {
|
||||||
|
UTF16ToStringPosition := func(s []uint16) (string, int) {
|
||||||
|
for i, v := range s {
|
||||||
|
if v == 0 {
|
||||||
|
s = s[0:i]
|
||||||
|
return string(utf16.Decode(s)), i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
s := (*[0xffff]uint16)(unsafe.Pointer(&rb.StringList[0]))[0:]
|
||||||
|
var link string
|
||||||
|
position := 0
|
||||||
|
for i := 0; i <= 2; i++ {
|
||||||
|
link, position = UTF16ToStringPosition(s)
|
||||||
|
position++
|
||||||
|
s = s[position:]
|
||||||
|
}
|
||||||
|
return link
|
||||||
|
}
|
||||||
|
|
||||||
|
// openSymlink calls CreateFile Windows API with FILE_FLAG_OPEN_REPARSE_POINT
|
||||||
|
// parameter, so that Windows does not follow symlink, if path is a symlink.
|
||||||
|
// openSymlink returns opened file handle.
|
||||||
|
func openSymlink(path string) (syscall.Handle, error) {
|
||||||
|
p, err := syscall.UTF16PtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)
|
||||||
|
// Use FILE_FLAG_OPEN_REPARSE_POINT, otherwise CreateFile will follow symlink.
|
||||||
|
// See https://docs.microsoft.com/en-us/windows/desktop/FileIO/symbolic-link-effects-on-file-systems-functions#createfile-and-createfiletransacted
|
||||||
|
attrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT
|
||||||
|
h, err := syscall.CreateFile(p, 0, 0, nil, syscall.OPEN_EXISTING, attrs, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readWinAppLink(path string) (string, error) {
|
||||||
|
h, err := openSymlink(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer syscall.CloseHandle(h) // nolint: errcheck
|
||||||
|
|
||||||
|
rdbbuf := make([]byte, syscall.MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
|
||||||
|
var bytesReturned uint32
|
||||||
|
err = syscall.DeviceIoControl(h, syscall.FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
rdb := (*REPARSE_DATA_BUFFER)(unsafe.Pointer(&rdbbuf[0]))
|
||||||
|
rb := (*GenericDataBuffer)(unsafe.Pointer(&rdb.DUMMYUNIONNAME))
|
||||||
|
appExecLink := (*AppExecLinkReparseBuffer)(unsafe.Pointer(&rb.DataBuffer))
|
||||||
|
if appExecLink.Version != 3 {
|
||||||
|
return " ", errors.New("unknown appexec link version")
|
||||||
|
}
|
||||||
|
link := appExecLink.Path()
|
||||||
|
return link, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue