"syscall/js": {"L0"},
"internal/oserror": {"L0"},
"internal/syscall/unix": {"L0", "syscall"},
- "internal/syscall/windows": {"L0", "syscall", "internal/syscall/windows/sysdll"},
+ "internal/syscall/windows": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
"internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
"time": {
// "L0" without the "io" package:
// Path returns path stored in rb.
func (rb *SymbolicLinkReparseBuffer) Path() string {
- p := (*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))
- return syscall.UTF16ToString(p[rb.SubstituteNameOffset/2 : (rb.SubstituteNameOffset+rb.SubstituteNameLength)/2])
+ n1 := rb.SubstituteNameOffset / 2
+ n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2
+ return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2])
}
type MountPointReparseBuffer struct {
// Path returns path stored in rb.
func (rb *MountPointReparseBuffer) Path() string {
- p := (*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))
- return syscall.UTF16ToString(p[rb.SubstituteNameOffset/2 : (rb.SubstituteNameOffset+rb.SubstituteNameLength)/2])
+ n1 := rb.SubstituteNameOffset / 2
+ n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2
+ return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2])
}
import (
"sync"
"syscall"
+ "unicode/utf16"
"unsafe"
)
+// UTF16PtrToString is like UTF16ToString, but takes *uint16
+// as a parameter instead of []uint16.
+// max is how many times p can be advanced looking for the null terminator.
+// If max is hit, the string is truncated at that point.
+func UTF16PtrToString(p *uint16, max int) string {
+ if p == nil {
+ return ""
+ }
+ // Find NUL terminator.
+ end := unsafe.Pointer(p)
+ n := 0
+ for *(*uint16)(end) != 0 && n < max {
+ end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
+ n++
+ }
+ s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
+ return string(utf16.Decode(s))
+}
+
const (
ERROR_SHARING_VIOLATION syscall.Errno = 32
ERROR_LOCK_VIOLATION syscall.Errno = 33
if ifindex == 0 || ifindex == int(index) {
ifi := Interface{
Index: int(index),
- Name: syscall.UTF16ToString((*(*[10000]uint16)(unsafe.Pointer(aa.FriendlyName)))[:]),
+ Name: windows.UTF16PtrToString(aa.FriendlyName, 10000),
}
if aa.OperStatus == windows.IfOperStatusUp {
ifi.Flags |= FlagUp
import (
"context"
+ "internal/syscall/windows"
"os"
"runtime"
"syscall"
defer syscall.DnsRecordListFree(r, 1)
resolved := resolveCNAME(syscall.StringToUTF16Ptr(name), r)
- cname := syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(resolved))[:])
+ cname := windows.UTF16PtrToString(resolved, 256)
return absDomainName([]byte(cname)), nil
}
mxs := make([]*MX, 0, 10)
for _, p := range validRecs(r, syscall.DNS_TYPE_MX, name) {
v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0]))
- mxs = append(mxs, &MX{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.NameExchange))[:]))), v.Preference})
+ mxs = append(mxs, &MX{absDomainName([]byte(windows.UTF16PtrToString(v.NameExchange, 256))), v.Preference})
}
byPref(mxs).sort()
return mxs, nil
for _, p := range validRecs(r, syscall.DNS_TYPE_TEXT, name) {
d := (*syscall.DNSTXTData)(unsafe.Pointer(&p.Data[0]))
s := ""
- for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringArray[0])))[:d.StringCount] {
- s += syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(v))[:])
+ for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringArray[0])))[:d.StringCount:d.StringCount] {
+ s += windows.UTF16PtrToString(v, 1<<20)
}
txts = append(txts, s)
}
ptrs := make([]string, 0, 10)
for _, p := range validRecs(r, syscall.DNS_TYPE_PTR, arpa) {
v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
- ptrs = append(ptrs, absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))))
+ ptrs = append(ptrs, absDomainName([]byte(windows.UTF16PtrToString(v.Host, 256))))
}
return ptrs, nil
}
defer windows.DestroyEnvironmentBlock(block)
blockp := uintptr(unsafe.Pointer(block))
for {
- entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:]
- for i, v := range entry {
- if v == 0 {
- entry = entry[:i]
- break
- }
+
+ // find NUL terminator
+ end := unsafe.Pointer(blockp)
+ for *(*uint16)(end) != 0 {
+ end = unsafe.Pointer(uintptr(end) + 2)
}
- if len(entry) == 0 {
+
+ n := (uintptr(end) - uintptr(unsafe.Pointer(blockp))) / 2
+ if n == 0 {
+ // environment block ends with empty string
break
}
+
+ entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:n:n]
env = append(env, string(utf16.Decode(entry)))
blockp += 2 * (uintptr(len(entry)) + 1)
}
import (
"errors"
+ "internal/syscall/windows"
"runtime"
"sync/atomic"
"syscall"
"time"
- "unsafe"
)
func (p *Process) wait() (ps *ProcessState, err error) {
}
func init() {
- p := syscall.GetCommandLine()
- cmd := syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(p))[:])
+ cmd := windows.UTF16PtrToString(syscall.GetCommandLine(), 0xffff)
if len(cmd) == 0 {
arg0, _ := Executable()
Args = []string{arg0}
buf.SubstituteNameLength = target.substituteName.length
buf.PrintNameOffset = target.printName.offset
buf.PrintNameLength = target.printName.length
- copy((*[2048]uint16)(unsafe.Pointer(&buf.PathBuffer[0]))[:], target.pathBuf)
+ pbuflen := len(target.pathBuf)
+ copy((*[2048]uint16)(unsafe.Pointer(&buf.PathBuffer[0]))[:pbuflen:pbuflen], target.pathBuf)
var rdb _REPARSE_DATA_BUFFER
rdb.header.ReparseTag = windows.IO_REPARSE_TAG_MOUNT_POINT
if isrelative {
buf.Flags = windows.SYMLINK_FLAG_RELATIVE
}
- copy((*[2048]uint16)(unsafe.Pointer(&buf.PathBuffer[0]))[:], target.pathBuf)
+ pbuflen := len(target.pathBuf)
+ copy((*[2048]uint16)(unsafe.Pointer(&buf.PathBuffer[0]))[:pbuflen:pbuflen], target.pathBuf)
var rdb _REPARSE_DATA_BUFFER
rdb.header.ReparseTag = syscall.IO_REPARSE_TAG_SYMLINK
if n > consoleSize {
n = consoleSize
}
- n = copy((*[10000]uint16)(unsafe.Pointer(buf))[:n], s16)
+ n = copy((*[10000]uint16)(unsafe.Pointer(buf))[:n:n], s16)
s16 = s16[n:]
*read = uint32(n)
t.Logf("read %d -> %d", toread, *read)
}
defer syscall.NetApiBufferFree(p)
i := (*syscall.UserInfo10)(unsafe.Pointer(p))
- if i.FullName == nil {
- return "", nil
- }
- name := syscall.UTF16ToString((*[1024]uint16)(unsafe.Pointer(i.FullName))[:])
- return name, nil
+ return windows.UTF16PtrToString(i.FullName, 1024), nil
}
func lookupFullName(domain, username, domainAndUser string) (string, error) {
if entriesRead == 0 {
return nil, fmt.Errorf("listGroupsForUsernameAndDomain: NetUserGetLocalGroups() returned an empty list for domain: %s, username: %s", domain, username)
}
- entries := (*[1024]windows.LocalGroupUserInfo0)(unsafe.Pointer(p0))[:entriesRead]
+ entries := (*[1024]windows.LocalGroupUserInfo0)(unsafe.Pointer(p0))[:entriesRead:entriesRead]
var sids []string
for _, entry := range entries {
if entry.Name == nil {
continue
}
- name := syscall.UTF16ToString((*[1024]uint16)(unsafe.Pointer(entry.Name))[:])
- sid, err := lookupGroupName(name)
+ sid, err := lookupGroupName(windows.UTF16PtrToString(entry.Name, 1024))
if err != nil {
return nil, err
}
return "", e
}
defer LocalFree((Handle)(unsafe.Pointer(s)))
- return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
+ return utf16PtrToString(s, 256), nil
}
// Len returns the length, in bytes, of a valid security identifier sid.
return string(utf16.Decode(s))
}
+// utf16PtrToString is like UTF16ToString, but takes *uint16
+// as a parameter instead of []uint16.
+// max is how many times p can be advanced looking for the null terminator.
+// If max is hit, the string is truncated at that point.
+func utf16PtrToString(p *uint16, max int) string {
+ if p == nil {
+ return ""
+ }
+ // Find NUL terminator.
+ end := unsafe.Pointer(p)
+ n := 0
+ for *(*uint16)(end) != 0 && n < max {
+ end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
+ n++
+ }
+ s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
+ return string(utf16.Decode(s))
+}
+
// StringToUTF16Ptr returns pointer to the UTF-16 encoding of
// the UTF-8 string s, with a terminating NUL added. If s
// contains a NUL byte this function panics instead of
for n < len(pp.Path) && pp.Path[n] != 0 {
n++
}
- bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
+ bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n:n]
sa.Name = string(bytes)
return sa, nil