mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-03 15:47:35 -04:00
windows: add Get*PreferredUILanguages
This commit adds the following MUI functions: - GetUserPreferredUILanguages - GetSystemPreferredUILanguages - GetThreadPreferredUILanguages - GetProcessPreferredUILanguages Change-Id: I44f1c07245ab814935778c6b910b224d24cc753c Reviewed-on: https://go-review.googlesource.com/c/sys/+/207860 Reviewed-by: Simon Rozman <simon@rozman.si> Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com> Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
committed by
Jason A. Donenfeld
parent
f068ffe820
commit
6bfc516c86
@@ -313,6 +313,10 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
|||||||
//sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree
|
//sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree
|
||||||
//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion
|
//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion
|
||||||
//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers
|
//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers
|
||||||
|
//sys getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetProcessPreferredUILanguages
|
||||||
|
//sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages
|
||||||
|
//sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages
|
||||||
|
//sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages
|
||||||
|
|
||||||
// Process Status API (PSAPI)
|
// Process Status API (PSAPI)
|
||||||
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
|
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
|
||||||
@@ -1378,3 +1382,54 @@ func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) {
|
|||||||
buildNumber &= 0xffff
|
buildNumber &= 0xffff
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProcessPreferredUILanguages retrieves the process preferred UI languages.
|
||||||
|
func GetProcessPreferredUILanguages(flags uint32) ([]string, error) {
|
||||||
|
return getUILanguages(flags, getProcessPreferredUILanguages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetThreadPreferredUILanguages retrieves the thread preferred UI languages for the current thread.
|
||||||
|
func GetThreadPreferredUILanguages(flags uint32) ([]string, error) {
|
||||||
|
return getUILanguages(flags, getThreadPreferredUILanguages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserPreferredUILanguages retrieves information about the user preferred UI languages.
|
||||||
|
func GetUserPreferredUILanguages(flags uint32) ([]string, error) {
|
||||||
|
return getUILanguages(flags, getUserPreferredUILanguages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSystemPreferredUILanguages retrieves the system preferred UI languages.
|
||||||
|
func GetSystemPreferredUILanguages(flags uint32) ([]string, error) {
|
||||||
|
return getUILanguages(flags, getSystemPreferredUILanguages)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUILanguages(flags uint32, f func(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) error) ([]string, error) {
|
||||||
|
size := uint32(128)
|
||||||
|
for {
|
||||||
|
var numLanguages uint32
|
||||||
|
buf := make([]uint16, size)
|
||||||
|
err := f(flags, &numLanguages, &buf[0], &size)
|
||||||
|
if err == ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf = buf[:size]
|
||||||
|
if numLanguages == 0 || len(buf) == 0 { // GetProcessPreferredUILanguages may return numLanguages==0 with "\0\0"
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
if buf[len(buf)-1] == 0 {
|
||||||
|
buf = buf[:len(buf)-1] // remove terminating null
|
||||||
|
}
|
||||||
|
languages := make([]string, 0, numLanguages)
|
||||||
|
from := 0
|
||||||
|
for i, c := range buf {
|
||||||
|
if c == 0 {
|
||||||
|
languages = append(languages, string(utf16.Decode(buf[from:i])))
|
||||||
|
from = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return languages, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -377,3 +378,29 @@ func TestGetDiskFreeSpaceEx(t *testing.T) {
|
|||||||
t.Errorf("totalNumberOfFreeBytes: got 0; want > 0")
|
t.Errorf("totalNumberOfFreeBytes: got 0; want > 0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetPreferredUILanguages(t *testing.T) {
|
||||||
|
tab := map[string]func(flags uint32) ([]string, error){
|
||||||
|
"GetProcessPreferredUILanguages": windows.GetProcessPreferredUILanguages,
|
||||||
|
"GetThreadPreferredUILanguages": windows.GetThreadPreferredUILanguages,
|
||||||
|
"GetUserPreferredUILanguages": windows.GetUserPreferredUILanguages,
|
||||||
|
"GetSystemPreferredUILanguages": windows.GetSystemPreferredUILanguages,
|
||||||
|
}
|
||||||
|
for fName, f := range tab {
|
||||||
|
lang, err := f(windows.MUI_LANGUAGE_ID)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(`failed to call %v(MUI_LANGUAGE_ID): %v`, fName, err)
|
||||||
|
}
|
||||||
|
for _, l := range lang {
|
||||||
|
_, err := strconv.ParseUint(l, 16, 16)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(`%v(MUI_LANGUAGE_ID) returned unexpected LANGID: %v`, fName, l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lang, err = f(windows.MUI_LANGUAGE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(`failed to call %v(MUI_LANGUAGE_NAME): %v`, fName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1742,3 +1742,36 @@ const (
|
|||||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2
|
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2
|
||||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4
|
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MUI function flag values
|
||||||
|
const (
|
||||||
|
MUI_LANGUAGE_ID = 0x4
|
||||||
|
MUI_LANGUAGE_NAME = 0x8
|
||||||
|
MUI_MERGE_SYSTEM_FALLBACK = 0x10
|
||||||
|
MUI_MERGE_USER_FALLBACK = 0x20
|
||||||
|
MUI_UI_FALLBACK = MUI_MERGE_SYSTEM_FALLBACK | MUI_MERGE_USER_FALLBACK
|
||||||
|
MUI_THREAD_LANGUAGES = 0x40
|
||||||
|
MUI_CONSOLE_FILTER = 0x100
|
||||||
|
MUI_COMPLEX_SCRIPT_FILTER = 0x200
|
||||||
|
MUI_RESET_FILTERS = 0x001
|
||||||
|
MUI_USER_PREFERRED_UI_LANGUAGES = 0x10
|
||||||
|
MUI_USE_INSTALLED_LANGUAGES = 0x20
|
||||||
|
MUI_USE_SEARCH_ALL_LANGUAGES = 0x40
|
||||||
|
MUI_LANG_NEUTRAL_PE_FILE = 0x100
|
||||||
|
MUI_NON_LANG_NEUTRAL_FILE = 0x200
|
||||||
|
MUI_MACHINE_LANGUAGE_SETTINGS = 0x400
|
||||||
|
MUI_FILETYPE_NOT_LANGUAGE_NEUTRAL = 0x001
|
||||||
|
MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN = 0x002
|
||||||
|
MUI_FILETYPE_LANGUAGE_NEUTRAL_MUI = 0x004
|
||||||
|
MUI_QUERY_TYPE = 0x001
|
||||||
|
MUI_QUERY_CHECKSUM = 0x002
|
||||||
|
MUI_QUERY_LANGUAGE_NAME = 0x004
|
||||||
|
MUI_QUERY_RESOURCE_TYPES = 0x008
|
||||||
|
MUI_FILEINFO_VERSION = 0x001
|
||||||
|
|
||||||
|
MUI_FULL_LANGUAGE = 0x01
|
||||||
|
MUI_PARTIAL_LANGUAGE = 0x02
|
||||||
|
MUI_LIP_LANGUAGE = 0x04
|
||||||
|
MUI_LANGUAGE_INSTALLED = 0x20
|
||||||
|
MUI_LANGUAGE_LICENSED = 0x40
|
||||||
|
)
|
||||||
|
|||||||
@@ -248,6 +248,10 @@ var (
|
|||||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||||
procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
|
procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
|
||||||
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
|
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
|
||||||
|
procGetProcessPreferredUILanguages = modkernel32.NewProc("GetProcessPreferredUILanguages")
|
||||||
|
procGetThreadPreferredUILanguages = modkernel32.NewProc("GetThreadPreferredUILanguages")
|
||||||
|
procGetUserPreferredUILanguages = modkernel32.NewProc("GetUserPreferredUILanguages")
|
||||||
|
procGetSystemPreferredUILanguages = modkernel32.NewProc("GetSystemPreferredUILanguages")
|
||||||
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
|
procEnumProcesses = modpsapi.NewProc("EnumProcesses")
|
||||||
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
||||||
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
||||||
@@ -2760,6 +2764,54 @@ func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNum
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procGetProcessPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procGetThreadPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procGetUserPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall6(procGetSystemPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
|
func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) {
|
||||||
var _p0 *uint32
|
var _p0 *uint32
|
||||||
if len(processIds) > 0 {
|
if len(processIds) > 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user