Skip to content

Commit 25df2e8

Browse files
committed
ipn/desktop: fix panics on Windows 10, x86
[G,S]etWindowLongPtrW are not available on 32-bit Windows, where [G,S]etWindowLongW should be used instead. The initial revision of tailscale#14945 imported the win package for calling and other Win32 API functions, which exported the correct API depending on the platform. However, the same logic wasn't implemented when we removed the win package dependency in a later revision, resulting in panics on Windows 10 x86 (there's no 32-bit Windows 11). In this PR, we update the ipn/desktop package to use either [G,S]etWindowLongPtrW or [G,S]etWindowLongW depending on the platform. Fixes tailscale#15684 Signed-off-by: Nick Khyl <nickk@tailscale.com> (cherry picked from commit 60614fa)
1 parent 5254e70 commit 25df2e8

File tree

3 files changed

+35
-22
lines changed

3 files changed

+35
-22
lines changed

ipn/desktop/mksyscall.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ package desktop
1111
//sys registerClassEx(windowClass *_WNDCLASSEX) (atom uint16, err error) [atom==0] = user32.RegisterClassExW
1212
//sys createWindowEx(dwExStyle uint32, lpClassName *uint16, lpWindowName *uint16, dwStyle uint32, x int32, y int32, nWidth int32, nHeight int32, hWndParent windows.HWND, hMenu windows.Handle, hInstance windows.Handle, lpParam unsafe.Pointer) (hWnd windows.HWND, err error) [hWnd==0] = user32.CreateWindowExW
1313
//sys defWindowProc(hwnd windows.HWND, msg uint32, wparam uintptr, lparam uintptr) (res uintptr) = user32.DefWindowProcW
14-
//sys setWindowLongPtr(hwnd windows.HWND, index int32, newLong uintptr) (res uintptr, err error) [res==0 && e1!=0] = user32.SetWindowLongPtrW
15-
//sys getWindowLongPtr(hwnd windows.HWND, index int32) (res uintptr, err error) [res==0 && e1!=0] = user32.GetWindowLongPtrW
1614
//sys sendMessage(hwnd windows.HWND, msg uint32, wparam uintptr, lparam uintptr) (res uintptr) = user32.SendMessageW
1715
//sys getMessage(lpMsg *_MSG, hwnd windows.HWND, msgMin uint32, msgMax uint32) (ret int32) = user32.GetMessageW
1816
//sys translateMessage(lpMsg *_MSG) (res bool) = user32.TranslateMessage

ipn/desktop/sessions_windows.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,3 +670,38 @@ func (cs _WTS_CONNECTSTATE_CLASS) ToSessionStatus() SessionStatus {
670670
return ClosedSession
671671
}
672672
}
673+
674+
var (
675+
procGetWindowLongPtrW *windows.LazyProc
676+
procSetWindowLongPtrW *windows.LazyProc
677+
)
678+
679+
func init() {
680+
// GetWindowLongPtrW and SetWindowLongPtrW are only available on 64-bit platforms.
681+
// https://web.archive.org/web/20250414195520/https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw
682+
if runtime.GOARCH == "386" || runtime.GOARCH == "arm" {
683+
procGetWindowLongPtrW = moduser32.NewProc("GetWindowLongW")
684+
procSetWindowLongPtrW = moduser32.NewProc("SetWindowLongW")
685+
} else {
686+
procGetWindowLongPtrW = moduser32.NewProc("GetWindowLongPtrW")
687+
procSetWindowLongPtrW = moduser32.NewProc("SetWindowLongPtrW")
688+
}
689+
}
690+
691+
func getWindowLongPtr(hwnd windows.HWND, index int32) (res uintptr, err error) {
692+
r0, _, e1 := syscall.Syscall(procGetWindowLongPtrW.Addr(), 2, uintptr(hwnd), uintptr(index), 0)
693+
res = uintptr(r0)
694+
if res == 0 && e1 != 0 {
695+
err = errnoErr(e1)
696+
}
697+
return
698+
}
699+
700+
func setWindowLongPtr(hwnd windows.HWND, index int32, newLong uintptr) (res uintptr, err error) {
701+
r0, _, e1 := syscall.Syscall(procSetWindowLongPtrW.Addr(), 3, uintptr(hwnd), uintptr(index), uintptr(newLong))
702+
res = uintptr(r0)
703+
if res == 0 && e1 != 0 {
704+
err = errnoErr(e1)
705+
}
706+
return
707+
}

ipn/desktop/zsyscall_windows.go

Lines changed: 0 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)