1
0
mirror of https://git.zx2c4.com/wireguard-go synced 2024-11-15 09:15:14 +01:00

setupapi: safer aliasing of slice types

This commit is contained in:
Jason A. Donenfeld 2019-05-03 09:34:00 +02:00
parent 2e988467c2
commit 81ca08f1b3
5 changed files with 40 additions and 23 deletions

View File

@ -12,7 +12,7 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
//sys clsidFromString(lpsz *uint16, pclsid *windows.GUID) (hr int32) = ole32.CLSIDFromString //sys clsidFromString(lpsz *uint16, pclsid *windows.GUID) (err error) [failretval!=0] = ole32.CLSIDFromString
// //
// FromString parses "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" string to GUID. // FromString parses "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" string to GUID.
@ -22,14 +22,11 @@ func FromString(str string) (*windows.GUID, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
guid := &windows.GUID{} guid := &windows.GUID{}
err = clsidFromString(strUTF16, guid)
hr := clsidFromString(strUTF16, guid) if err != nil {
if hr < 0 { return nil, err
return nil, syscall.Errno(hr)
} }
return guid, nil return guid, nil
} }

View File

@ -42,8 +42,14 @@ var (
procCLSIDFromString = modole32.NewProc("CLSIDFromString") procCLSIDFromString = modole32.NewProc("CLSIDFromString")
) )
func clsidFromString(lpsz *uint16, pclsid *windows.GUID) (hr int32) { func clsidFromString(lpsz *uint16, pclsid *windows.GUID) (err error) {
r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0) r1, _, e1 := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0)
hr = int32(r0) if r1 != 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return return
} }

View File

@ -8,6 +8,7 @@ package setupapi
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"runtime"
"syscall" "syscall"
"unsafe" "unsafe"
@ -261,9 +262,13 @@ func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *Dev
func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) { func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
switch dataType { switch dataType {
case windows.REG_SZ: case windows.REG_SZ:
return windows.UTF16ToString(BufToUTF16(buf)), nil ret := windows.UTF16ToString(bufToUTF16(buf))
runtime.KeepAlive(buf)
return ret, nil
case windows.REG_EXPAND_SZ: case windows.REG_EXPAND_SZ:
return registry.ExpandString(windows.UTF16ToString(BufToUTF16(buf))) ret, err := registry.ExpandString(windows.UTF16ToString(bufToUTF16(buf)))
runtime.KeepAlive(buf)
return ret, err
case windows.REG_BINARY: case windows.REG_BINARY:
return buf, nil return buf, nil
case windows.REG_DWORD_LITTLE_ENDIAN: case windows.REG_DWORD_LITTLE_ENDIAN:
@ -271,7 +276,7 @@ func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
case windows.REG_DWORD_BIG_ENDIAN: case windows.REG_DWORD_BIG_ENDIAN:
return binary.BigEndian.Uint32(buf), nil return binary.BigEndian.Uint32(buf), nil
case windows.REG_MULTI_SZ: case windows.REG_MULTI_SZ:
bufW := BufToUTF16(buf) bufW := bufToUTF16(buf)
a := []string{} a := []string{}
for i := 0; i < len(bufW); { for i := 0; i < len(bufW); {
j := i + wcslen(bufW[i:]) j := i + wcslen(bufW[i:])
@ -280,6 +285,7 @@ func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
} }
i = j + 1 i = j + 1
} }
runtime.KeepAlive(buf)
return a, nil return a, nil
case windows.REG_QWORD_LITTLE_ENDIAN: case windows.REG_QWORD_LITTLE_ENDIAN:
return binary.LittleEndian.Uint64(buf), nil return binary.LittleEndian.Uint64(buf), nil
@ -288,8 +294,8 @@ func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
} }
} }
// BufToUTF16 function reinterprets []byte buffer as []uint16 // bufToUTF16 function reinterprets []byte buffer as []uint16
func BufToUTF16(buf []byte) []uint16 { func bufToUTF16(buf []byte) []uint16 {
sl := struct { sl := struct {
addr *uint16 addr *uint16
len int len int
@ -298,8 +304,8 @@ func BufToUTF16(buf []byte) []uint16 {
return *(*[]uint16)(unsafe.Pointer(&sl)) return *(*[]uint16)(unsafe.Pointer(&sl))
} }
// UTF16ToBuf function reinterprets []uint16 as []byte // utf16ToBuf function reinterprets []uint16 as []byte
func UTF16ToBuf(buf []uint16) []byte { func utf16ToBuf(buf []uint16) []byte {
sl := struct { sl := struct {
addr *byte addr *byte
len int len int
@ -334,6 +340,16 @@ func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoDa
return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers) return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers)
} }
func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error {
str16, err := windows.UTF16FromString(str)
if err != nil {
return err
}
err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0)))
runtime.KeepAlive(str16)
return err
}
//sys setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW //sys setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW
// SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element. // SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.

View File

@ -6,6 +6,7 @@
package setupapi package setupapi
import ( import (
"runtime"
"strings" "strings"
"syscall" "syscall"
"testing" "testing"
@ -471,7 +472,7 @@ func TestSetupDiGetSelectedDevice(t *testing.T) {
func TestUTF16ToBuf(t *testing.T) { func TestUTF16ToBuf(t *testing.T) {
buf := []uint16{0x0123, 0x4567, 0x89ab, 0xcdef} buf := []uint16{0x0123, 0x4567, 0x89ab, 0xcdef}
buf2 := UTF16ToBuf(buf) buf2 := utf16ToBuf(buf)
if len(buf)*2 != len(buf2) || if len(buf)*2 != len(buf2) ||
cap(buf)*2 != cap(buf2) || cap(buf)*2 != cap(buf2) ||
buf2[0] != 0x23 || buf2[1] != 0x01 || buf2[0] != 0x23 || buf2[1] != 0x01 ||
@ -480,4 +481,5 @@ func TestUTF16ToBuf(t *testing.T) {
buf2[6] != 0xef || buf2[7] != 0xcd { buf2[6] != 0xef || buf2[7] != 0xcd {
t.Errorf("SetupDiSetSelectedDevice(nil) should fail with ERROR_INVALID_USER_BUFFER") t.Errorf("SetupDiSetSelectedDevice(nil) should fail with ERROR_INVALID_USER_BUFFER")
} }
runtime.KeepAlive(buf)
} }

View File

@ -218,11 +218,7 @@ func CreateInterface(description string, hwndParent uintptr) (*Wintun, bool, err
} }
// Set Plug&Play device hardware ID property. // Set Plug&Play device hardware ID property.
hwid, err := syscall.UTF16FromString(hardwareID) err = devInfoList.SetDeviceRegistryPropertyString(deviceData, setupapi.SPDRP_HARDWAREID, hardwareID)
if err != nil {
return nil, false, err // syscall.UTF16FromString(hardwareID) should never fail: hardwareID is const string without NUL chars.
}
err = devInfoList.SetDeviceRegistryProperty(deviceData, setupapi.SPDRP_HARDWAREID, setupapi.UTF16ToBuf(append(hwid, 0)))
if err != nil { if err != nil {
return nil, false, errors.New("SetupDiSetDeviceRegistryProperty(SPDRP_HARDWAREID) failed: " + err.Error()) return nil, false, errors.New("SetupDiSetDeviceRegistryProperty(SPDRP_HARDWAREID) failed: " + err.Error())
} }