Refactor (windows).

This commit is contained in:
Nuno Cruces 2022-06-18 16:12:03 +01:00
parent d47150a866
commit 561f2b8b32
11 changed files with 74 additions and 52 deletions

View file

@ -27,4 +27,4 @@ type LOGFONT struct {
//sys CreateFontIndirect(lf *LOGFONT) (font Handle) = gdi32.CreateFontIndirectW //sys CreateFontIndirect(lf *LOGFONT) (font Handle) = gdi32.CreateFontIndirectW
//sys DeleteObject(o Handle) (ok bool) = gdi32.DeleteObject //sys DeleteObject(o Handle) (ok bool) = gdi32.DeleteObject
//sys GetDeviceCaps(dc Handle, index int) (cap uintptr) = gdi32.GetDeviceCaps //sys GetDeviceCaps(dc Handle, index int) (cap int) = gdi32.GetDeviceCaps

View file

@ -1,6 +1,6 @@
//go:build generate //go:build generate
//go:generate -command mkwinsyscall go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go //go:generate -command mkwinsyscall go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go
//go:generate mkwinsyscall comctl32.go comdlg32.go gdi32.go ole32.go shell32.go user32.go //go:generate mkwinsyscall comctl32.go comdlg32.go gdi32.go ole32.go shell32.go user32.go win32.go wtsapi32.go
package win package win

View file

@ -44,4 +44,4 @@ func (o *COMObject) Call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr er
} }
//sys CoTaskMemFree(address uintptr) = ole32.CoTaskMemFree //sys CoTaskMemFree(address uintptr) = ole32.CoTaskMemFree
//sys CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (ret error) = ole32.CoCreateInstance //sys CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance

View file

@ -53,6 +53,6 @@ type _IShellItemVtbl struct {
} }
//sys SHBrowseForFolder(bi *BROWSEINFO) (ptr uintptr) = shell32.SHBrowseForFolder //sys SHBrowseForFolder(bi *BROWSEINFO) (ptr uintptr) = shell32.SHBrowseForFolder
//sys SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (err error) = shell32.SHCreateItemFromParsingName //sys SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName
//sys SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (err error) = shell32.SHGetPathFromIDListEx //sys SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx
//sys ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) = shell32.Shell_NotifyIconW //sys ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) = shell32.Shell_NotifyIconW

View file

@ -32,3 +32,5 @@ const (
func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) {
return windows.MessageBox(hwnd, text, caption, boxtype) return windows.MessageBox(hwnd, text, caption, boxtype)
} }
//sys GetDlgCtrlID(wnd HWND) (ret int) = user32.GetDlgCtrlID

View file

@ -7,3 +7,5 @@ import "golang.org/x/sys/windows"
type Handle = windows.Handle type Handle = windows.Handle
type HWND = windows.HWND type HWND = windows.HWND
//sys RtlGetNtVersionNumbers(major *uint32, minor *uint32, build *uint32) = ntdll.RtlGetNtVersionNumbers

10
internal/win/wtsapi32.go Normal file
View file

@ -0,0 +1,10 @@
//go:build windows
package win
const (
WTS_CURRENT_SERVER_HANDLE = 0
WTS_CURRENT_SESSION = 0xffffffff
)
//sys WTSSendMessage(server Handle, sessionID uint32, title *uint16, titleLength int, message *uint16, messageLength int, style uint32, timeout int, response *uint32, wait bool) (err error) = wtsapi32.WTSSendMessageW

View file

