From 023668638298d0abf81090dd44464d3c8b724aa7 Mon Sep 17 00:00:00 2001 From: qiulaidongfeng <2645477756@qq.com> Date: Sat, 29 Jul 2023 08:27:21 +0000 Subject: [PATCH] os: fix test failure when Workstation service is not enabled TestNetworkSymbolicLink needs to enable the Workstation service, otherwise it will fail. This CL avoids failure by skipping testing when the Workstation service is not enabled. Fixes #61467 Change-Id: I395952fc18329e0b0dfdec55c8a18f4007ea91de Change-Id: I395952fc18329e0b0dfdec55c8a18f4007ea91de GitHub-Last-Rev: 7f089d1dff3ca939915fc8b3e49eba3908f15180 GitHub-Pull-Request: golang/go#61564 Reviewed-on: https://go-review.googlesource.com/c/go/+/512736 Reviewed-by: Quim Muntal TryBot-Result: Gopher Robot Reviewed-by: Alex Brainman Reviewed-by: Michael Knyszek Run-TryBot: Alex Brainman Reviewed-by: Bryan Mills --- .../syscall/windows/syscall_windows.go | 19 ++++++++++++ .../syscall/windows/zsyscall_windows.go | 29 +++++++++++++++++++ src/os/os_windows_test.go | 23 +++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go index 9e3c3dc873..924dd1e121 100644 --- a/src/internal/syscall/windows/syscall_windows.go +++ b/src/internal/syscall/windows/syscall_windows.go @@ -401,3 +401,22 @@ type FILE_ID_BOTH_DIR_INFO struct { //sys RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) = kernel32.RtlLookupFunctionEntry //sys RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) = kernel32.RtlVirtualUnwind + +type SERVICE_STATUS struct { + ServiceType uint32 + CurrentState uint32 + ControlsAccepted uint32 + Win32ExitCode uint32 + ServiceSpecificExitCode uint32 + CheckPoint uint32 + WaitHint uint32 +} + +const ( + SERVICE_RUNNING = 4 + SERVICE_QUERY_STATUS = 4 +) + +//sys OpenService(mgr syscall.Handle, serviceName *uint16, access uint32) (handle syscall.Handle, err error) = advapi32.OpenServiceW +//sys QueryServiceStatus(hService syscall.Handle, lpServiceStatus *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus +//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle syscall.Handle, err error) [failretval==0] = advapi32.OpenSCManagerW diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go index 32744b00fc..fb87bd03a2 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -49,7 +49,10 @@ var ( procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") + procOpenServiceW = modadvapi32.NewProc("OpenServiceW") procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") procSystemFunction036 = modadvapi32.NewProc("SystemFunction036") @@ -121,6 +124,24 @@ func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err err return } +func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(access)) + handle = syscall.Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func OpenService(mgr syscall.Handle, serviceName *uint16, access uint32) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall(procOpenServiceW.Addr(), 3, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(access)) + handle = syscall.Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) { var _p0 uint32 if openasself { @@ -133,6 +154,14 @@ func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *sy return } +func QueryServiceStatus(hService syscall.Handle, lpServiceStatus *SERVICE_STATUS) (err error) { + r1, _, e1 := syscall.Syscall(procQueryServiceStatus.Addr(), 2, uintptr(hService), uintptr(unsafe.Pointer(lpServiceStatus)), 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 { diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go index fee539a227..75ac61bb96 100644 --- a/src/os/os_windows_test.go +++ b/src/os/os_windows_test.go @@ -427,6 +427,28 @@ func TestDirectorySymbolicLink(t *testing.T) { testDirLinks(t, tests) } +func mustHaveWorkstation(t *testing.T) { + mar, err := windows.OpenSCManager(nil, nil, windows.SERVICE_QUERY_STATUS) + if err != nil { + return + } + defer syscall.CloseHandle(mar) + //LanmanWorkstation is the service name, and Workstation is the display name. + srv, err := windows.OpenService(mar, syscall.StringToUTF16Ptr("LanmanWorkstation"), windows.SERVICE_QUERY_STATUS) + if err != nil { + return + } + defer syscall.CloseHandle(srv) + var state windows.SERVICE_STATUS + err = windows.QueryServiceStatus(srv, &state) + if err != nil { + return + } + if state.CurrentState != windows.SERVICE_RUNNING { + t.Skip("Requires the Windows service Workstation, but it is detected that it is not enabled.") + } +} + func TestNetworkSymbolicLink(t *testing.T) { testenv.MustHaveSymlink(t) @@ -498,6 +520,7 @@ func TestNetworkSymbolicLink(t *testing.T) { } fi2, err := os.Stat(UNCPath) if err != nil { + mustHaveWorkstation(t) t.Fatal(err) } if !os.SameFile(fi1, fi2) { -- 2.48.1