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)
var ptr unsafe.Pointer
var ptr win.Pointer
hr, _, _ = item.Call(item.GetDisplayName,
_SIGDN_FILESYSPATH, uintptr(unsafe.Pointer(&ptr)))
if int32(hr) < 0 {
@ -337,7 +337,7 @@ func browseForFolder(opts options) (string, []string, error) {
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", nil, opts.ctx.Err()
}
if ptr == nil {
if ptr == nullptr {
return "", nil, ErrCanceled
}
defer win.CoTaskMemFree(ptr)

View file

@ -31,8 +31,6 @@ func CoInitializeEx(reserved uintptr, coInit uint32) error {
func CoUninitialize() { windows.CoUninitialize() }
func CoTaskMemFree(address unsafe.Pointer) { windows.CoTaskMemFree(address) }
// https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl
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
}
//sys SHBrowseForFolder(bi *BROWSEINFO) (ret unsafe.Pointer) = shell32.SHBrowseForFolder
//sys SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName
//sys SHBrowseForFolder(bi *BROWSEINFO) (ret Pointer) = shell32.SHBrowseForFolder
//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 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_CONTEXTHELP = 0xf180
// SetWindowsHookEx types
WH_CALLWNDPROCRET = 12
USER_DEFAULT_SCREEN_DPI = 96
DPI_AWARENESS_CONTEXT_UNAWARE = ^uintptr(1) + 1
@ -350,12 +353,13 @@ type NONCLIENTMETRICS struct {
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 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 DestroyWindow(wnd HWND) (err error) = user32.DestroyWindow
//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 EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) = 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 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 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 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 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

View file

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

View file

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

View file

@ -5,6 +5,7 @@ package zenity
import (
"bytes"
"os/exec"
"reflect"
"strconv"
"strings"
@ -98,7 +99,9 @@ func pwdResult(sep string, opts options, out []byte, err error) (string, string,
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.
func cut(s, sep string) (before, after string, found bool) {

View file

@ -13,15 +13,6 @@ import (
"unsafe"
"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 (
@ -32,9 +23,14 @@ const (
_WS_ZEN_BUTTON = _WS_ZEN_CONTROL
)
const nullptr win.Pointer = 0
func intptr(i int64) uintptr { return uintptr(i) }
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 {
var wnd win.HWND
@ -99,7 +95,7 @@ type dialogHook struct {
ctx context.Context
tid uint32
wnd uintptr
hook uintptr
hook win.Handle
done chan struct{}
icon any
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) {
tid := win.GetCurrentThreadId()
hk, _, err := setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
syscall.NewCallback(dialogHookProc), 0, uintptr(tid))
hk, err := win.SetWindowsHookEx(win.WH_CALLWNDPROCRET,
syscall.NewCallback(dialogHookProc), 0, tid)
if hk == 0 {
return nil, err
}
@ -154,9 +150,7 @@ func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
}
}
}
next, _, _ := callNextHookEx.Call(
0, uintptr(code), wparam, uintptr(unsafe.Pointer(lparam)))
return next
return win.CallNextHookEx(0, code, wparam, unsafe.Pointer(lparam))
}
func (h *dialogHook) unhook() {
@ -164,7 +158,7 @@ func (h *dialogHook) unhook() {
if h.done != nil {
close(h.done)
}
unhookWindowsHookEx.Call(h.hook)
win.UnhookWindowsHookEx(h.hook)
}
func (h *dialogHook) wait() {

View file

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