From d80ed10b9189ce0b1a760b229806e5322643d112 Mon Sep 17 00:00:00 2001 From: Kathryn Baldauf Date: Wed, 21 Apr 2021 12:49:06 -0700 Subject: [PATCH 1/9] Revert "Replace local *FileInformationByHandleEx with x/sys/windows" This reverts commit bfd546865c984c87c6f60e8f41aec2c0c3aac9a2. Signed-off-by: Kathryn Baldauf --- backuptar/tar.go | 11 +++++------ fileinfo.go | 17 ++++++++++++----- zsyscall_windows.go | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/backuptar/tar.go b/backuptar/tar.go index cb461ca3..088a43c6 100644 --- a/backuptar/tar.go +++ b/backuptar/tar.go @@ -16,7 +16,6 @@ import ( "time" "github.com/Microsoft/go-winio" - "golang.org/x/sys/windows" ) const ( @@ -298,11 +297,11 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win size = hdr.Size } fileInfo = &winio.FileBasicInfo{ - LastAccessTime: windows.NsecToFiletime(hdr.AccessTime.UnixNano()), - LastWriteTime: windows.NsecToFiletime(hdr.ModTime.UnixNano()), - ChangeTime: windows.NsecToFiletime(hdr.ChangeTime.UnixNano()), + LastAccessTime: syscall.NsecToFiletime(hdr.AccessTime.UnixNano()), + LastWriteTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()), + ChangeTime: syscall.NsecToFiletime(hdr.ChangeTime.UnixNano()), // Default to ModTime, we'll pull hdrCreationTime below if present - CreationTime: windows.NsecToFiletime(hdr.ModTime.UnixNano()), + CreationTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()), } if attrStr, ok := hdr.PAXRecords[hdrFileAttributes]; ok { attr, err := strconv.ParseUint(attrStr, 10, 32) @@ -320,7 +319,7 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win if err != nil { return "", 0, nil, err } - fileInfo.CreationTime = windows.NsecToFiletime(creationTime.UnixNano()) + fileInfo.CreationTime = syscall.NsecToFiletime(creationTime.UnixNano()) } return } diff --git a/fileinfo.go b/fileinfo.go index 3ab6bff6..7f5b72fd 100644 --- a/fileinfo.go +++ b/fileinfo.go @@ -5,14 +5,21 @@ package winio import ( "os" "runtime" + "syscall" "unsafe" +) + +//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx +//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle - "golang.org/x/sys/windows" +const ( + fileBasicInfo = 0 + fileIDInfo = 0x12 ) // FileBasicInfo contains file access time and file attributes information. type FileBasicInfo struct { - CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime + CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime FileAttributes uint32 pad uint32 // padding } @@ -20,7 +27,7 @@ type FileBasicInfo struct { // GetFileBasicInfo retrieves times and attributes for a file. func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { bi := &FileBasicInfo{} - if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) @@ -29,7 +36,7 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { // SetFileBasicInfo sets times and attributes for a file. func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { - if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} } runtime.KeepAlive(f) @@ -65,7 +72,7 @@ type FileIDInfo struct { // GetFileID retrieves the unique (volume, file ID) pair for a file. func GetFileID(f *os.File) (*FileIDInfo, error) { fileID := &FileIDInfo{} - if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { + if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) diff --git a/zsyscall_windows.go b/zsyscall_windows.go index 176ff75e..4579c745 100644 --- a/zsyscall_windows.go +++ b/zsyscall_windows.go @@ -63,12 +63,14 @@ var ( procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") + procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") procLocalAlloc = modkernel32.NewProc("LocalAlloc") procLocalFree = modkernel32.NewProc("LocalFree") procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") @@ -337,6 +339,14 @@ func getCurrentThread() (h syscall.Handle) { return } +func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) if r1 == 0 { @@ -380,6 +390,14 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro return } +func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) status = ntstatus(r0) From e5bd3f6e2840343c8c692408e3efc746e5923249 Mon Sep 17 00:00:00 2001 From: Kathryn Baldauf Date: Wed, 21 Apr 2021 12:49:58 -0700 Subject: [PATCH 2/9] Revert "Implement winio.GetFileStandardInfo" This reverts commit ef753e60d269623cd564ba1951e5f52dc1ba439d. Signed-off-by: Kathryn Baldauf --- fileinfo.go | 19 ------- fileinfo_test.go | 134 ----------------------------------------------- 2 files changed, 153 deletions(-) delete mode 100644 fileinfo_test.go diff --git a/fileinfo.go b/fileinfo.go index 7f5b72fd..ada2fbab 100644 --- a/fileinfo.go +++ b/fileinfo.go @@ -43,25 +43,6 @@ func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { return nil } -// FileStandardInfo contains extended information for the file. -// FILE_STANDARD_INFO in WinBase.h -// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info -type FileStandardInfo struct { - AllocationSize, EndOfFile int64 - NumberOfLinks uint32 - DeletePending, Directory bool -} - -// GetFileStandardInfo retrieves ended information for the file. -func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { - si := &FileStandardInfo{} - if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil { - return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} - } - runtime.KeepAlive(f) - return si, nil -} - // FileIDInfo contains the volume serial number and file ID for a file. This pair should be // unique on a system. type FileIDInfo struct { diff --git a/fileinfo_test.go b/fileinfo_test.go deleted file mode 100644 index e79700ba..00000000 --- a/fileinfo_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package winio - -import ( - "io/ioutil" - "os" - "testing" - - "golang.org/x/sys/windows" -) - -// Checks if current matches expected. Note that AllocationSize is filesystem-specific, -// so we check that the current.AllocationSize is >= expected.AllocationSize. -// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/5afa7f66-619c-48f3-955f-68c4ece704ae -func checkFileStandardInfo(t *testing.T, current, expected *FileStandardInfo) { - if current.AllocationSize < expected.AllocationSize { - t.Fatalf("FileStandardInfo unexpectedly had AllocationSize %d, expecting >=%d", current.AllocationSize, expected.AllocationSize) - } - - if current.EndOfFile != expected.EndOfFile { - t.Fatalf("FileStandardInfo unexpectedly had EndOfFile %d, expecting %d", current.EndOfFile, expected.EndOfFile) - } - - if current.NumberOfLinks != expected.NumberOfLinks { - t.Fatalf("FileStandardInfo unexpectedly had NumberOfLinks %d, expecting %d", current.NumberOfLinks, expected.NumberOfLinks) - } - - if current.DeletePending != expected.DeletePending { - if current.DeletePending { - t.Fatalf("FileStandardInfo unexpectedly DeletePending") - } else { - t.Fatalf("FileStandardInfo unexpectedly not DeletePending") - } - } - - if current.Directory != expected.Directory { - if current.Directory { - t.Fatalf("FileStandardInfo unexpectedly Directory") - } else { - t.Fatalf("FileStandardInfo unexpectedly not Directory") - } - } -} - -func TestGetFileStandardInfo_File(t *testing.T) { - f, err := ioutil.TempFile("", "tst") - if err != nil { - t.Fatal(err) - } - defer f.Close() - defer os.Remove(f.Name()) - - expectedFileInfo := &FileStandardInfo{ - AllocationSize: 0, - EndOfFile: 0, - NumberOfLinks: 1, - DeletePending: false, - Directory: false, - } - - info, err := GetFileStandardInfo(f) - if err != nil { - t.Fatal(err) - } - checkFileStandardInfo(t, info, expectedFileInfo) - - bytesWritten, err := f.Write([]byte("0123456789")) - if err != nil { - t.Fatal(err) - } - - expectedFileInfo.EndOfFile = int64(bytesWritten) - expectedFileInfo.AllocationSize = int64(bytesWritten) - - info, err = GetFileStandardInfo(f) - if err != nil { - t.Fatal(err) - } - checkFileStandardInfo(t, info, expectedFileInfo) - - linkName := f.Name() + ".link" - - if err = os.Link(f.Name(), linkName); err != nil { - t.Fatal(err) - } - defer os.Remove(linkName) - - expectedFileInfo.NumberOfLinks = 2 - - info, err = GetFileStandardInfo(f) - if err != nil { - t.Fatal(err) - } - checkFileStandardInfo(t, info, expectedFileInfo) - - os.Remove(linkName) - - expectedFileInfo.NumberOfLinks = 1 - - info, err = GetFileStandardInfo(f) - if err != nil { - t.Fatal(err) - } - checkFileStandardInfo(t, info, expectedFileInfo) -} - -func TestGetFileStandardInfo_Directory(t *testing.T) { - tempDir, err := ioutil.TempDir("", "tst") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - - // os.Open returns the Search Handle, not the Directory Handle - // See https://github.com/golang/go/issues/13738 - f, err := OpenForBackup(tempDir, windows.GENERIC_READ, 0, windows.OPEN_EXISTING) - if err != nil { - t.Fatal(err) - } - defer f.Close() - - expectedFileInfo := &FileStandardInfo{ - AllocationSize: 0, - EndOfFile: 0, - NumberOfLinks: 1, - DeletePending: false, - Directory: true, - } - - info, err := GetFileStandardInfo(f) - if err != nil { - t.Fatal(err) - } - checkFileStandardInfo(t, info, expectedFileInfo) -} From 085c1a94ab02c4635b3819f237d0e0a6eb459c87 Mon Sep 17 00:00:00 2001 From: Kathryn Baldauf Date: Wed, 21 Apr 2021 13:08:53 -0700 Subject: [PATCH 3/9] Add CI github action for testing on push and PR Signed-off-by: Kathryn Baldauf --- .github/workflows/ci.yml | 12 ++++++++ pkg/security/grantvmgroupaccess_test.go | 40 ++++++++++++++++--------- 2 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..7ed729c5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,12 @@ +name: CI +on: + - push + - pull_request + +jobs: + test: + runs-on: 'windows-2019' + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + - run: go test -gcflags=all=-d=checkptr -v ./... diff --git a/pkg/security/grantvmgroupaccess_test.go b/pkg/security/grantvmgroupaccess_test.go index 9d87eef1..2dffaa12 100644 --- a/pkg/security/grantvmgroupaccess_test.go +++ b/pkg/security/grantvmgroupaccess_test.go @@ -13,6 +13,11 @@ import ( exec "golang.org/x/sys/execabs" ) +const ( + vmAccountName = `NT VIRTUAL MACHINE\\Virtual Machines` + vmAccountSID = "S-1-5-83-0" +) + // TestGrantVmGroupAccess verifies for the three case of a file, a directory, // and a file in a directory that the appropriate ACEs are set, including // inheritance in the second two examples. These are the expected ACES. Is @@ -59,9 +64,9 @@ func TestGrantVmGroupAccess(t *testing.T) { t.Fatal(err) } - verifyicacls(t, + verifyVMAccountDACLs(t, f.Name(), - []string{`NT VIRTUAL MACHINE\\Virtual Machines:(R)`}, + []string{`(R)`}, ) // Two items here: @@ -74,19 +79,19 @@ func TestGrantVmGroupAccess(t *testing.T) { // // In properties for the directory, advanced security settings, this will // show as a single line "Allow/Virtual Machines/Read/Inherited from none/This folder, subfolder and files - verifyicacls(t, + verifyVMAccountDACLs(t, d, - []string{`NT VIRTUAL MACHINE\\Virtual Machines:(R)`, `NT VIRTUAL MACHINE\\Virtual Machines:(OI)(CI)(IO)(GR)`}, + []string{`(R)`, `(OI)(CI)(IO)(GR)`}, ) - verifyicacls(t, + verifyVMAccountDACLs(t, find.Name(), - []string{`NT VIRTUAL MACHINE\\Virtual Machines:(I)(R)`}, + []string{`(I)(R)`}, ) } -func verifyicacls(t *testing.T, name string, aces []string) { +func verifyVMAccountDACLs(t *testing.T, name string, permissions []string) { cmd := exec.Command("icacls", name) outb, err := cmd.CombinedOutput() if err != nil { @@ -94,15 +99,22 @@ func verifyicacls(t *testing.T, name string, aces []string) { } out := string(outb) - for _, ace := range aces { + for _, p := range permissions { // Avoid '(' and ')' being part of match groups - ace = strings.Replace(ace, "(", "\\(", -1) - ace = strings.Replace(ace, ")", "\\)", -1) + p = strings.Replace(p, "(", "\\(", -1) + p = strings.Replace(p, ")", "\\)", -1) + + nameToCheck := vmAccountName + ":" + p + sidToCheck := vmAccountSID + ":" + p + + rxName := regexp.MustCompile(nameToCheck) + rxSID := regexp.MustCompile(sidToCheck) + + matchesName := rxName.FindAllStringIndex(out, -1) + matchesSID := rxSID.FindAllStringIndex(out, -1) - rx := regexp.MustCompile(ace) - matches := rx.FindAllStringIndex(out, -1) - if len(matches) != 1 { - t.Fatalf("expected one match for %s got %d\n%s", ace, len(matches), out) + if len(matchesName) != 1 && len(matchesSID) != 1 { + t.Fatalf("expected one match for %s or %s\n%s", nameToCheck, sidToCheck, out) } } } From 090e4c6b27d46dd427cc00f12659fa329979599c Mon Sep 17 00:00:00 2001 From: Kathryn Baldauf Date: Wed, 21 Apr 2021 15:43:01 -0700 Subject: [PATCH 4/9] Add build status badge to readme Signed-off-by: Kathryn Baldauf --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56800105..60c93fe5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# go-winio +# go-winio [![Build Status](https://github.com/microsoft/go-winio/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/go-winio/actions/workflows/ci.yml) This repository contains utilities for efficiently performing Win32 IO operations in Go. Currently, this is focused on accessing named pipes and other file handles, and From 1358edb60703d9dd7f44b287e8c8c8aa708fecdc Mon Sep 17 00:00:00 2001 From: Daniel Canter Date: Wed, 21 Apr 2021 18:42:54 -0700 Subject: [PATCH 5/9] Build the three binaries in this repo from the ci Even though this repo is normally used as a dependency, there are some sample binaries and tools built out of here. This just makes sure they still build in the CI. Signed-off-by: Daniel Canter --- .github/workflows/ci.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ed729c5..4b24bde4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,24 @@ -name: CI +name: CI on: - push - pull_request -jobs: +jobs: test: runs-on: 'windows-2019' steps: - uses: actions/checkout@v2 - uses: actions/setup-go@v2 - run: go test -gcflags=all=-d=checkptr -v ./... + + build: + runs-on: 'windows-2019' + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: '^1.15.0' + + - run: go build ./pkg/etw/sample/ + - run: go build ./tools/etw-provider-gen/ + - run: go build ./wim/validate/ \ No newline at end of file From 8f0d50b3b381b741820d6737cfbda5b9284be616 Mon Sep 17 00:00:00 2001 From: Kathryn Baldauf Date: Thu, 22 Apr 2021 10:33:11 -0700 Subject: [PATCH 6/9] Revert "[Temporary] Revert Implement winio.GetFileStandardInfo FileInfo commits " --- backuptar/tar.go | 11 ++-- fileinfo.go | 36 ++++++++---- fileinfo_test.go | 134 ++++++++++++++++++++++++++++++++++++++++++++ zsyscall_windows.go | 18 ------ 4 files changed, 164 insertions(+), 35 deletions(-) create mode 100644 fileinfo_test.go diff --git a/backuptar/tar.go b/backuptar/tar.go index 088a43c6..cb461ca3 100644 --- a/backuptar/tar.go +++ b/backuptar/tar.go @@ -16,6 +16,7 @@ import ( "time" "github.com/Microsoft/go-winio" + "golang.org/x/sys/windows" ) const ( @@ -297,11 +298,11 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win size = hdr.Size } fileInfo = &winio.FileBasicInfo{ - LastAccessTime: syscall.NsecToFiletime(hdr.AccessTime.UnixNano()), - LastWriteTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()), - ChangeTime: syscall.NsecToFiletime(hdr.ChangeTime.UnixNano()), + LastAccessTime: windows.NsecToFiletime(hdr.AccessTime.UnixNano()), + LastWriteTime: windows.NsecToFiletime(hdr.ModTime.UnixNano()), + ChangeTime: windows.NsecToFiletime(hdr.ChangeTime.UnixNano()), // Default to ModTime, we'll pull hdrCreationTime below if present - CreationTime: syscall.NsecToFiletime(hdr.ModTime.UnixNano()), + CreationTime: windows.NsecToFiletime(hdr.ModTime.UnixNano()), } if attrStr, ok := hdr.PAXRecords[hdrFileAttributes]; ok { attr, err := strconv.ParseUint(attrStr, 10, 32) @@ -319,7 +320,7 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win if err != nil { return "", 0, nil, err } - fileInfo.CreationTime = syscall.NsecToFiletime(creationTime.UnixNano()) + fileInfo.CreationTime = windows.NsecToFiletime(creationTime.UnixNano()) } return } diff --git a/fileinfo.go b/fileinfo.go index ada2fbab..3ab6bff6 100644 --- a/fileinfo.go +++ b/fileinfo.go @@ -5,21 +5,14 @@ package winio import ( "os" "runtime" - "syscall" "unsafe" -) - -//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx -//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle -const ( - fileBasicInfo = 0 - fileIDInfo = 0x12 + "golang.org/x/sys/windows" ) // FileBasicInfo contains file access time and file attributes information. type FileBasicInfo struct { - CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime + CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime FileAttributes uint32 pad uint32 // padding } @@ -27,7 +20,7 @@ type FileBasicInfo struct { // GetFileBasicInfo retrieves times and attributes for a file. func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { bi := &FileBasicInfo{} - if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) @@ -36,13 +29,32 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { // SetFileBasicInfo sets times and attributes for a file. func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { - if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} } runtime.KeepAlive(f) return nil } +// FileStandardInfo contains extended information for the file. +// FILE_STANDARD_INFO in WinBase.h +// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info +type FileStandardInfo struct { + AllocationSize, EndOfFile int64 + NumberOfLinks uint32 + DeletePending, Directory bool +} + +// GetFileStandardInfo retrieves ended information for the file. +func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { + si := &FileStandardInfo{} + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil { + return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return si, nil +} + // FileIDInfo contains the volume serial number and file ID for a file. This pair should be // unique on a system. type FileIDInfo struct { @@ -53,7 +65,7 @@ type FileIDInfo struct { // GetFileID retrieves the unique (volume, file ID) pair for a file. func GetFileID(f *os.File) (*FileIDInfo, error) { fileID := &FileIDInfo{} - if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) diff --git a/fileinfo_test.go b/fileinfo_test.go new file mode 100644 index 00000000..e79700ba --- /dev/null +++ b/fileinfo_test.go @@ -0,0 +1,134 @@ +package winio + +import ( + "io/ioutil" + "os" + "testing" + + "golang.org/x/sys/windows" +) + +// Checks if current matches expected. Note that AllocationSize is filesystem-specific, +// so we check that the current.AllocationSize is >= expected.AllocationSize. +// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/5afa7f66-619c-48f3-955f-68c4ece704ae +func checkFileStandardInfo(t *testing.T, current, expected *FileStandardInfo) { + if current.AllocationSize < expected.AllocationSize { + t.Fatalf("FileStandardInfo unexpectedly had AllocationSize %d, expecting >=%d", current.AllocationSize, expected.AllocationSize) + } + + if current.EndOfFile != expected.EndOfFile { + t.Fatalf("FileStandardInfo unexpectedly had EndOfFile %d, expecting %d", current.EndOfFile, expected.EndOfFile) + } + + if current.NumberOfLinks != expected.NumberOfLinks { + t.Fatalf("FileStandardInfo unexpectedly had NumberOfLinks %d, expecting %d", current.NumberOfLinks, expected.NumberOfLinks) + } + + if current.DeletePending != expected.DeletePending { + if current.DeletePending { + t.Fatalf("FileStandardInfo unexpectedly DeletePending") + } else { + t.Fatalf("FileStandardInfo unexpectedly not DeletePending") + } + } + + if current.Directory != expected.Directory { + if current.Directory { + t.Fatalf("FileStandardInfo unexpectedly Directory") + } else { + t.Fatalf("FileStandardInfo unexpectedly not Directory") + } + } +} + +func TestGetFileStandardInfo_File(t *testing.T) { + f, err := ioutil.TempFile("", "tst") + if err != nil { + t.Fatal(err) + } + defer f.Close() + defer os.Remove(f.Name()) + + expectedFileInfo := &FileStandardInfo{ + AllocationSize: 0, + EndOfFile: 0, + NumberOfLinks: 1, + DeletePending: false, + Directory: false, + } + + info, err := GetFileStandardInfo(f) + if err != nil { + t.Fatal(err) + } + checkFileStandardInfo(t, info, expectedFileInfo) + + bytesWritten, err := f.Write([]byte("0123456789")) + if err != nil { + t.Fatal(err) + } + + expectedFileInfo.EndOfFile = int64(bytesWritten) + expectedFileInfo.AllocationSize = int64(bytesWritten) + + info, err = GetFileStandardInfo(f) + if err != nil { + t.Fatal(err) + } + checkFileStandardInfo(t, info, expectedFileInfo) + + linkName := f.Name() + ".link" + + if err = os.Link(f.Name(), linkName); err != nil { + t.Fatal(err) + } + defer os.Remove(linkName) + + expectedFileInfo.NumberOfLinks = 2 + + info, err = GetFileStandardInfo(f) + if err != nil { + t.Fatal(err) + } + checkFileStandardInfo(t, info, expectedFileInfo) + + os.Remove(linkName) + + expectedFileInfo.NumberOfLinks = 1 + + info, err = GetFileStandardInfo(f) + if err != nil { + t.Fatal(err) + } + checkFileStandardInfo(t, info, expectedFileInfo) +} + +func TestGetFileStandardInfo_Directory(t *testing.T) { + tempDir, err := ioutil.TempDir("", "tst") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tempDir) + + // os.Open returns the Search Handle, not the Directory Handle + // See https://github.com/golang/go/issues/13738 + f, err := OpenForBackup(tempDir, windows.GENERIC_READ, 0, windows.OPEN_EXISTING) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + expectedFileInfo := &FileStandardInfo{ + AllocationSize: 0, + EndOfFile: 0, + NumberOfLinks: 1, + DeletePending: false, + Directory: true, + } + + info, err := GetFileStandardInfo(f) + if err != nil { + t.Fatal(err) + } + checkFileStandardInfo(t, info, expectedFileInfo) +} diff --git a/zsyscall_windows.go b/zsyscall_windows.go index 4579c745..176ff75e 100644 --- a/zsyscall_windows.go +++ b/zsyscall_windows.go @@ -63,14 +63,12 @@ var ( procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") - procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") procLocalAlloc = modkernel32.NewProc("LocalAlloc") procLocalFree = modkernel32.NewProc("LocalFree") procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") @@ -339,14 +337,6 @@ func getCurrentThread() (h syscall.Handle) { return } -func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) if r1 == 0 { @@ -390,14 +380,6 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro return } -func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) status = ntstatus(r0) From 323bd13f37c66d0fdcb1587a8f86c215eeb951b5 Mon Sep 17 00:00:00 2001 From: "Paul \"TBBle\" Hampson" Date: Wed, 21 Apr 2021 21:31:48 +1000 Subject: [PATCH 7/9] Pull golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 Specifically, this pulls the fix for https://github.com/golang/go/issues/44538 as we're going to start using this API in place of our own generated wrapper. Signed-off-by: Paul "TBBle" Hampson --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 98a8dea0..55d2c581 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,5 @@ go 1.12 require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.7.0 - golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c + golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 ) diff --git a/go.sum b/go.sum index aa6ad3b5..8a47c7ad 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,6 @@ github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988 h1:EjgCl+fVlIaPJSori0ikSz3uV0DOHKWOJFpv1sAAhBM= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 3415dd22982570e2811012e708b421123f7ec405 Mon Sep 17 00:00:00 2001 From: "Paul \"TBBle\" Hampson" Date: Wed, 6 Jan 2021 02:26:03 +1100 Subject: [PATCH 8/9] Use x/sys/windows for all windows constants This replaces the use of either syscall or hard-coded magic numbers. Signed-off-by: Paul "TBBle" Hampson --- backup.go | 10 ++++++---- backuptar/tar.go | 5 ++--- file.go | 16 +++++++++------- hvsock.go | 9 +++++---- pipe.go | 22 ++++++++++++---------- pipe_test.go | 6 ++++-- pkg/security/grantvmgroupaccess.go | 7 ++++--- privilege.go | 7 +++---- reparse.go | 6 ++++-- sd.go | 6 ++++-- 10 files changed, 53 insertions(+), 41 deletions(-) diff --git a/backup.go b/backup.go index 2be34af4..5ba4f236 100644 --- a/backup.go +++ b/backup.go @@ -12,6 +12,8 @@ import ( "runtime" "syscall" "unicode/utf16" + + "golang.org/x/sys/windows" ) //sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead @@ -35,9 +37,9 @@ const ( ) const ( - WRITE_DAC = 0x40000 - WRITE_OWNER = 0x80000 - ACCESS_SYSTEM_SECURITY = 0x1000000 + WRITE_DAC = windows.WRITE_DAC + WRITE_OWNER = windows.WRITE_OWNER + ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY ) // BackupHeader represents a backup stream of a file. @@ -271,7 +273,7 @@ func OpenForBackup(path string, access uint32, share uint32, createmode uint32) if err != nil { return nil, err } - h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0) + h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_OPEN_REPARSE_POINT, 0) if err != nil { err = &os.PathError{Op: "open", Path: path, Err: err} return nil, err diff --git a/backuptar/tar.go b/backuptar/tar.go index cb461ca3..80339333 100644 --- a/backuptar/tar.go +++ b/backuptar/tar.go @@ -12,7 +12,6 @@ import ( "path/filepath" "strconv" "strings" - "syscall" "time" "github.com/Microsoft/go-winio" @@ -101,7 +100,7 @@ func BasicInfoHeader(name string, size int64, fileInfo *winio.FileBasicInfo) *ta hdr.PAXRecords[hdrFileAttributes] = fmt.Sprintf("%d", fileInfo.FileAttributes) hdr.PAXRecords[hdrCreationTime] = formatPAXTime(time.Unix(0, fileInfo.CreationTime.Nanoseconds())) - if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { + if (fileInfo.FileAttributes & windows.FILE_ATTRIBUTE_DIRECTORY) != 0 { hdr.Mode |= c_ISDIR hdr.Size = 0 hdr.Typeflag = tar.TypeDir @@ -312,7 +311,7 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win fileInfo.FileAttributes = uint32(attr) } else { if hdr.Typeflag == tar.TypeDir { - fileInfo.FileAttributes |= syscall.FILE_ATTRIBUTE_DIRECTORY + fileInfo.FileAttributes |= windows.FILE_ATTRIBUTE_DIRECTORY } } if creationTimeStr, ok := hdr.PAXRecords[hdrCreationTime]; ok { diff --git a/file.go b/file.go index 0385e410..630c5fbf 100644 --- a/file.go +++ b/file.go @@ -10,6 +10,8 @@ import ( "sync/atomic" "syscall" "time" + + "golang.org/x/sys/windows" ) //sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx @@ -32,8 +34,8 @@ func (b *atomicBool) swap(new bool) bool { } const ( - cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 - cFILE_SKIP_SET_EVENT_ON_HANDLE = 2 + cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS + cFILE_SKIP_SET_EVENT_ON_HANDLE = windows.FILE_SKIP_SET_EVENT_ON_HANDLE ) var ( @@ -164,7 +166,7 @@ func ioCompletionProcessor(h syscall.Handle) { var bytes uint32 var key uintptr var op *ioOperation - err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE) + err := getQueuedCompletionStatus(h, &bytes, &key, &op, windows.INFINITE) if op == nil { panic(err) } @@ -175,7 +177,7 @@ func ioCompletionProcessor(h syscall.Handle) { // asyncIo processes the return value from ReadFile or WriteFile, blocking until // the operation has actually completed. func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { - if err != syscall.ERROR_IO_PENDING { + if err != windows.ERROR_IO_PENDING { return int(bytes), err } @@ -194,7 +196,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er select { case r = <-c.ch: err = r.err - if err == syscall.ERROR_OPERATION_ABORTED { + if err == windows.ERROR_OPERATION_ABORTED { if f.closing.isSet() { err = ErrFileClosed } @@ -207,7 +209,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er cancelIoEx(f.handle, &c.o) r = <-c.ch err = r.err - if err == syscall.ERROR_OPERATION_ABORTED { + if err == windows.ERROR_OPERATION_ABORTED { err = ErrTimeout } } @@ -239,7 +241,7 @@ func (f *win32File) Read(b []byte) (int, error) { // Handle EOF conditions. if err == nil && n == 0 && len(b) != 0 { return 0, io.EOF - } else if err == syscall.ERROR_BROKEN_PIPE { + } else if err == windows.ERROR_BROKEN_PIPE { return 0, io.EOF } else { return n, err diff --git a/hvsock.go b/hvsock.go index b632f8f8..2b0c9b43 100644 --- a/hvsock.go +++ b/hvsock.go @@ -12,6 +12,7 @@ import ( "unsafe" "github.com/Microsoft/go-winio/pkg/guid" + "golang.org/x/sys/windows" ) //sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind @@ -77,7 +78,7 @@ type HvsockConn struct { } func newHvSocket() (*win32File, error) { - fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1) + fd, err := syscall.Socket(afHvSock, windows.SOCK_STREAM, 1) if err != nil { return nil, os.NewSyscallError("socket", err) } @@ -253,7 +254,7 @@ func (conn *HvsockConn) Close() error { } func (conn *HvsockConn) shutdown(how int) error { - err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) + err := syscall.Shutdown(conn.sock.handle, windows.SHUT_RD) if err != nil { return os.NewSyscallError("shutdown", err) } @@ -262,7 +263,7 @@ func (conn *HvsockConn) shutdown(how int) error { // CloseRead shuts down the read end of the socket. func (conn *HvsockConn) CloseRead() error { - err := conn.shutdown(syscall.SHUT_RD) + err := conn.shutdown(windows.SHUT_RD) if err != nil { return conn.opErr("close", err) } @@ -272,7 +273,7 @@ func (conn *HvsockConn) CloseRead() error { // CloseWrite shuts down the write end of the socket, notifying the other endpoint that // no more data will be written. func (conn *HvsockConn) CloseWrite() error { - err := conn.shutdown(syscall.SHUT_WR) + err := conn.shutdown(windows.SHUT_WR) if err != nil { return conn.opErr("close", err) } diff --git a/pipe.go b/pipe.go index 96700a73..8df3e9e2 100644 --- a/pipe.go +++ b/pipe.go @@ -13,6 +13,8 @@ import ( "syscall" "time" "unsafe" + + "golang.org/x/sys/windows" ) //sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe @@ -65,10 +67,10 @@ func (status ntstatus) Err() error { } const ( - cERROR_PIPE_BUSY = syscall.Errno(231) - cERROR_NO_DATA = syscall.Errno(232) - cERROR_PIPE_CONNECTED = syscall.Errno(535) - cERROR_SEM_TIMEOUT = syscall.Errno(121) + cERROR_PIPE_BUSY = windows.ERROR_PIPE_BUSY + cERROR_NO_DATA = windows.ERROR_NO_DATA + cERROR_PIPE_CONNECTED = windows.ERROR_PIPE_CONNECTED + cERROR_SEM_TIMEOUT = windows.ERROR_SEM_TIMEOUT cSECURITY_SQOS_PRESENT = 0x100000 cSECURITY_ANONYMOUS = 0 @@ -164,7 +166,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) { // zero-byte message, ensure that all future Read() calls // also return EOF. f.readEOF = true - } else if err == syscall.ERROR_MORE_DATA { + } else if err == windows.ERROR_MORE_DATA { // ERROR_MORE_DATA indicates that the pipe's read mode is message mode // and the message still has more bytes. Treat this as a success, since // this package presents all named pipes as byte streams. @@ -189,7 +191,7 @@ func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Hand case <-ctx.Done(): return syscall.Handle(0), ctx.Err() default: - h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) + h, err := createFile(*path, access, 0, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) if err == nil { return h, nil } @@ -224,7 +226,7 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { // DialPipeContext attempts to connect to a named pipe by `path` until `ctx` // cancellation or timeout. func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { - return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE) + return DialPipeAccess(ctx, path, windows.GENERIC_READ|windows.GENERIC_WRITE) } // DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx` @@ -320,13 +322,13 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy } disposition := uint32(cFILE_OPEN) - access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE) + access := uint32(windows.GENERIC_READ | windows.GENERIC_WRITE | windows.SYNCHRONIZE) if first { disposition = cFILE_CREATE // By not asking for read or write access, the named pipe file system // will put this pipe into an initially disconnected state, blocking // client connections until the next call with first == false. - access = syscall.SYNCHRONIZE + access = windows.SYNCHRONIZE } timeout := int64(-50 * 10000) // 50ms @@ -335,7 +337,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy h syscall.Handle iosb ioStatusBlock ) - err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() + err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() if err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } diff --git a/pipe_test.go b/pipe_test.go index a4ddea59..fc940c01 100644 --- a/pipe_test.go +++ b/pipe_test.go @@ -14,6 +14,8 @@ import ( "testing" "time" "unsafe" + + "golang.org/x/sys/windows" ) var testPipeName = `\\.\pipe\winiotestpipe` @@ -22,7 +24,7 @@ var aLongTimeAgo = time.Unix(1, 0) func TestDialUnknownFailsImmediately(t *testing.T) { _, err := DialPipe(testPipeName, nil) - if err.(*os.PathError).Err != syscall.ENOENT { + if err.(*os.PathError).Err != windows.ERROR_FILE_NOT_FOUND { t.Fatalf("expected ENOENT got %v", err) } } @@ -84,7 +86,7 @@ func TestDialAccessDeniedWithRestrictedSD(t *testing.T) { } defer l.Close() _, err = DialPipe(testPipeName, nil) - if err.(*os.PathError).Err != syscall.ERROR_ACCESS_DENIED { + if err.(*os.PathError).Err != windows.ERROR_ACCESS_DENIED { t.Fatalf("expected ERROR_ACCESS_DENIED, got %v", err) } } diff --git a/pkg/security/grantvmgroupaccess.go b/pkg/security/grantvmgroupaccess.go index fca24159..79de86fc 100644 --- a/pkg/security/grantvmgroupaccess.go +++ b/pkg/security/grantvmgroupaccess.go @@ -8,6 +8,7 @@ import ( "unsafe" "github.com/pkg/errors" + "golang.org/x/sys/windows" ) type ( @@ -114,11 +115,11 @@ func createFile(name string, isDir bool) (syscall.Handle, error) { namep := syscall.StringToUTF16(name) da := uint32(desiredAccessReadControl | desiredAccessWriteDac) sm := uint32(shareModeRead | shareModeWrite) - fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL) + fa := uint32(windows.FILE_ATTRIBUTE_NORMAL) if isDir { - fa = uint32(fa | syscall.FILE_FLAG_BACKUP_SEMANTICS) + fa = uint32(fa | windows.FILE_FLAG_BACKUP_SEMANTICS) } - fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0) + fd, err := syscall.CreateFile(&namep[0], da, sm, nil, windows.OPEN_EXISTING, fa, 0) if err != nil { return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name) } diff --git a/privilege.go b/privilege.go index c3dd7c21..b77d717c 100644 --- a/privilege.go +++ b/privilege.go @@ -8,7 +8,6 @@ import ( "fmt" "runtime" "sync" - "syscall" "unicode/utf16" "golang.org/x/sys/windows" @@ -24,9 +23,9 @@ import ( //sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW const ( - SE_PRIVILEGE_ENABLED = 2 + SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED - ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 + ERROR_NOT_ALL_ASSIGNED = windows.ERROR_NOT_ALL_ASSIGNED SeBackupPrivilege = "SeBackupPrivilege" SeRestorePrivilege = "SeRestorePrivilege" @@ -183,7 +182,7 @@ func newThreadToken() (windows.Token, error) { } var token windows.Token - err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token) + err = openThreadToken(getCurrentThread(), windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, false, &token) if err != nil { rerr := revertToSelf() if rerr != nil { diff --git a/reparse.go b/reparse.go index fc1ee4d3..ee49e980 100644 --- a/reparse.go +++ b/reparse.go @@ -7,11 +7,13 @@ import ( "strings" "unicode/utf16" "unsafe" + + "golang.org/x/sys/windows" ) const ( - reparseTagMountPoint = 0xA0000003 - reparseTagSymlink = 0xA000000C + reparseTagMountPoint = windows.IO_REPARSE_TAG_MOUNT_POINT + reparseTagSymlink = windows.IO_REPARSE_TAG_SYMLINK ) type reparseDataBuffer struct { diff --git a/sd.go b/sd.go index db1b370a..7b53f4cd 100644 --- a/sd.go +++ b/sd.go @@ -5,6 +5,8 @@ package winio import ( "syscall" "unsafe" + + "golang.org/x/sys/windows" ) //sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW @@ -15,7 +17,7 @@ import ( //sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength const ( - cERROR_NONE_MAPPED = syscall.Errno(1332) + cERROR_NONE_MAPPED = windows.ERROR_NONE_MAPPED ) type AccountLookupError struct { @@ -54,7 +56,7 @@ func LookupSidByName(name string) (sid string, err error) { var sidSize, sidNameUse, refDomainSize uint32 err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) - if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { + if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { return "", &AccountLookupError{name, err} } sidBuffer := make([]byte, sidSize) From 5188886a6381c8559d96c7754eb38d60d44665b8 Mon Sep 17 00:00:00 2001 From: "Paul \"TBBle\" Hampson" Date: Wed, 6 Jan 2021 02:57:08 +1100 Subject: [PATCH 9/9] Flip Handle from syscall to windows, and everything changes syscall.Handle is core to a _lot_ of structures and APIs, so this great-big commit contains the entire rest of the conversion from syscall to x/sys/windows. I also eliminated a bunch of generated syscall wrappers which had _direct_ equivalents in x/sys/windows. There's still a bunch which exist in x/sys/windows and either have worse implementations, e.g. windows.CreateFile, or somehow expose different APIs, e.g. the calls used by privileges.go Signed-off-by: Paul "TBBle" Hampson --- backup.go | 19 +++-- backup_test.go | 5 +- ea_test.go | 5 +- file.go | 44 +++++------ hvsock.go | 25 +++--- pipe.go | 38 +++++---- pipe_test.go | 3 +- pkg/etw/eventdata.go | 5 +- pkg/etw/fieldopt.go | 5 +- pkg/security/grantvmgroupaccess.go | 19 +++-- pkg/security/syscall_windows.go | 4 +- pkg/security/zsyscall_windows.go | 4 +- privilege.go | 13 ++-- sd.go | 12 ++- vhd/vhd.go | 35 ++++----- vhd/zvhd_windows.go | 14 ++-- zsyscall_windows.go | 121 ++++------------------------- 17 files changed, 134 insertions(+), 237 deletions(-) diff --git a/backup.go b/backup.go index 5ba4f236..a5bbc82b 100644 --- a/backup.go +++ b/backup.go @@ -10,14 +10,13 @@ import ( "io/ioutil" "os" "runtime" - "syscall" "unicode/utf16" "golang.org/x/sys/windows" ) -//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead -//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite +//sys backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead +//sys backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite const ( BackupData = uint32(iota + 1) @@ -102,7 +101,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) { if err := binary.Read(r.r, binary.LittleEndian, name); err != nil { return nil, err } - hdr.Name = syscall.UTF16ToString(name) + hdr.Name = windows.UTF16ToString(name) } if wsi.StreamId == BackupSparseBlock { if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil { @@ -203,7 +202,7 @@ func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader { // Read reads a backup stream from the file by calling the Win32 API BackupRead(). func (r *BackupFileReader) Read(b []byte) (int, error) { var bytesRead uint32 - err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) + err := backupRead(windows.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) if err != nil { return 0, &os.PathError{"BackupRead", r.f.Name(), err} } @@ -218,7 +217,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { // the underlying file. func (r *BackupFileReader) Close() error { if r.ctx != 0 { - backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) + backupRead(windows.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) runtime.KeepAlive(r.f) r.ctx = 0 } @@ -242,7 +241,7 @@ func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter { // Write restores a portion of the file using the provided backup stream. func (w *BackupFileWriter) Write(b []byte) (int, error) { var bytesWritten uint32 - err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) + err := backupWrite(windows.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) if err != nil { return 0, &os.PathError{"BackupWrite", w.f.Name(), err} } @@ -257,7 +256,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { // close the underlying file. func (w *BackupFileWriter) Close() error { if w.ctx != 0 { - backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) + backupWrite(windows.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) runtime.KeepAlive(w.f) w.ctx = 0 } @@ -269,11 +268,11 @@ func (w *BackupFileWriter) Close() error { // // If the file opened was a directory, it cannot be used with Readdir(). func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) { - winPath, err := syscall.UTF16FromString(path) + winPath, err := windows.UTF16FromString(path) if err != nil { return nil, err } - h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_OPEN_REPARSE_POINT, 0) + h, err := windows.CreateFile(&winPath[0], access, share, nil, createmode, windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_OPEN_REPARSE_POINT, 0) if err != nil { err = &os.PathError{Op: "open", Path: path, Err: err} return nil, err diff --git a/backup_test.go b/backup_test.go index 0522a127..e02714ea 100644 --- a/backup_test.go +++ b/backup_test.go @@ -6,8 +6,9 @@ import ( "io" "io/ioutil" "os" - "syscall" "testing" + + "golang.org/x/sys/windows" ) var testFileName string @@ -205,7 +206,7 @@ func makeSparseFile() error { FSCTL_SET_ZERO_DATA = 0x000980c8 ) - err = syscall.DeviceIoControl(syscall.Handle(f.Fd()), FSCTL_SET_SPARSE, nil, 0, nil, 0, nil, nil) + err = windows.DeviceIoControl(windows.Handle(f.Fd()), FSCTL_SET_SPARSE, nil, 0, nil, 0, nil, nil) if err != nil { return err } diff --git a/ea_test.go b/ea_test.go index 1d2abd79..b55951f7 100644 --- a/ea_test.go +++ b/ea_test.go @@ -6,9 +6,10 @@ import ( "io/ioutil" "os" "reflect" - "syscall" "testing" "unsafe" + + "golang.org/x/sys/windows" ) var ( @@ -81,7 +82,7 @@ func Test_SetFileEa(t *testing.T) { } defer os.Remove(f.Name()) defer f.Close() - ntdll := syscall.MustLoadDLL("ntdll.dll") + ntdll := windows.MustLoadDLL("ntdll.dll") ntSetEaFile := ntdll.MustFindProc("NtSetEaFile") var iosb [2]uintptr r, _, _ := ntSetEaFile.Call(f.Fd(), uintptr(unsafe.Pointer(&iosb[0])), uintptr(unsafe.Pointer(&testEasEncoded[0])), uintptr(len(testEasEncoded))) diff --git a/file.go b/file.go index 630c5fbf..c5210ead 100644 --- a/file.go +++ b/file.go @@ -8,17 +8,13 @@ import ( "runtime" "sync" "sync/atomic" - "syscall" "time" + "unsafe" "golang.org/x/sys/windows" ) -//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx -//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort -//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus -//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes -//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult +//sys wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult type atomicBool int32 @@ -52,7 +48,7 @@ func (e *timeoutError) Temporary() bool { return true } type timeoutChan chan struct{} var ioInitOnce sync.Once -var ioCompletionPort syscall.Handle +var ioCompletionPort windows.Handle // ioResult contains the result of an asynchronous IO operation type ioResult struct { @@ -62,12 +58,12 @@ type ioResult struct { // ioOperation represents an outstanding asynchronous Win32 IO type ioOperation struct { - o syscall.Overlapped + o windows.Overlapped ch chan ioResult } func initIo() { - h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) + h, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0xffffffff) if err != nil { panic(err) } @@ -78,7 +74,7 @@ func initIo() { // win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall. // It takes ownership of this handle and will close it if it is garbage collected. type win32File struct { - handle syscall.Handle + handle windows.Handle wg sync.WaitGroup wgLock sync.RWMutex closing atomicBool @@ -96,14 +92,14 @@ type deadlineHandler struct { } // makeWin32File makes a new win32File from an existing file handle -func makeWin32File(h syscall.Handle) (*win32File, error) { +func makeWin32File(h windows.Handle) (*win32File, error) { f := &win32File{handle: h} ioInitOnce.Do(initIo) - _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) + _, err := windows.CreateIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) if err != nil { return nil, err } - err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) + err = windows.SetFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) if err != nil { return nil, err } @@ -112,7 +108,7 @@ func makeWin32File(h syscall.Handle) (*win32File, error) { return f, nil } -func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { +func MakeOpenFile(h windows.Handle) (io.ReadWriteCloser, error) { // If we return the result of makeWin32File directly, it can result in an // interface-wrapped nil, rather than a nil interface value. f, err := makeWin32File(h) @@ -129,10 +125,10 @@ func (f *win32File) closeHandle() { if !f.closing.swap(true) { f.wgLock.Unlock() // cancel all IO and wait for it to complete - cancelIoEx(f.handle, nil) + windows.CancelIoEx(f.handle, nil) f.wg.Wait() // at this point, no new IO can start - syscall.Close(f.handle) + windows.Close(f.handle) f.handle = 0 } else { f.wgLock.Unlock() @@ -161,12 +157,14 @@ func (f *win32File) prepareIo() (*ioOperation, error) { } // ioCompletionProcessor processes completed async IOs forever -func ioCompletionProcessor(h syscall.Handle) { +func ioCompletionProcessor(h windows.Handle) { for { var bytes uint32 var key uintptr var op *ioOperation - err := getQueuedCompletionStatus(h, &bytes, &key, &op, windows.INFINITE) + // Safe: windows.Overlapped is the leading member of ioOperation + opPtr := (**windows.Overlapped)(unsafe.Pointer(&op)) + err := windows.GetQueuedCompletionStatus(h, &bytes, &key, opPtr, windows.INFINITE) if op == nil { panic(err) } @@ -182,7 +180,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er } if f.closing.isSet() { - cancelIoEx(f.handle, &c.o) + windows.CancelIoEx(f.handle, &c.o) } var timeout timeoutChan @@ -206,7 +204,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags) } case <-timeout: - cancelIoEx(f.handle, &c.o) + windows.CancelIoEx(f.handle, &c.o) r = <-c.ch err = r.err if err == windows.ERROR_OPERATION_ABORTED { @@ -234,7 +232,7 @@ func (f *win32File) Read(b []byte) (int, error) { } var bytes uint32 - err = syscall.ReadFile(f.handle, b, &bytes, &c.o) + err = windows.ReadFile(f.handle, b, &bytes, &c.o) n, err := f.asyncIo(c, &f.readDeadline, bytes, err) runtime.KeepAlive(b) @@ -261,7 +259,7 @@ func (f *win32File) Write(b []byte) (int, error) { } var bytes uint32 - err = syscall.WriteFile(f.handle, b, &bytes, &c.o) + err = windows.WriteFile(f.handle, b, &bytes, &c.o) n, err := f.asyncIo(c, &f.writeDeadline, bytes, err) runtime.KeepAlive(b) return n, err @@ -276,7 +274,7 @@ func (f *win32File) SetWriteDeadline(deadline time.Time) error { } func (f *win32File) Flush() error { - return syscall.FlushFileBuffers(f.handle) + return windows.FlushFileBuffers(f.handle) } func (f *win32File) Fd() uintptr { diff --git a/hvsock.go b/hvsock.go index 2b0c9b43..fc6c4844 100644 --- a/hvsock.go +++ b/hvsock.go @@ -7,7 +7,6 @@ import ( "io" "net" "os" - "syscall" "time" "unsafe" @@ -15,7 +14,7 @@ import ( "golang.org/x/sys/windows" ) -//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind +//sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind const ( afHvSock = 34 // AF_HYPERV @@ -78,13 +77,13 @@ type HvsockConn struct { } func newHvSocket() (*win32File, error) { - fd, err := syscall.Socket(afHvSock, windows.SOCK_STREAM, 1) + fd, err := windows.Socket(afHvSock, windows.SOCK_STREAM, 1) if err != nil { return nil, os.NewSyscallError("socket", err) } f, err := makeWin32File(fd) if err != nil { - syscall.Close(fd) + windows.Close(fd) return nil, err } f.socket = true @@ -103,7 +102,7 @@ func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { if err != nil { return nil, l.opErr("listen", os.NewSyscallError("socket", err)) } - err = syscall.Listen(sock.handle, 16) + err = windows.Listen(sock.handle, 16) if err != nil { return nil, l.opErr("listen", os.NewSyscallError("listen", err)) } @@ -141,7 +140,7 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) { var addrbuf [addrlen * 2]byte var bytes uint32 - err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o) + err = windows.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o) _, err = l.sock.asyncIo(c, nil, bytes, err) if err != nil { return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) @@ -201,12 +200,12 @@ func (conn *HvsockConn) Read(b []byte) (int, error) { return 0, conn.opErr("read", err) } defer conn.sock.wg.Done() - buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))} var flags, bytes uint32 - err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) + err = windows.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err) if err != nil { - if _, ok := err.(syscall.Errno); ok { + if _, ok := err.(windows.Errno); ok { err = os.NewSyscallError("wsarecv", err) } return 0, conn.opErr("read", err) @@ -235,12 +234,12 @@ func (conn *HvsockConn) write(b []byte) (int, error) { return 0, conn.opErr("write", err) } defer conn.sock.wg.Done() - buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))} var bytes uint32 - err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) + err = windows.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err) if err != nil { - if _, ok := err.(syscall.Errno); ok { + if _, ok := err.(windows.Errno); ok { err = os.NewSyscallError("wsasend", err) } return 0, conn.opErr("write", err) @@ -254,7 +253,7 @@ func (conn *HvsockConn) Close() error { } func (conn *HvsockConn) shutdown(how int) error { - err := syscall.Shutdown(conn.sock.handle, windows.SHUT_RD) + err := windows.Shutdown(conn.sock.handle, windows.SHUT_RD) if err != nil { return os.NewSyscallError("shutdown", err) } diff --git a/pipe.go b/pipe.go index 8df3e9e2..4571fb11 100644 --- a/pipe.go +++ b/pipe.go @@ -10,20 +10,18 @@ import ( "net" "os" "runtime" - "syscall" "time" "unsafe" "golang.org/x/sys/windows" ) -//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe -//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW -//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW -//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo -//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW +//sys connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) = ConnectNamedPipe +//sys createFile(name string, access uint32, mode uint32, sa *windows.SecurityAttributes, createmode uint32, attrs uint32, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW +//sys getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo +//sys getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW //sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc -//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile +//sys ntCreateNamedPipeFile(pipe *windows.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile //sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb //sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U //sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl @@ -184,12 +182,12 @@ func (s pipeAddress) String() string { } // tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout. -func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) { +func tryDialPipe(ctx context.Context, path *string, access uint32) (windows.Handle, error) { for { select { case <-ctx.Done(): - return syscall.Handle(0), ctx.Err() + return windows.Handle(0), ctx.Err() default: h, err := createFile(*path, access, 0, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) if err == nil { @@ -233,7 +231,7 @@ func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { // cancellation or timeout. func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) { var err error - var h syscall.Handle + var h windows.Handle h, err = tryDialPipe(ctx, &path, access) if err != nil { return nil, err @@ -247,7 +245,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, f, err := makeWin32File(h) if err != nil { - syscall.Close(h) + windows.Close(h) return nil, err } @@ -267,7 +265,7 @@ type acceptResponse struct { } type win32PipeListener struct { - firstHandle syscall.Handle + firstHandle windows.Handle path string config PipeConfig acceptCh chan (chan acceptResponse) @@ -275,8 +273,8 @@ type win32PipeListener struct { doneCh chan int } -func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) { - path16, err := syscall.UTF16FromString(path) +func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (windows.Handle, error) { + path16, err := windows.UTF16FromString(path) if err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } @@ -288,7 +286,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } - defer localFree(ntPath.Buffer) + defer windows.LocalFree((windows.Handle)(unsafe.Pointer(ntPath.Buffer))) oa.ObjectName = &ntPath // The security descriptor is only needed for the first pipe. @@ -296,7 +294,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy if sd != nil { len := uint32(len(sd)) sdb := localAlloc(0, len) - defer localFree(sdb) + defer windows.LocalFree((windows.Handle)(unsafe.Pointer(sdb))) copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) } else { @@ -305,7 +303,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { return 0, fmt.Errorf("getting default named pipe ACL: %s", err) } - defer localFree(dacl) + defer windows.LocalFree((windows.Handle)(unsafe.Pointer(dacl))) sdb := &securityDescriptor{ Revision: 1, @@ -334,7 +332,7 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy timeout := int64(-50 * 10000) // 50ms var ( - h syscall.Handle + h windows.Handle iosb ioStatusBlock ) err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() @@ -353,7 +351,7 @@ func (l *win32PipeListener) makeServerPipe() (*win32File, error) { } f, err := makeWin32File(h) if err != nil { - syscall.Close(h) + windows.Close(h) return nil, err } return f, nil @@ -412,7 +410,7 @@ func (l *win32PipeListener) listenerRoutine() { closed = err == ErrPipeListenerClosed } } - syscall.Close(l.firstHandle) + windows.Close(l.firstHandle) l.firstHandle = 0 // Notify Close() and Accept() callers that the handle has been closed. close(l.doneCh) diff --git a/pipe_test.go b/pipe_test.go index fc940c01..feceea38 100644 --- a/pipe_test.go +++ b/pipe_test.go @@ -10,7 +10,6 @@ import ( "net" "os" "sync" - "syscall" "testing" "time" "unsafe" @@ -526,7 +525,7 @@ func TestMessageReadMode(t *testing.T) { } defer c.Close() - setNamedPipeHandleState := syscall.NewLazyDLL("kernel32.dll").NewProc("SetNamedPipeHandleState") + setNamedPipeHandleState := windows.NewLazyDLL("kernel32.dll").NewProc("SetNamedPipeHandleState") p := c.(*win32MessageBytePipe) mode := uint32(cPIPE_READMODE_MESSAGE) diff --git a/pkg/etw/eventdata.go b/pkg/etw/eventdata.go index abf16803..dc2d0792 100644 --- a/pkg/etw/eventdata.go +++ b/pkg/etw/eventdata.go @@ -5,7 +5,8 @@ package etw import ( "bytes" "encoding/binary" - "syscall" + + "golang.org/x/sys/windows" ) // eventData maintains a buffer which builds up the data for an ETW event. It @@ -68,6 +69,6 @@ func (ed *eventData) writeUint64(value uint64) { } // writeFiletime appends a FILETIME to the buffer. -func (ed *eventData) writeFiletime(value syscall.Filetime) { +func (ed *eventData) writeFiletime(value windows.Filetime) { binary.Write(&ed.buffer, binary.LittleEndian, value) } diff --git a/pkg/etw/fieldopt.go b/pkg/etw/fieldopt.go index b5ea80a4..db4beeab 100644 --- a/pkg/etw/fieldopt.go +++ b/pkg/etw/fieldopt.go @@ -6,9 +6,10 @@ import ( "fmt" "math" "reflect" - "syscall" "time" "unsafe" + + "golang.org/x/sys/windows" ) // FieldOpt defines the option function type that can be passed to @@ -388,7 +389,7 @@ func Struct(name string, opts ...FieldOpt) FieldOpt { func Time(name string, value time.Time) FieldOpt { return func(em *eventMetadata, ed *eventData) { em.writeField(name, inTypeFileTime, outTypeDateTimeUTC, 0) - ed.writeFiletime(syscall.NsecToFiletime(value.UTC().UnixNano())) + ed.writeFiletime(windows.NsecToFiletime(value.UTC().UnixNano())) } } diff --git a/pkg/security/grantvmgroupaccess.go b/pkg/security/grantvmgroupaccess.go index 79de86fc..823f223a 100644 --- a/pkg/security/grantvmgroupaccess.go +++ b/pkg/security/grantvmgroupaccess.go @@ -4,7 +4,6 @@ package security import ( "os" - "syscall" "unsafe" "github.com/pkg/errors" @@ -81,7 +80,7 @@ func GrantVmGroupAccess(name string) error { if err != nil { return err // Already wrapped } - defer syscall.CloseHandle(fd) + defer windows.CloseHandle(fd) // Get the current DACL and Security Descriptor. Must defer LocalFree on success. ot := objectTypeFileObject @@ -91,7 +90,7 @@ func GrantVmGroupAccess(name string) error { if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil { return errors.Wrapf(err, "%s GetSecurityInfo %s", gvmga, name) } - defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) + defer windows.LocalFree((windows.Handle)(unsafe.Pointer(sd))) // Generate a new DACL which is the current DACL with the required ACEs added. // Must defer LocalFree on success. @@ -99,7 +98,7 @@ func GrantVmGroupAccess(name string) error { if err != nil { return err // Already wrapped } - defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL))) + defer windows.LocalFree((windows.Handle)(unsafe.Pointer(newDACL))) // And finally use SetSecurityInfo to apply the updated DACL. if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil { @@ -111,17 +110,17 @@ func GrantVmGroupAccess(name string) error { // createFile is a helper function to call [Nt]CreateFile to get a handle to // the file or directory. -func createFile(name string, isDir bool) (syscall.Handle, error) { - namep := syscall.StringToUTF16(name) +func createFile(name string, isDir bool) (windows.Handle, error) { + namep := windows.StringToUTF16(name) da := uint32(desiredAccessReadControl | desiredAccessWriteDac) sm := uint32(shareModeRead | shareModeWrite) fa := uint32(windows.FILE_ATTRIBUTE_NORMAL) if isDir { fa = uint32(fa | windows.FILE_FLAG_BACKUP_SEMANTICS) } - fd, err := syscall.CreateFile(&namep[0], da, sm, nil, windows.OPEN_EXISTING, fa, 0) + fd, err := windows.CreateFile(&namep[0], da, sm, nil, windows.OPEN_EXISTING, fa, 0) if err != nil { - return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name) + return 0, errors.Wrapf(err, "%s windows.CreateFile %s", gvmga, name) } return fd, nil } @@ -130,9 +129,9 @@ func createFile(name string, isDir bool) (syscall.Handle, error) { // The caller is responsible for LocalFree of the returned DACL on success. func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) { // Generate pointers to the SIDs based on the string SIDs - sid, err := syscall.StringToSid(sidVmGroup) + sid, err := windows.StringToSid(sidVmGroup) if err != nil { - return 0, errors.Wrapf(err, "%s syscall.StringToSid %s %s", gvmga, name, sidVmGroup) + return 0, errors.Wrapf(err, "%s windows.StringToSid %s %s", gvmga, name, sidVmGroup) } inheritance := inheritModeNoInheritance diff --git a/pkg/security/syscall_windows.go b/pkg/security/syscall_windows.go index c40c2739..34be353f 100644 --- a/pkg/security/syscall_windows.go +++ b/pkg/security/syscall_windows.go @@ -2,6 +2,6 @@ package security //go:generate go run mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go -//sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo -//sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) [failretval!=0] = advapi32.SetSecurityInfo +//sys getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo +//sys setSecurityInfo(handle windows.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) [failretval!=0] = advapi32.SetSecurityInfo //sys setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) [failretval!=0] = advapi32.SetEntriesInAclW diff --git a/pkg/security/zsyscall_windows.go b/pkg/security/zsyscall_windows.go index 4a90cb3c..e3043a8b 100644 --- a/pkg/security/zsyscall_windows.go +++ b/pkg/security/zsyscall_windows.go @@ -45,7 +45,7 @@ var ( procSetSecurityInfo = modadvapi32.NewProc("SetSecurityInfo") ) -func getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) { +func getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) { r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(ppsidOwner)), uintptr(unsafe.Pointer(ppsidGroup)), uintptr(unsafe.Pointer(ppDacl)), uintptr(unsafe.Pointer(ppSacl)), uintptr(unsafe.Pointer(ppSecurityDescriptor)), 0) if r1 != 0 { err = errnoErr(e1) @@ -61,7 +61,7 @@ func setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl * return } -func setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) { +func setSecurityInfo(handle windows.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) { r1, _, e1 := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(psidOwner), uintptr(psidGroup), uintptr(pDacl), uintptr(pSacl), 0, 0) if r1 != 0 { err = errnoErr(e1) diff --git a/privilege.go b/privilege.go index b77d717c..ec29e40f 100644 --- a/privilege.go +++ b/privilege.go @@ -14,10 +14,7 @@ import ( ) //sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges -//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf -//sys revertToSelf() (err error) = advapi32.RevertToSelf -//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken -//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread +//sys getCurrentThread() (h windows.Handle) = GetCurrentThread //sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW //sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW //sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW @@ -176,15 +173,15 @@ func getPrivilegeName(luid uint64) string { } func newThreadToken() (windows.Token, error) { - err := impersonateSelf(securityImpersonation) + err := windows.ImpersonateSelf(securityImpersonation) if err != nil { return 0, err } var token windows.Token - err = openThreadToken(getCurrentThread(), windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, false, &token) + err = windows.OpenThreadToken(getCurrentThread(), windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, false, &token) if err != nil { - rerr := revertToSelf() + rerr := windows.RevertToSelf() if rerr != nil { panic(rerr) } @@ -194,7 +191,7 @@ func newThreadToken() (windows.Token, error) { } func releaseThreadToken(h windows.Token) { - err := revertToSelf() + err := windows.RevertToSelf() if err != nil { panic(err) } diff --git a/sd.go b/sd.go index 7b53f4cd..e60dcbe0 100644 --- a/sd.go +++ b/sd.go @@ -3,7 +3,6 @@ package winio import ( - "syscall" "unsafe" "golang.org/x/sys/windows" @@ -13,7 +12,6 @@ import ( //sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW //sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW //sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW -//sys localFree(mem uintptr) = LocalFree //sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength const ( @@ -70,8 +68,8 @@ func LookupSidByName(name string) (sid string, err error) { if err != nil { return "", &AccountLookupError{name, err} } - sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:]) - localFree(uintptr(unsafe.Pointer(strBuffer))) + sid = windows.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:]) + windows.LocalFree((windows.Handle)(unsafe.Pointer(strBuffer))) return sid, nil } @@ -81,7 +79,7 @@ func SddlToSecurityDescriptor(sddl string) ([]byte, error) { if err != nil { return nil, &SddlConversionError{sddl, err} } - defer localFree(sdBuffer) + defer windows.LocalFree((windows.Handle)(unsafe.Pointer(sdBuffer))) sd := make([]byte, getSecurityDescriptorLength(sdBuffer)) copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)]) return sd, nil @@ -95,6 +93,6 @@ func SecurityDescriptorToSddl(sd []byte) (string, error) { if err != nil { return "", err } - defer localFree(uintptr(unsafe.Pointer(sddl))) - return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil + defer windows.LocalFree((windows.Handle)(unsafe.Pointer(sddl))) + return windows.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil } diff --git a/vhd/vhd.go b/vhd/vhd.go index b03b789e..2475e418 100644 --- a/vhd/vhd.go +++ b/vhd/vhd.go @@ -4,7 +4,6 @@ package vhd import ( "fmt" - "syscall" "github.com/Microsoft/go-winio/pkg/guid" "github.com/pkg/errors" @@ -13,11 +12,11 @@ import ( //go:generate go run mksyscall_windows.go -output zvhd_windows.go vhd.go -//sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.CreateVirtualDisk -//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.OpenVirtualDisk -//sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) [failretval != 0] = virtdisk.AttachVirtualDisk -//sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = virtdisk.DetachVirtualDisk -//sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) [failretval != 0] = virtdisk.GetVirtualDiskPhysicalPath +//sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *windows.Overlapped, handle *windows.Handle) (err error) [failretval != 0] = virtdisk.CreateVirtualDisk +//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *windows.Handle) (err error) [failretval != 0] = virtdisk.OpenVirtualDisk +//sys attachVirtualDisk(handle windows.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *windows.Overlapped) (err error) [failretval != 0] = virtdisk.AttachVirtualDisk +//sys detachVirtualDisk(handle windows.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = virtdisk.DetachVirtualDisk +//sys getVirtualDiskPhysicalPath(handle windows.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) [failretval != 0] = virtdisk.GetVirtualDiskPhysicalPath type ( CreateVirtualDiskFlag uint32 @@ -146,14 +145,14 @@ func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { return err } - if err := syscall.CloseHandle(handle); err != nil { + if err := windows.CloseHandle(handle); err != nil { return err } return nil } // DetachVirtualDisk detaches a virtual hard disk by handle. -func DetachVirtualDisk(handle syscall.Handle) (err error) { +func DetachVirtualDisk(handle windows.Handle) (err error) { if err := detachVirtualDisk(handle, 0, 0); err != nil { return errors.Wrap(err, "failed to detach virtual disk") } @@ -170,12 +169,12 @@ func DetachVhd(path string) error { if err != nil { return err } - defer syscall.CloseHandle(handle) + defer windows.CloseHandle(handle) return DetachVirtualDisk(handle) } // AttachVirtualDisk attaches a virtual hard disk for use. -func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtualDiskFlag, parameters *AttachVirtualDiskParameters) (err error) { +func AttachVirtualDisk(handle windows.Handle, attachVirtualDiskFlag AttachVirtualDiskFlag, parameters *AttachVirtualDiskParameters) (err error) { // Supports both version 1 and 2 of the attach parameters as version 2 wasn't present in RS5. if err := attachVirtualDisk( handle, @@ -202,7 +201,7 @@ func AttachVhd(path string) (err error) { return err } - defer syscall.CloseHandle(handle) + defer windows.CloseHandle(handle) params := AttachVirtualDiskParameters{Version: 2} if err := AttachVirtualDisk( handle, @@ -215,7 +214,7 @@ func AttachVhd(path string) (err error) { } // OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags. -func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag) (syscall.Handle, error) { +func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag) (windows.Handle, error) { parameters := OpenVirtualDiskParameters{Version: 2} handle, err := OpenVirtualDiskWithParameters( vhdPath, @@ -230,9 +229,9 @@ func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask } // OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters. -func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag, parameters *OpenVirtualDiskParameters) (syscall.Handle, error) { +func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag, parameters *OpenVirtualDiskParameters) (windows.Handle, error) { var ( - handle syscall.Handle + handle windows.Handle defaultType VirtualStorageType ) if parameters.Version != 2 { @@ -252,9 +251,9 @@ func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask Virtual } // CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk. -func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, createVirtualDiskFlags CreateVirtualDiskFlag, parameters *CreateVirtualDiskParameters) (syscall.Handle, error) { +func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, createVirtualDiskFlags CreateVirtualDiskFlag, parameters *CreateVirtualDiskParameters) (windows.Handle, error) { var ( - handle syscall.Handle + handle windows.Handle defaultType VirtualStorageType ) if parameters.Version != 2 { @@ -280,7 +279,7 @@ func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, // GetVirtualDiskPhysicalPath takes a handle to a virtual hard disk and returns the physical // path of the disk on the machine. This path is in the form \\.\PhysicalDriveX where X is an integer // that represents the particular enumeration of the physical disk on the caller's system. -func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) { +func GetVirtualDiskPhysicalPath(handle windows.Handle) (_ string, err error) { var ( diskPathSizeInBytes uint32 = 256 * 2 // max path length 256 wide chars diskPhysicalPathBuf [256]uint16 @@ -316,7 +315,7 @@ func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error if err != nil { return fmt.Errorf("failed to create differencing vhd: %s", err) } - if err := syscall.CloseHandle(vhdHandle); err != nil { + if err := windows.CloseHandle(vhdHandle); err != nil { return fmt.Errorf("failed to close differencing vhd handle: %s", err) } return nil diff --git a/vhd/zvhd_windows.go b/vhd/zvhd_windows.go index 572f7b42..b5a03127 100644 --- a/vhd/zvhd_windows.go +++ b/vhd/zvhd_windows.go @@ -47,7 +47,7 @@ var ( procOpenVirtualDisk = modvirtdisk.NewProc("OpenVirtualDisk") ) -func attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) { +func attachVirtualDisk(handle windows.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *windows.Overlapped) (err error) { r1, _, e1 := syscall.Syscall6(procAttachVirtualDisk.Addr(), 6, uintptr(handle), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(attachVirtualDiskFlag), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped))) if r1 != 0 { err = errnoErr(e1) @@ -55,7 +55,7 @@ func attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attac return } -func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) { +func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *windows.Overlapped, handle *windows.Handle) (err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(path) if err != nil { @@ -64,7 +64,7 @@ func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virt return _createVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, securityDescriptor, createVirtualDiskFlags, providerSpecificFlags, parameters, overlapped, handle) } -func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) { +func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *windows.Overlapped, handle *windows.Handle) (err error) { r1, _, e1 := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(createVirtualDiskFlags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(handle))) if r1 != 0 { err = errnoErr(e1) @@ -72,7 +72,7 @@ func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, vi return } -func detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) { +func detachVirtualDisk(handle windows.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) { r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(detachVirtualDiskFlags), uintptr(providerSpecificFlags)) if r1 != 0 { err = errnoErr(e1) @@ -80,7 +80,7 @@ func detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, pro return } -func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) { +func getVirtualDiskPhysicalPath(handle windows.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) { r1, _, e1 := syscall.Syscall(procGetVirtualDiskPhysicalPath.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(diskPathSizeInBytes)), uintptr(unsafe.Pointer(buffer))) if r1 != 0 { err = errnoErr(e1) @@ -88,7 +88,7 @@ func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint return } -func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) { +func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *windows.Handle) (err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(path) if err != nil { @@ -97,7 +97,7 @@ func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtua return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle) } -func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) { +func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *windows.Handle) (err error) { r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle))) if r1 != 0 { err = errnoErr(e1) diff --git a/zsyscall_windows.go b/zsyscall_windows.go index 176ff75e..33ae6c20 100644 --- a/zsyscall_windows.go +++ b/zsyscall_windows.go @@ -48,27 +48,18 @@ var ( procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") - procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procBackupRead = modkernel32.NewProc("BackupRead") procBackupWrite = modkernel32.NewProc("BackupWrite") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") procCreateFileW = modkernel32.NewProc("CreateFileW") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") procLocalAlloc = modkernel32.NewProc("LocalAlloc") - procLocalFree = modkernel32.NewProc("LocalFree") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") @@ -129,14 +120,6 @@ func getSecurityDescriptorLength(sd uintptr) (len uint32) { return } -func impersonateSelf(level uint32) (err error) { - r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(accountName) @@ -210,27 +193,7 @@ func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err return } -func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { - var _p0 uint32 - if openAsSelf { - _p0 = 1 - } - r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func revertToSelf() (err error) { - r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { +func backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { var _p0 *byte if len(b) > 0 { _p0 = &b[0] @@ -250,7 +213,7 @@ func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, proce return } -func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { +func backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { var _p0 *byte if len(b) > 0 { _p0 = &b[0] @@ -270,15 +233,7 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p return } -func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { +func connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) { r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) if r1 == 0 { err = errnoErr(e1) @@ -286,7 +241,7 @@ func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { return } -func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { +func createFile(name string, access uint32, mode uint32, sa *windows.SecurityAttributes, createmode uint32, attrs uint32, templatefile windows.Handle) (handle windows.Handle, err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(name) if err != nil { @@ -295,49 +250,22 @@ func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAtt return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) } -func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { +func _createFile(name *uint16, access uint32, mode uint32, sa *windows.SecurityAttributes, createmode uint32, attrs uint32, templatefile windows.Handle) (handle windows.Handle, err error) { r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) - handle = syscall.Handle(r0) - if handle == syscall.InvalidHandle { + handle = windows.Handle(r0) + if handle == windows.InvalidHandle { err = errnoErr(e1) } return } -func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) - newport = syscall.Handle(r0) - if newport == 0 { - err = errnoErr(e1) - } - return -} - -func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(name) - if err != nil { - return - } - return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) -} - -func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) - handle = syscall.Handle(r0) - if handle == syscall.InvalidHandle { - err = errnoErr(e1) - } - return -} - -func getCurrentThread() (h syscall.Handle) { +func getCurrentThread() (h windows.Handle) { r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) - h = syscall.Handle(r0) + h = windows.Handle(r0) return } -func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { +func getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) if r1 == 0 { err = errnoErr(e1) @@ -345,7 +273,7 @@ func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *u return } -func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { +func getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) if r1 == 0 { err = errnoErr(e1) @@ -353,34 +281,13 @@ func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSiz return } -func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) ptr = uintptr(r0) return } -func localFree(mem uintptr) { - syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) - return -} - -func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { +func ntCreateNamedPipeFile(pipe *windows.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) status = ntstatus(r0) return @@ -406,7 +313,7 @@ func rtlNtStatusToDosError(status ntstatus) (winerr error) { return } -func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { +func wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { var _p0 uint32 if wait { _p0 = 1 @@ -418,7 +325,7 @@ func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint return } -func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { +func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) { r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) if r1 == socketError { err = errnoErr(e1)