mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-02 23:27:31 -04:00
windows: use proper system directory path in fallback loader
The %WINDIR% variable is an odd choice and not even entirely reliable. Since Windows 2000, there has been a specific function for determining this information, so let's use it. It's also a useful function in its own right for folks who want to launch system tools in a somewhat safe way, like netsh.exe. Updates golang/go#14959 Updates golang/go#30642 Change-Id: Ic24baf37d14f2daced0c1db2771b5a673d2c8852 Reviewed-on: https://go-review.googlesource.com/c/sys/+/165759 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
committed by
Alex Brainman
parent
980fc434d2
commit
10058d7d4f
@@ -359,11 +359,11 @@ func loadLibraryEx(name string, system bool) (*DLL, error) {
|
|||||||
// trying to load "foo.dll" out of the system
|
// trying to load "foo.dll" out of the system
|
||||||
// folder, but LoadLibraryEx doesn't support
|
// folder, but LoadLibraryEx doesn't support
|
||||||
// that yet on their system, so emulate it.
|
// that yet on their system, so emulate it.
|
||||||
windir, _ := Getenv("WINDIR") // old var; apparently works on XP
|
systemdir, err := GetSystemDirectory()
|
||||||
if windir == "" {
|
if err != nil {
|
||||||
return nil, errString("%WINDIR% not defined")
|
return nil, err
|
||||||
}
|
}
|
||||||
loadDLL = windir + "\\System32\\" + name
|
loadDLL = systemdir + "\\" + name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h, err := LoadLibraryEx(loadDLL, 0, flags)
|
h, err := LoadLibraryEx(loadDLL, 0, flags)
|
||||||
|
|||||||
@@ -372,6 +372,7 @@ type Tokengroups struct {
|
|||||||
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
|
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
|
||||||
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
|
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
|
||||||
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
||||||
|
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
||||||
|
|
||||||
// An access token contains the security information for a logon session.
|
// An access token contains the security information for a logon session.
|
||||||
// The system creates an access token when a user logs on, and every
|
// The system creates an access token when a user logs on, and every
|
||||||
@@ -468,6 +469,23 @@ func (t Token) GetUserProfileDirectory() (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSystemDirectory retrieves path to current location of the system
|
||||||
|
// directory, which is typically, though not always, C:\Windows\System32.
|
||||||
|
func GetSystemDirectory() (string, error) {
|
||||||
|
n := uint32(MAX_PATH)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
l, e := getSystemDirectory(&b[0], n)
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
if l <= n {
|
||||||
|
return UTF16ToString(b[:l]), nil
|
||||||
|
}
|
||||||
|
n = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IsMember reports whether the access token t is a member of the provided SID.
|
// IsMember reports whether the access token t is a member of the provided SID.
|
||||||
func (t Token) IsMember(sid *SID) (bool, error) {
|
func (t Token) IsMember(sid *SID) (bool, error) {
|
||||||
var b int32
|
var b int32
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
package windows_test
|
package windows_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -51,3 +52,13 @@ func TestGetProcAddressByOrdinal(t *testing.T) {
|
|||||||
t.Error("shlwapi.dll:IsOS(OS_NT) returned 0, expected non-zero value")
|
t.Error("shlwapi.dll:IsOS(OS_NT) returned 0, expected non-zero value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetSystemDirectory(t *testing.T) {
|
||||||
|
d, err := windows.GetSystemDirectory()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get system directory: %s", err)
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(strings.ToLower(d), "\\system32") {
|
||||||
|
t.Fatalf("System directory does not end in system32: %s", d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -252,6 +252,7 @@ var (
|
|||||||
procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken")
|
procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken")
|
||||||
procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation")
|
procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation")
|
||||||
procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW")
|
procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW")
|
||||||
|
procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW")
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) {
|
func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) {
|
||||||
@@ -2718,3 +2719,16 @@ func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0)
|
||||||
|
len = uint32(r0)
|
||||||
|
if len == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user