windows: correct NT definitions and add more resolution

Alex pointed out that some of these original types were incomplete, so
this commit fills things out a bit more. We also add more to the test
case.

Change-Id: Iff7bd9ea6e0d021ba997c6d7351fe7c4a46187a9
Reviewed-on: https://go-review.googlesource.com/c/sys/+/299189
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Jason A. Donenfeld
2021-03-05 08:28:14 -07:00
parent d6cf4ab887
commit 5cdee2b1b5
4 changed files with 124 additions and 23 deletions

View File

@@ -402,11 +402,12 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys rtlGetVersion(info *OsVersionInfoEx) (ntstatus error) = ntdll.RtlGetVersion
//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers
//sys RtlGetCurrentPeb() (peb *PEB) = ntdll.RtlGetCurrentPeb
//sys RtlInitUnicodeString(destinationString *UNICODE_STRING, sourceString *uint16) = ntdll.RtlInitUnicodeString
//sys RtlInitUnicodeString(destinationString *NTUnicodeString, sourceString *uint16) = ntdll.RtlInitUnicodeString
//sys RtlInitString(destinationString *NTString, sourceString *byte) = ntdll.RtlInitString
//sys NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile
//sys NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) = ntdll.NtCreateNamedPipeFile
//sys RtlDosPathNameToNtPathName(dosName *uint16, ntName *UNICODE_STRING, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToNtPathName_U_WithStatus
//sys RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *UNICODE_STRING, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToRelativeNtPathName_U_WithStatus
//sys RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToNtPathName_U_WithStatus
//sys RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToRelativeNtPathName_U_WithStatus
//sys RtlDefaultNpAcl(acl **ACL) (ntstatus error) = ntdll.RtlDefaultNpAcl
//sys NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQueryInformationProcess
//sys NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) = ntdll.NtSetInformationProcess
@@ -1560,12 +1561,12 @@ func (s NTStatus) Error() string {
return string(utf16.Decode(b[:n]))
}
// NewUnicodeString returns a new UNICODE_STRING structure for use with native
// NT APIs that work over the UNICODE_STRING type. Note that most Windows APIs
// do not use UNICODE_STRING, and instead UTF16PtrFromString should be used for
// NewNTUnicodeString returns a new NTUnicodeString structure for use with native
// NT APIs that work over the NTUnicodeString type. Note that most Windows APIs
// do not use NTUnicodeString, and instead UTF16PtrFromString should be used for
// the more common *uint16 string type.
func NewUnicodeString(s string) (*UNICODE_STRING, error) {
var u UNICODE_STRING
func NewNTUnicodeString(s string) (*NTUnicodeString, error) {
var u NTUnicodeString
s16, err := UTF16PtrFromString(s)
if err != nil {
return nil, err
@@ -1574,8 +1575,8 @@ func NewUnicodeString(s string) (*UNICODE_STRING, error) {
return &u, nil
}
// Slice returns a uint16 slice that aliases the data in the UNICODE_STRING.
func (s *UNICODE_STRING) Slice() []uint16 {
// Slice returns a uint16 slice that aliases the data in the NTUnicodeString.
func (s *NTUnicodeString) Slice() []uint16 {
var slice []uint16
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&slice))
hdr.Data = unsafe.Pointer(s.Buffer)
@@ -1584,10 +1585,38 @@ func (s *UNICODE_STRING) Slice() []uint16 {
return slice
}
func (s *UNICODE_STRING) String() string {
func (s *NTUnicodeString) String() string {
return UTF16ToString(s.Slice())
}
// NewNTString returns a new NTString structure for use with native
// NT APIs that work over the NTString type. Note that most Windows APIs
// do not use NTString, and instead UTF16PtrFromString should be used for
// the more common *uint16 string type.
func NewNTString(s string) (*NTString, error) {
var nts NTString
s8, err := BytePtrFromString(s)
if err != nil {
return nil, err
}
RtlInitString(&nts, s8)
return &nts, nil
}
// Slice returns a byte slice that aliases the data in the NTString.
func (s *NTString) Slice() []byte {
var slice []byte
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&slice))
hdr.Data = unsafe.Pointer(s.Buffer)
hdr.Len = int(s.Length)
hdr.Cap = int(s.MaximumLength)
return slice
}
func (s *NTString) String() string {
return ByteSliceToString(s.Slice())
}
// FindResource resolves a resource of the given name and resource type.
func FindResource(module Handle, name, resType ResourceIDOrString) (Handle, error) {
var namePtr, resTypePtr uintptr

View File

@@ -560,7 +560,20 @@ func TestPEBFilePath(t *testing.T) {
}
pebPath := entry.FullDllName.String()
if osPath != pebPath {
t.Errorf("expected os.Executable() to return same value as peb.Ldr.{entry}.FullDllName - want %#q; got %#q", osPath, pebPath)
t.Errorf("peb.Ldr.{entry}.FullDllName = %#q; want %#q", pebPath, osPath)
}
paramPath := peb.ProcessParameters.ImagePathName.String()
if osPath != paramPath {
t.Errorf("peb.ProcessParameters.ImagePathName.{entry}.ImagePathName = %#q; want %#q", paramPath, osPath)
}
osCwd, err := os.Getwd()
if err != nil {
t.Errorf("unable to get working directory: %v", err)
}
osCwd = filepath.Clean(osCwd)
paramCwd := filepath.Clean(peb.ProcessParameters.CurrentDirectory.DosPath.String())
if paramCwd != osCwd {
t.Errorf("peb.ProcessParameters.CurrentDirectory.DosPath = %#q; want %#q", paramCwd, osCwd)
}
}

View File

@@ -2277,12 +2277,20 @@ type CommTimeouts struct {
WriteTotalTimeoutConstant uint32
}
type UNICODE_STRING struct {
// NTUnicodeString is a UTF-16 string for NT native APIs, corresponding to UNICODE_STRING.
type NTUnicodeString struct {
Length uint16
MaximumLength uint16
Buffer *uint16
}
// NTString is an ANSI string for NT native APIs, corresponding to STRING.
type NTString struct {
Length uint16
MaximumLength uint16
Buffer *byte
}
type LIST_ENTRY struct {
Flink *LIST_ENTRY
Blink *LIST_ENTRY
@@ -2294,7 +2302,7 @@ type LDR_DATA_TABLE_ENTRY struct {
reserved2 [2]uintptr
DllBase uintptr
reserved3 [2]uintptr
FullDllName UNICODE_STRING
FullDllName NTUnicodeString
reserved4 [8]byte
reserved5 [3]uintptr
reserved6 uintptr
@@ -2307,6 +2315,51 @@ type PEB_LDR_DATA struct {
InMemoryOrderModuleList LIST_ENTRY
}
type CURDIR struct {
DosPath NTUnicodeString
Handle Handle
}
type RTL_DRIVE_LETTER_CURDIR struct {
Flags uint16
Length uint16
TimeStamp uint32
DosPath NTString
}
type RTL_USER_PROCESS_PARAMETERS struct {
MaximumLength, Length uint32
Flags, DebugFlags uint32
ConsoleHandle Handle
ConsoleFlags uint32
StandardInput, StandardOutput, StandardError Handle
CurrentDirectory CURDIR
DllPath NTUnicodeString
ImagePathName NTUnicodeString
CommandLine NTUnicodeString
Environment unsafe.Pointer
StartingX, StartingY, CountX, CountY, CountCharsX, CountCharsY, FillAttribute uint32
WindowFlags, ShowWindowFlags uint32
WindowTitle, DesktopInfo, ShellInfo, RuntimeData NTUnicodeString
CurrentDirectories [32]RTL_DRIVE_LETTER_CURDIR
EnvironmentSize, EnvironmentVersion uintptr
PackageDependencyData unsafe.Pointer
ProcessGroupId uint32
LoaderThreads uint32
RedirectionDllName NTUnicodeString
HeapPartitionName NTUnicodeString
DefaultThreadpoolCpuSetMasks uintptr
DefaultThreadpoolCpuSetMaskCount uint32
}
type PEB struct {
reserved1 [2]byte
BeingDebugged byte
@@ -2314,7 +2367,7 @@ type PEB struct {
reserved3 uintptr
ImageBaseAddress uintptr
Ldr *PEB_LDR_DATA
ProcessParameters uintptr
ProcessParameters *RTL_USER_PROCESS_PARAMETERS
reserved4 [3]uintptr
AtlThunkSListPtr uintptr
reserved5 uintptr
@@ -2333,7 +2386,7 @@ type PEB struct {
type OBJECT_ATTRIBUTES struct {
Length uint32
RootDirectory Handle
ObjectName *UNICODE_STRING
ObjectName *NTUnicodeString
Attributes uint32
SecurityDescriptor *SECURITY_DESCRIPTOR
SecurityQoS *SECURITY_QUALITY_OF_SERVICE
@@ -2365,7 +2418,7 @@ type RTLP_CURDIR_REF struct {
}
type RTL_RELATIVE_NAME struct {
RelativeName UNICODE_STRING
RelativeName NTUnicodeString
ContainingDirectory Handle
CurDirRef *RTLP_CURDIR_REF
}
@@ -2470,7 +2523,7 @@ const (
ProcessHandleTracing
ProcessIoPriority
ProcessExecuteFlags
ProcessResourceManagement
ProcessTlsInformation
ProcessCookie
ProcessImageInformation
ProcessCycleTime
@@ -2545,8 +2598,8 @@ type PROCESS_BASIC_INFORMATION struct {
PebBaseAddress *PEB
AffinityMask uintptr
BasePriority int32
UniqueProcessId Handle
InheritedFromUniqueProcessId Handle
UniqueProcessId uintptr
InheritedFromUniqueProcessId uintptr
}
// Constants for LocalAlloc flags.

View File

@@ -364,6 +364,7 @@ var (
procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb")
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
procRtlInitString = modntdll.NewProc("RtlInitString")
procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString")
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
procCLSIDFromString = modole32.NewProc("CLSIDFromString")
@@ -3096,7 +3097,7 @@ func RtlDefaultNpAcl(acl **ACL) (ntstatus error) {
return
}
func RtlDosPathNameToNtPathName(dosName *uint16, ntName *UNICODE_STRING, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) {
func RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) {
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U_WithStatus.Addr(), 4, uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName)), 0, 0)
if r0 != 0 {
ntstatus = NTStatus(r0)
@@ -3104,7 +3105,7 @@ func RtlDosPathNameToNtPathName(dosName *uint16, ntName *UNICODE_STRING, ntFileN
return
}
func RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *UNICODE_STRING, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) {
func RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) {
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToRelativeNtPathName_U_WithStatus.Addr(), 4, uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName)), 0, 0)
if r0 != 0 {
ntstatus = NTStatus(r0)
@@ -3131,7 +3132,12 @@ func rtlGetVersion(info *OsVersionInfoEx) (ntstatus error) {
return
}
func RtlInitUnicodeString(destinationString *UNICODE_STRING, sourceString *uint16) {
func RtlInitString(destinationString *NTString, sourceString *byte) {
syscall.Syscall(procRtlInitString.Addr(), 2, uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString)), 0)
return
}
func RtlInitUnicodeString(destinationString *NTUnicodeString, sourceString *uint16) {
syscall.Syscall(procRtlInitUnicodeString.Addr(), 2, uintptr(unsafe.Pointer(destinationString)), uintptr(unsafe.Pointer(sourceString)), 0)
return
}