@ -41,8 +41,11 @@ var (
modcomctl32 = windows.NewLazySystemDLL("comctl32.dll") modcomctl32 = windows.NewLazySystemDLL("comctl32.dll")
modcomdlg32 = windows.NewLazySystemDLL("comdlg32.dll") modcomdlg32 = windows.NewLazySystemDLL("comdlg32.dll")
modgdi32 = windows.NewLazySystemDLL("gdi32.dll") modgdi32 = windows.NewLazySystemDLL("gdi32.dll")
modntdll = windows.NewLazySystemDLL("ntdll.dll")
modole32 = windows.NewLazySystemDLL("ole32.dll") modole32 = windows.NewLazySystemDLL("ole32.dll")
modshell32 = windows.NewLazySystemDLL("shell32.dll") modshell32 = windows.NewLazySystemDLL("shell32.dll")
moduser32 = windows.NewLazySystemDLL("user32.dll")
modwtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll")
procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx") procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx")
procChooseColorW = modcomdlg32.NewProc("ChooseColorW") procChooseColorW = modcomdlg32.NewProc("ChooseColorW")
@ -52,12 +55,15 @@ var (
procCreateFontIndirectW = modgdi32.NewProc("CreateFontIndirectW") procCreateFontIndirectW = modgdi32.NewProc("CreateFontIndirectW")
procDeleteObject = modgdi32.NewProc("DeleteObject") procDeleteObject = modgdi32.NewProc("DeleteObject")
procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps") procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps")
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
procCoCreateInstance = modole32.NewProc("CoCreateInstance") procCoCreateInstance = modole32.NewProc("CoCreateInstance")
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder") procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder")
procSHCreateItemFromParsingName = modshell32.NewProc("SHCreateItemFromParsingName") procSHCreateItemFromParsingName = modshell32.NewProc("SHCreateItemFromParsingName")
procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx") procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx")
procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW") procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW")
procGetDlgCtrlID = moduser32.NewProc("GetDlgCtrlID")
procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW")
) )
func InitCommonControlsEx(icc *INITCOMMONCONTROLSEX) (ok bool) { func InitCommonControlsEx(icc *INITCOMMONCONTROLSEX) (ok bool) {
@ -102,16 +108,21 @@ func DeleteObject(o Handle) (ok bool) {
return return
} }
func GetDeviceCaps(dc Handle, index int) (cap uintptr) { func GetDeviceCaps(dc Handle, index int) (cap int) {
r0, _, _ := syscall.Syscall(procGetDeviceCaps.Addr(), 2, uintptr(dc), uintptr(index), 0) r0, _, _ := syscall.Syscall(procGetDeviceCaps.Addr(), 2, uintptr(dc), uintptr(index), 0)
cap = uintptr(r0) cap = int(r0)
return return
} }
func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (ret error) { func RtlGetNtVersionNumbers(major *uint32, minor *uint32, build *uint32) {
syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(major)), uintptr(unsafe.Pointer(minor)), uintptr(unsafe.Pointer(build)))
return
}
func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) {
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unkOuter), uintptr(clsContext), uintptr(iid), uintptr(address), 0) r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unkOuter), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
if r0 != 0 { if r0 != 0 {
ret = syscall.Errno(r0) res = syscall.Errno(r0)
} }
return return
} }
@ -127,19 +138,17 @@ func SHBrowseForFolder(bi *BROWSEINFO) (ptr uintptr) {
return return
} }
func SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (err error) { func SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) {
r1, _, e1 := syscall.Syscall6(procSHCreateItemFromParsingName.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(bc), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0) r0, _, _ := syscall.Syscall6(procSHCreateItemFromParsingName.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(bc), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0)
if r1 == 0 { if r0 != 0 {
err = errnoErr(e1) res = syscall.Errno(r0)
} }
return return
} }
func SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (err error) { func SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (ok bool) {
r1, _, e1 := syscall.Syscall6(procSHGetPathFromIDListEx.Addr(), 4, uintptr(ptr), uintptr(unsafe.Pointer(path)), uintptr(pathLen), uintptr(opts), 0, 0) r0, _, _ := syscall.Syscall6(procSHGetPathFromIDListEx.Addr(), 4, uintptr(ptr), uintptr(unsafe.Pointer(path)), uintptr(pathLen), uintptr(opts), 0, 0)
if r1 == 0 { ok = r0 != 0
err = errnoErr(e1)
}
return return
} }
@ -151,3 +160,21 @@ func ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error)
} }
return return
} }
func GetDlgCtrlID(wnd HWND) (ret int) {
r0, _, _ := syscall.Syscall(procGetDlgCtrlID.Addr(), 1, uintptr(wnd), 0, 0)
ret = int(r0)
return
}
func WTSSendMessage(server Handle, sessionID uint32, title *uint16, titleLength int, message *uint16, messageLength int, style uint32, timeout int, response *uint32, wait bool) (err error) {
var _p0 uint32
if wait {
_p0 = 1
}
r1, _, e1 := syscall.Syscall12(procWTSSendMessageW.Addr(), 10, uintptr(server), uintptr(sessionID), uintptr(unsafe.Pointer(title)), uintptr(titleLength), uintptr(unsafe.Pointer(message)), uintptr(messageLength), uintptr(style), uintptr(timeout), uintptr(unsafe.Pointer(response)), uintptr(_p0), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}

View file

@ -8,10 +8,6 @@ import (
"github.com/ncruces/zenity/internal/win" "github.com/ncruces/zenity/internal/win"
) )
var (
getDlgCtrlID = user32.NewProc("GetDlgCtrlID")
)
func message(kind messageKind, text string, opts options) error { func message(kind messageKind, text string, opts options) error {
var flags uint32 var flags uint32
@ -22,6 +18,8 @@ func message(kind messageKind, text string, opts options) error {
flags |= win.MB_OKCANCEL flags |= win.MB_OKCANCEL
case opts.extraButton != nil: case opts.extraButton != nil:
flags |= win.MB_YESNO flags |= win.MB_YESNO
default:
opts.cancelLabel = opts.okLabel
} }
switch opts.icon { switch opts.icon {
@ -59,7 +57,7 @@ func message(kind messageKind, text string, opts options) error {
defer setup()() defer setup()()
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil { if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
unhook, err := hookMessageDialog(kind, opts) unhook, err := hookMessageDialog(opts)
if err != nil { if err != nil {
return err return err
} }
@ -89,7 +87,7 @@ func message(kind messageKind, text string, opts options) error {
} }
} }
func hookMessageDialog(kind messageKind, opts options) (unhook context.CancelFunc, err error) { func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) {
return hookDialog(opts.ctx, opts.windowIcon, nil, func(wnd uintptr) { return hookDialog(opts.ctx, opts.windowIcon, nil, func(wnd uintptr) {
enumChildWindows.Call(wnd, enumChildWindows.Call(wnd,
syscall.NewCallback(hookMessageDialogCallback), syscall.NewCallback(hookMessageDialogCallback),
@ -97,8 +95,8 @@ func hookMessageDialog(kind messageKind, opts options) (unhook context.CancelFun
}) })
} }
func hookMessageDialogCallback(wnd uintptr, lparam *options) uintptr { func hookMessageDialogCallback(wnd win.HWND, lparam *options) uintptr {
ctl, _, _ := getDlgCtrlID.Call(wnd) ctl := win.GetDlgCtrlID(wnd)
var text *string var text *string
switch ctl { switch ctl {
@ -110,14 +108,14 @@ func hookMessageDialogCallback(wnd uintptr, lparam *options) uintptr {
text = lparam.extraButton text = lparam.extraButton
} }
if text != nil { if text != nil {
setWindowText.Call(wnd, strptr(*text)) setWindowText.Call(uintptr(wnd), strptr(*text))
} }
if ctl == 20 /*IDC_STATIC_OK*/ { if ctl == 20 /*IDC_STATIC_OK*/ {
icon := getIcon(lparam.icon) icon := getIcon(lparam.icon)
if icon.handle != 0 { if icon.handle != 0 {
defer icon.delete() defer icon.delete()
sendMessage.Call(wnd, _STM_SETICON, icon.handle, 0) sendMessage.Call(uintptr(wnd), _STM_SETICON, icon.handle, 0)
} }
} }
return 1 return 1

View file

@ -11,11 +11,6 @@ import (
"github.com/ncruces/zenity/internal/zenutil" "github.com/ncruces/zenity/internal/zenutil"
) )
var (
rtlGetNtVersionNumbers = ntdll.NewProc("RtlGetNtVersionNumbers")
wtsSendMessage = wtsapi32.NewProc("WTSSendMessageW")
)
func notify(text string, opts options) error { func notify(text string, opts options) error {
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {
return opts.ctx.Err() return opts.ctx.Err()
@ -64,10 +59,7 @@ func notify(text string, opts options) error {
} }
var major, minor, build uint32 var major, minor, build uint32
rtlGetNtVersionNumbers.Call( win.RtlGetNtVersionNumbers(&major, &minor, &build)
uintptr(unsafe.Pointer(&major)),
uintptr(unsafe.Pointer(&minor)),
uintptr(unsafe.Pointer(&build)))
// On Windows 7 (6.1) and lower, wait up to 10 seconds to clean up. // On Windows 7 (6.1) and lower, wait up to 10 seconds to clean up.
if major < 6 || major == 6 && minor < 2 { if major < 6 || major == 6 && minor < 2 {
@ -86,7 +78,7 @@ func notify(text string, opts options) error {
} }
func wtsMessage(text string, opts options) error { func wtsMessage(text string, opts options) error {
var flags uintptr var flags uint32
switch opts.icon { switch opts.icon {
case ErrorIcon: case ErrorIcon:
@ -113,15 +105,8 @@ func wtsMessage(text string, opts options) error {
ptitle := syscall.StringToUTF16(*title) ptitle := syscall.StringToUTF16(*title)
var res uint32 var res uint32
s, _, err := wtsSendMessage.Call( return win.WTSSendMessage(
0, // WTS_CURRENT_SERVER_HANDLE win.WTS_CURRENT_SERVER_HANDLE, win.WTS_CURRENT_SESSION,
0xffffffff, // WTS_CURRENT_SESSION &ptitle[0], 2*len(ptitle), &ptext[0], 2*len(ptext),
uintptr(unsafe.Pointer(&ptitle[0])), uintptr(2*len(ptitle)), flags, timeout, &res, false)
uintptr(unsafe.Pointer(&ptext[0])), uintptr(2*len(ptext)),
flags, uintptr(timeout), uintptr(unsafe.Pointer(&res)), 0)
if s == 0 {
return err
}
return nil
} }

View file

@ -18,9 +18,7 @@ import (
var ( var (
kernel32 = windows.NewLazySystemDLL("kernel32.dll") kernel32 = windows.NewLazySystemDLL("kernel32.dll")
ntdll = windows.NewLazySystemDLL("ntdll.dll")
user32 = windows.NewLazySystemDLL("user32.dll") user32 = windows.NewLazySystemDLL("user32.dll")
wtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll")
activateActCtx = kernel32.NewProc("ActivateActCtx") activateActCtx = kernel32.NewProc("ActivateActCtx")
createActCtx = kernel32.NewProc("CreateActCtxW") createActCtx = kernel32.NewProc("CreateActCtxW")
@ -261,7 +259,7 @@ func getDPI(wnd uintptr) dpi {
if wnd != 0 && getDpiForWindow.Find() == nil { if wnd != 0 && getDpiForWindow.Find() == nil {
res, _, _ = getDpiForWindow.Call(wnd) res, _, _ = getDpiForWindow.Call(wnd)
} else if dc, _, _ := getWindowDC.Call(wnd); dc != 0 { } else if dc, _, _ := getWindowDC.Call(wnd); dc != 0 {
res = win.GetDeviceCaps(win.Handle(dc), win.LOGPIXELSY) res = uintptr(win.GetDeviceCaps(win.Handle(dc), win.LOGPIXELSY))
releaseDC.Call(0, dc) releaseDC.Call(0, dc)
} }