Refactor (windows).

This commit is contained in:
Nuno Cruces 2022-06-21 14:27:19 +01:00
parent 113333268d
commit 6928e74895
9 changed files with 70 additions and 36 deletions

View file

@ -274,7 +274,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
} }
defer item.Call(item.Release) defer item.Call(item.Release)
var ptr unsafe.Pointer var ptr win.Pointer
hr, _, _ = item.Call(item.GetDisplayName, hr, _, _ = item.Call(item.GetDisplayName,
_SIGDN_FILESYSPATH, uintptr(unsafe.Pointer(&ptr))) _SIGDN_FILESYSPATH, uintptr(unsafe.Pointer(&ptr)))
if int32(hr) < 0 { if int32(hr) < 0 {
@ -337,7 +337,7 @@ func browseForFolder(opts options) (string, []string, error) {
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {
return "", nil, opts.ctx.Err() return "", nil, opts.ctx.Err()
} }
if ptr == nil { if ptr == nullptr {
return "", nil, ErrCanceled return "", nil, ErrCanceled
} }
defer win.CoTaskMemFree(ptr) defer win.CoTaskMemFree(ptr)

View file

@ -31,8 +31,6 @@ func CoInitializeEx(reserved uintptr, coInit uint32) error {
func CoUninitialize() { windows.CoUninitialize() } func CoUninitialize() { windows.CoUninitialize() }
func CoTaskMemFree(address unsafe.Pointer) { windows.CoTaskMemFree(address) }
// https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl // https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl
type IUnknownVtbl struct { type IUnknownVtbl struct {
@ -57,4 +55,5 @@ func (o *COMObject) Call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr er
} }
} }
//sys CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance //sys CoCreateInstance(clsid uintptr, unkOuter *COMObject, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance
//sys CoTaskMemFree(address Pointer) = ole32.CoTaskMemFree

View file

@ -57,7 +57,7 @@ type _IShellItemVtbl struct {
Compare uintptr Compare uintptr
} }
//sys SHBrowseForFolder(bi *BROWSEINFO) (ret unsafe.Pointer) = shell32.SHBrowseForFolder //sys SHBrowseForFolder(bi *BROWSEINFO) (ret Pointer) = shell32.SHBrowseForFolder
//sys SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName //sys SHCreateItemFromParsingName(path *uint16, bc *COMObject, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName
//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
//sys SHGetPathFromIDListEx(ptr unsafe.Pointer, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx //sys SHGetPathFromIDListEx(ptr Pointer, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx

View file

