Wails version family
v3
Exact Wails version
v3.0.0-beta.2
Operating System
Windows
Description
w32.GetStockObject invokes the wrong Win32 export and returns 0 for every input. It has never worked.
v3/pkg/w32/gdi32.go:
func GetStockObject(fnObject int) HGDIOBJ {
ret, _, _ := procGetDeviceCaps.Call(
uintptr(fnObject))
return HGDIOBJ(ret)
}
It calls procGetDeviceCaps, not procGetStockObject — even though procGetStockObject is declared a few lines above, at gdi32.go:40, and is otherwise unused.
GetDeviceCaps takes (HDC, index). Passing a stock-object constant such as DEFAULT_GUI_FONT (17) as the HDC is an invalid handle, so the call returns 0. Every GetStockObject call therefore yields a null GDI handle.
There are no callers in v3 today, which is why this has gone unnoticed. It only surfaces for a new caller, and then indirectly: the null handle is passed to some other GDI function, which fails for reasons that point away from the actual cause. I lost time to exactly this while prototyping owner-drawn menus — SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)) terminated the process, and the null handle was several steps removed from the visible symptom.
This is the same class of defect as the DestroyMenu argument bug already covered by v3/pkg/w32/menu_windows_test.go, where a syscall wrapper passed the wrong arguments and silently returned failure for every call.
To Reproduce
No special hardware or Windows version required.
//go:build windows
package w32_test
import (
"testing"
"github.com/wailsapp/wails/v3/pkg/w32"
)
func TestRepro(t *testing.T) {
for name, obj := range map[string]int{
"DEFAULT_GUI_FONT": w32.DEFAULT_GUI_FONT,
"SYSTEM_FONT": w32.SYSTEM_FONT,
"BLACK_BRUSH": w32.BLACK_BRUSH,
"WHITE_BRUSH": w32.WHITE_BRUSH,
} {
if got := w32.GetStockObject(obj); got == 0 {
t.Errorf("GetStockObject(%s) = 0, want a valid handle", name)
}
}
}
go test ./pkg/w32/ on Windows: every case fails with 0.
Expected behaviour
GetStockObject returns a valid, usable GDI handle for standard stock objects. Stock objects are always available, so a 0 return indicates the wrapper is calling the wrong export.
Screenshots
No response
Attempted Fixes
No response
System Details
Wails: v3.0.0-beta.2
OS: Any Windows build — not version-specific
Arch: amd64
Found on Windows Server 2019 (build 17763) but the defect is in the wrapper
itself and is independent of Windows version.
Additional context
Found while investigating menu theming on Windows; unrelated to that work, so filing separately.
While confirming this, I also noticed that SelectObject panics on failure rather than returning 0. That turns a null handle from this bug into a process termination, since SelectObject is called from inside Windows message handlers. I am not proposing a change to it here: panicking on failure is the established convention across pkg/w32 (39 call sites in 10 files, including SetTextColor and SetBkMode in the same file), so changing one function in isolation would be arbitrary. Happy to raise that separately as a design question if it is worth discussing.
AI Usage Disclosure: I used AI in investigating and writing this issue to confirm my own initial findings.
Wails version family
v3
Exact Wails version
v3.0.0-beta.2
Operating System
Windows
Description
w32.GetStockObjectinvokes the wrong Win32 export and returns 0 for every input. It has never worked.v3/pkg/w32/gdi32.go:It calls
procGetDeviceCaps, notprocGetStockObject— even thoughprocGetStockObjectis declared a few lines above, atgdi32.go:40, and is otherwise unused.GetDeviceCapstakes(HDC, index). Passing a stock-object constant such asDEFAULT_GUI_FONT(17) as theHDCis an invalid handle, so the call returns 0. EveryGetStockObjectcall therefore yields a null GDI handle.There are no callers in v3 today, which is why this has gone unnoticed. It only surfaces for a new caller, and then indirectly: the null handle is passed to some other GDI function, which fails for reasons that point away from the actual cause. I lost time to exactly this while prototyping owner-drawn menus —
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT))terminated the process, and the null handle was several steps removed from the visible symptom.This is the same class of defect as the
DestroyMenuargument bug already covered byv3/pkg/w32/menu_windows_test.go, where a syscall wrapper passed the wrong arguments and silently returned failure for every call.To Reproduce
No special hardware or Windows version required.
go test ./pkg/w32/on Windows: every case fails with 0.Expected behaviour
GetStockObjectreturns a valid, usable GDI handle for standard stock objects. Stock objects are always available, so a 0 return indicates the wrapper is calling the wrong export.Screenshots
No response
Attempted Fixes
No response
System Details
Wails: v3.0.0-beta.2 OS: Any Windows build — not version-specific Arch: amd64 Found on Windows Server 2019 (build 17763) but the defect is in the wrapper itself and is independent of Windows version.Additional context
Found while investigating menu theming on Windows; unrelated to that work, so filing separately.
While confirming this, I also noticed that
SelectObjectpanics on failure rather than returning 0. That turns a null handle from this bug into a process termination, sinceSelectObjectis called from inside Windows message handlers. I am not proposing a change to it here: panicking on failure is the established convention acrosspkg/w32(39 call sites in 10 files, includingSetTextColorandSetBkModein the same file), so changing one function in isolation would be arbitrary. Happy to raise that separately as a design question if it is worth discussing.AI Usage Disclosure: I used AI in investigating and writing this issue to confirm my own initial findings.