@ -214,6 +214,9 @@ const (
SC_MONITORPOWER = 0xf170 SC_MONITORPOWER = 0xf170
SC_CONTEXTHELP = 0xf180 SC_CONTEXTHELP = 0xf180
// SetWindowsHookEx types
WH_CALLWNDPROCRET = 12
USER_DEFAULT_SCREEN_DPI = 96 USER_DEFAULT_SCREEN_DPI = 96
DPI_AWARENESS_CONTEXT_UNAWARE = ^uintptr(1) + 1 DPI_AWARENESS_CONTEXT_UNAWARE = ^uintptr(1) + 1
@ -350,12 +353,13 @@ type NONCLIENTMETRICS struct {
MessageFont LOGFONT MessageFont LOGFONT
} }
//sys CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.CallNextHookEx
//sys CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) = user32.CreateIconFromResource //sys CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) = user32.CreateIconFromResource
//sys CreateWindowEx(exStyle uint32, className *uint16, windowName *uint16, style uint32, x int, y int, width int, height int, parent HWND, menu Handle, instance Handle, param unsafe.Pointer) (ret HWND, err error) = user32.CreateWindowExW //sys CreateWindowEx(exStyle uint32, className *uint16, windowName *uint16, style uint32, x int, y int, width int, height int, parent HWND, menu Handle, instance Handle, param unsafe.Pointer) (ret HWND, err error) = user32.CreateWindowExW
//sys DefWindowProc(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.DefWindowProcW
//sys DestroyIcon(icon Handle) (err error) = user32.DestroyIcon //sys DestroyIcon(icon Handle) (err error) = user32.DestroyIcon
//sys DestroyWindow(wnd HWND) (err error) = user32.DestroyWindow //sys DestroyWindow(wnd HWND) (err error) = user32.DestroyWindow
//sys DispatchMessage(msg *MSG) (ret uintptr) = user32.DispatchMessageW //sys DispatchMessage(msg *MSG) (ret uintptr) = user32.DispatchMessageW
//sys DefWindowProc(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.DefWindowProcW
//sys EnableWindow(wnd HWND, enable bool) (ok bool) = user32.EnableWindow //sys EnableWindow(wnd HWND, enable bool) (ok bool) = user32.EnableWindow
//sys EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) = user32.EnumChildWindows //sys EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) = user32.EnumChildWindows
//sys EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) = user32.EnumChildWindows //sys EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) = user32.EnumChildWindows
@ -379,8 +383,10 @@ type NONCLIENTMETRICS struct {
//sys setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) = user32.SetThreadDpiAwarenessContext //sys setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) = user32.SetThreadDpiAwarenessContext
//sys SetWindowLong(wnd HWND, index int, newLong int) (ret int, err error) = user32.SetWindowLongW //sys SetWindowLong(wnd HWND, index int, newLong int) (ret int, err error) = user32.SetWindowLongW
//sys SetWindowPos(wnd HWND, wndInsertAfter HWND, x int, y int, cx int, cy int, flags int) (err error) = user32.SetWindowPos //sys SetWindowPos(wnd HWND, wndInsertAfter HWND, x int, y int, cx int, cy int, flags int) (err error) = user32.SetWindowPos
//sys SetWindowsHookEx(idHook int, fn uintptr, mod Handle, threadID uint32) (ret Handle, err error) = user32.SetWindowsHookExW
//sys SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW //sys SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW
//sys ShowWindow(wnd HWND, cmdShow int) (ok bool) = user32.ShowWindow //sys ShowWindow(wnd HWND, cmdShow int) (ok bool) = user32.ShowWindow
//sys SystemParametersInfo(action int, uiParam uintptr, pvParam unsafe.Pointer, winIni int) (err error) = user32.SystemParametersInfoW //sys SystemParametersInfo(action int, uiParam uintptr, pvParam unsafe.Pointer, winIni int) (err error) = user32.SystemParametersInfoW
//sys TranslateMessage(msg *MSG) (ok bool) = user32.TranslateMessage //sys TranslateMessage(msg *MSG) (ok bool) = user32.TranslateMessage
//sys UnhookWindowsHookEx(hk Handle) (err error) = user32.UnhookWindowsHookEx
//sys UnregisterClass(className *uint16, instance Handle) (err error) = user32.UnregisterClassW //sys UnregisterClass(className *uint16, instance Handle) (err error) = user32.UnregisterClassW

View file

@ -7,7 +7,7 @@ import "golang.org/x/sys/windows"
type Handle = windows.Handle type Handle = windows.Handle
type HWND = windows.HWND type HWND = windows.HWND
type Pointer = windows.Pointer type Pointer uintptr
func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) { func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) {
return windows.RtlGetNtVersionNumbers() return windows.RtlGetNtVersionNumbers()

View file

@ -62,10 +62,12 @@ var (
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW") procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
procReleaseActCtx = modkernel32.NewProc("ReleaseActCtx") procReleaseActCtx = modkernel32.NewProc("ReleaseActCtx")
procCoCreateInstance = modole32.NewProc("CoCreateInstance") procCoCreateInstance = modole32.NewProc("CoCreateInstance")
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")
procCallNextHookEx = moduser32.NewProc("CallNextHookEx")
procCreateIconFromResource = moduser32.NewProc("CreateIconFromResource") procCreateIconFromResource = moduser32.NewProc("CreateIconFromResource")
procCreateWindowExW = moduser32.NewProc("CreateWindowExW") procCreateWindowExW = moduser32.NewProc("CreateWindowExW")
procDefWindowProcW = moduser32.NewProc("DefWindowProcW") procDefWindowProcW = moduser32.NewProc("DefWindowProcW")
@ -95,9 +97,11 @@ var (
procSetWindowLongW = moduser32.NewProc("SetWindowLongW") procSetWindowLongW = moduser32.NewProc("SetWindowLongW")
procSetWindowPos = moduser32.NewProc("SetWindowPos") procSetWindowPos = moduser32.NewProc("SetWindowPos")
procSetWindowTextW = moduser32.NewProc("SetWindowTextW") procSetWindowTextW = moduser32.NewProc("SetWindowTextW")
procSetWindowsHookExW = moduser32.NewProc("SetWindowsHookExW")
procShowWindow = moduser32.NewProc("ShowWindow") procShowWindow = moduser32.NewProc("ShowWindow")
procSystemParametersInfoW = moduser32.NewProc("SystemParametersInfoW") procSystemParametersInfoW = moduser32.NewProc("SystemParametersInfoW")
procTranslateMessage = moduser32.NewProc("TranslateMessage") procTranslateMessage = moduser32.NewProc("TranslateMessage")
procUnhookWindowsHookEx = moduser32.NewProc("UnhookWindowsHookEx")
procUnregisterClassW = moduser32.NewProc("UnregisterClassW") procUnregisterClassW = moduser32.NewProc("UnregisterClassW")
procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW") procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW")
) )
@ -195,29 +199,34 @@ func ReleaseActCtx(actCtx Handle) {
return return
} }
func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) { func CoCreateInstance(clsid uintptr, unkOuter *COMObject, 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(unsafe.Pointer(unkOuter)), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
if r0 != 0 { if r0 != 0 {
res = syscall.Errno(r0) res = syscall.Errno(r0)
} }
return return
} }
func SHBrowseForFolder(bi *BROWSEINFO) (ret unsafe.Pointer) { func CoTaskMemFree(address Pointer) {
syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0)
return
}
func SHBrowseForFolder(bi *BROWSEINFO) (ret Pointer) {
r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0) r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0)
ret = unsafe.Pointer(r0) ret = Pointer(r0)
return return
} }
func SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) { func SHCreateItemFromParsingName(path *uint16, bc *COMObject, iid uintptr, item **IShellItem) (res error) {
r0, _, _ := 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(unsafe.Pointer(bc)), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0)
if r0 != 0 { if r0 != 0 {
res = syscall.Errno(r0) res = syscall.Errno(r0)
} }
return return
} }
func SHGetPathFromIDListEx(ptr unsafe.Pointer, path *uint16, pathLen int, opts int) (ok bool) { func SHGetPathFromIDListEx(ptr Pointer, path *uint16, pathLen int, opts int) (ok bool) {
r0, _, _ := 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)
ok = r0 != 0 ok = r0 != 0
return return
@ -232,6 +241,12 @@ func ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error)
return return
} }
func CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) {
r0, _, _ := syscall.Syscall6(procCallNextHookEx.Addr(), 4, uintptr(hk), uintptr(code), uintptr(wparam), uintptr(lparam), 0, 0)
ret = uintptr(r0)
return
}
func CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) { func CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) {
var _p0 *byte var _p0 *byte
if len(resBits) > 0 { if len(resBits) > 0 {
@ -460,6 +475,15 @@ func SetWindowText(wnd HWND, text *uint16) (err error) {
return return
} }
func SetWindowsHookEx(idHook int, fn uintptr, mod Handle, threadID uint32) (ret Handle, err error) {
r0, _, e1 := syscall.Syscall6(procSetWindowsHookExW.Addr(), 4, uintptr(idHook), uintptr(fn), uintptr(mod), uintptr(threadID), 0, 0)
ret = Handle(r0)
if ret == 0 {
err = errnoErr(e1)
}
return
}
func ShowWindow(wnd HWND, cmdShow int) (ok bool) { func ShowWindow(wnd HWND, cmdShow int) (ok bool) {
r0, _, _ := syscall.Syscall(procShowWindow.Addr(), 2, uintptr(wnd), uintptr(cmdShow), 0) r0, _, _ := syscall.Syscall(procShowWindow.Addr(), 2, uintptr(wnd), uintptr(cmdShow), 0)
ok = r0 != 0 ok = r0 != 0
@ -480,6 +504,14 @@ func TranslateMessage(msg *MSG) (ok bool) {
return return
} }
func UnhookWindowsHookEx(hk Handle) (err error) {
r1, _, e1 := syscall.Syscall(procUnhookWindowsHookEx.Addr(), 1, uintptr(hk), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func UnregisterClass(className *uint16, instance Handle) (err error) { func UnregisterClass(className *uint16, instance Handle) (err error) {
r1, _, e1 := syscall.Syscall(procUnregisterClassW.Addr(), 2, uintptr(unsafe.Pointer(className)), uintptr(instance), 0) r1, _, e1 := syscall.Syscall(procUnregisterClassW.Addr(), 2, uintptr(unsafe.Pointer(className)), uintptr(instance), 0)
if r1 == 0 { if r1 == 0 {

View file

@ -5,6 +5,7 @@ package zenity
import ( import (
"bytes" "bytes"
"os/exec" "os/exec"
"reflect"
"strconv" "strconv"
"strings" "strings"
@ -98,7 +99,9 @@ func pwdResult(sep string, opts options, out []byte, err error) (string, string,
return "", str, err return "", str, err
} }
func hwnd(i uint64) uintptr { return uintptr(i) } func hwnd(v reflect.Value) uintptr {
return uintptr(v.Uint())
}
// Replace with strings.Cut after 1.18. // Replace with strings.Cut after 1.18.
func cut(s, sep string) (before, after string, found bool) { func cut(s, sep string) (before, after string, found bool) {

View file

@ -13,15 +13,6 @@ import (
"unsafe" "unsafe"
"github.com/ncruces/zenity/internal/win" "github.com/ncruces/zenity/internal/win"
"golang.org/x/sys/windows"
)
var (
user32 = windows.NewLazySystemDLL("user32.dll")
callNextHookEx = user32.NewProc("CallNextHookEx")
setWindowsHookEx = user32.NewProc("SetWindowsHookExW")
unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
) )
const ( const (
@ -32,9 +23,14 @@ const (
_WS_ZEN_BUTTON = _WS_ZEN_CONTROL _WS_ZEN_BUTTON = _WS_ZEN_CONTROL
) )
const nullptr win.Pointer = 0
func intptr(i int64) uintptr { return uintptr(i) } func intptr(i int64) uintptr { return uintptr(i) }
func strptr(s string) *uint16 { return syscall.StringToUTF16Ptr(s) } func strptr(s string) *uint16 { return syscall.StringToUTF16Ptr(s) }
func hwnd(i uint64) win.HWND { return win.HWND(uintptr(i)) }
func hwnd(v reflect.Value) win.HWND {
return win.HWND(uintptr(v.Uint()))
}
func setup() context.CancelFunc { func setup() context.CancelFunc {
var wnd win.HWND var wnd win.HWND
@ -99,7 +95,7 @@ type dialogHook struct {
ctx context.Context ctx context.Context
tid uint32 tid uint32
wnd uintptr wnd uintptr
hook uintptr hook win.Handle
done chan struct{} done chan struct{}
icon any icon any
title *string title *string
@ -108,8 +104,8 @@ type dialogHook struct {
func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd win.HWND)) (*dialogHook, error) { func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd win.HWND)) (*dialogHook, error) {
tid := win.GetCurrentThreadId() tid := win.GetCurrentThreadId()
hk, _, err := setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET hk, err := win.SetWindowsHookEx(win.WH_CALLWNDPROCRET,
syscall.NewCallback(dialogHookProc), 0, uintptr(tid)) syscall.NewCallback(dialogHookProc), 0, tid)
if hk == 0 { if hk == 0 {
return nil, err return nil, err
} }
@ -154,9 +150,7 @@ func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
} }
} }
} }
next, _, _ := callNextHookEx.Call( return win.CallNextHookEx(0, code, wparam, unsafe.Pointer(lparam))
0, uintptr(code), wparam, uintptr(unsafe.Pointer(lparam)))
return next
} }
func (h *dialogHook) unhook() { func (h *dialogHook) unhook() {
@ -164,7 +158,7 @@ func (h *dialogHook) unhook() {
if h.done != nil { if h.done != nil {
close(h.done) close(h.done)
} }
unhookWindowsHookEx.Call(h.hook) win.UnhookWindowsHookEx(h.hook)
} }
func (h *dialogHook) wait() { func (h *dialogHook) wait() {

View file

@ -201,7 +201,7 @@ func Attach(id any) Option {
switch runtime.GOOS { switch runtime.GOOS {
case "windows": case "windows":
if v := reflect.ValueOf(id); v.Kind() == reflect.Uintptr { if v := reflect.ValueOf(id); v.Kind() == reflect.Uintptr {
id = hwnd(v.Uint()) id = hwnd(v)
} else { } else {
panic("interface conversion: expected uintptr") panic("interface conversion: expected uintptr")
} }