Refactor (windows).
This commit is contained in:
parent
971520115f
commit
4bfddad741
5 changed files with 54 additions and 26 deletions
|
@ -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 win32.go wtsapi32.go
|
//go:generate mkwinsyscall comctl32.go comdlg32.go gdi32.go kernel32.go ole32.go shell32.go user32.go win32.go wtsapi32.go
|
||||||
|
|
||||||
package win
|
package win
|
||||||
|
|
11
internal/win/kernel32.go
Normal file
11
internal/win/kernel32.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package win
|
||||||
|
|
||||||
|
import "golang.org/x/sys/windows"
|
||||||
|
|
||||||
|
func GetCurrentThreadId() (id uint32) { return windows.GetCurrentThreadId() }
|
||||||
|
func GetSystemDirectory() (string, error) { return windows.GetSystemDirectory() }
|
||||||
|
|
||||||
|
//sys GetConsoleWindow() (ret HWND) = kernel32.GetConsoleWindow
|
||||||
|
//sys GetModuleHandle(moduleName *uint16) (ret Handle, err error) = kernel32.GetModuleHandleW
|
|
@ -55,6 +55,10 @@ func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret i
|
||||||
return windows.MessageBox(hwnd, text, caption, boxtype)
|
return windows.MessageBox(hwnd, text, caption, boxtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) {
|
||||||
|
return windows.GetWindowThreadProcessId(hwnd, pid)
|
||||||
|
}
|
||||||
|
|
||||||
//sys GetDlgCtrlID(wnd HWND) (ret int) = user32.GetDlgCtrlID
|
//sys GetDlgCtrlID(wnd HWND) (ret int) = user32.GetDlgCtrlID
|
||||||
//sys SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uintptr) = user32.SendMessageW
|
//sys SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uintptr) = user32.SendMessageW
|
||||||
//sys SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW
|
//sys SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW
|
||||||
|
|
|
@ -41,6 +41,7 @@ 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")
|
||||||
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
modntdll = windows.NewLazySystemDLL("ntdll.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")
|
||||||
|
@ -55,6 +56,8 @@ 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")
|
||||||
|
procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow")
|
||||||
|
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
|
||||||
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
|
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
|
||||||
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
|
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
|
||||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||||
|
@ -117,6 +120,21 @@ func GetDeviceCaps(dc Handle, index int) (cap int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetConsoleWindow() (ret HWND) {
|
||||||
|
r0, _, _ := syscall.Syscall(procGetConsoleWindow.Addr(), 0, 0, 0, 0)
|
||||||
|
ret = HWND(r0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetModuleHandle(moduleName *uint16) (ret Handle, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(procGetModuleHandleW.Addr(), 1, uintptr(unsafe.Pointer(moduleName)), 0, 0)
|
||||||
|
ret = Handle(r0)
|
||||||
|
if ret == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func RtlGetNtVersionNumbers(major *uint32, minor *uint32, build *uint32) {
|
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)))
|
syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(major)), uintptr(unsafe.Pointer(minor)), uintptr(unsafe.Pointer(build)))
|
||||||
return
|
return
|
||||||
|
|
|
@ -23,10 +23,7 @@ var (
|
||||||
activateActCtx = kernel32.NewProc("ActivateActCtx")
|
activateActCtx = kernel32.NewProc("ActivateActCtx")
|
||||||
createActCtx = kernel32.NewProc("CreateActCtxW")
|
createActCtx = kernel32.NewProc("CreateActCtxW")
|
||||||
deactivateActCtx = kernel32.NewProc("DeactivateActCtx")
|
deactivateActCtx = kernel32.NewProc("DeactivateActCtx")
|
||||||
getConsoleWindow = kernel32.NewProc("GetConsoleWindow")
|
|
||||||
getCurrentThreadId = kernel32.NewProc("GetCurrentThreadId")
|
|
||||||
getModuleHandle = kernel32.NewProc("GetModuleHandleW")
|
getModuleHandle = kernel32.NewProc("GetModuleHandleW")
|
||||||
getSystemDirectory = kernel32.NewProc("GetSystemDirectoryW")
|
|
||||||
|
|
||||||
callNextHookEx = user32.NewProc("CallNextHookEx")
|
callNextHookEx = user32.NewProc("CallNextHookEx")
|
||||||
createIconFromResource = user32.NewProc("CreateIconFromResource")
|
createIconFromResource = user32.NewProc("CreateIconFromResource")
|
||||||
|
@ -43,7 +40,6 @@ var (
|
||||||
getWindowRect = user32.NewProc("GetWindowRect")
|
getWindowRect = user32.NewProc("GetWindowRect")
|
||||||
getWindowText = user32.NewProc("GetWindowTextW")
|
getWindowText = user32.NewProc("GetWindowTextW")
|
||||||
getWindowTextLength = user32.NewProc("GetWindowTextLengthW")
|
getWindowTextLength = user32.NewProc("GetWindowTextLengthW")
|
||||||
getWindowThreadProcessId = user32.NewProc("GetWindowThreadProcessId")
|
|
||||||
isDialogMessage = user32.NewProc("IsDialogMessageW")
|
isDialogMessage = user32.NewProc("IsDialogMessageW")
|
||||||
loadIcon = user32.NewProc("LoadIconW")
|
loadIcon = user32.NewProc("LoadIconW")
|
||||||
loadImage = user32.NewProc("LoadImageW")
|
loadImage = user32.NewProc("LoadImageW")
|
||||||
|
@ -76,13 +72,13 @@ func strptr(s string) uintptr {
|
||||||
func hwnd(i uint64) win.HWND { return win.HWND(uintptr(i)) }
|
func hwnd(i uint64) win.HWND { return win.HWND(uintptr(i)) }
|
||||||
|
|
||||||
func setup() context.CancelFunc {
|
func setup() context.CancelFunc {
|
||||||
var wnd uintptr
|
var wnd win.HWND
|
||||||
win.EnumWindows(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd)))
|
win.EnumWindows(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd)))
|
||||||
if wnd == 0 {
|
if wnd == 0 {
|
||||||
wnd, _, _ = getConsoleWindow.Call()
|
wnd = win.GetConsoleWindow()
|
||||||
}
|
}
|
||||||
if wnd != 0 {
|
if wnd != 0 {
|
||||||
setForegroundWindow.Call(wnd)
|
setForegroundWindow.Call(uintptr(wnd))
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
|
@ -118,9 +114,9 @@ func setup() context.CancelFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupEnumCallback(wnd uintptr, lparam *uintptr) uintptr {
|
func setupEnumCallback(wnd win.HWND, lparam *win.HWND) uintptr {
|
||||||
var pid uintptr
|
var pid uint32
|
||||||
getWindowThreadProcessId.Call(wnd, uintptr(unsafe.Pointer(&pid)))
|
win.GetWindowThreadProcessId(wnd, &pid)
|
||||||
if int(pid) == os.Getpid() {
|
if int(pid) == os.Getpid() {
|
||||||
*lparam = wnd
|
*lparam = wnd
|
||||||
return 0 // stop enumeration
|
return 0 // stop enumeration
|
||||||
|
@ -141,7 +137,7 @@ func hookDialog(ctx context.Context, icon any, title *string, init func(wnd win.
|
||||||
|
|
||||||
type dialogHook struct {
|
type dialogHook struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
tid uintptr
|
tid uint32
|
||||||
wnd uintptr
|
wnd uintptr
|
||||||
hook uintptr
|
hook uintptr
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
|
@ -151,9 +147,9 @@ 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, _, _ := getCurrentThreadId.Call()
|
tid := win.GetCurrentThreadId()
|
||||||
hk, _, err := setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
|
hk, _, err := setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
|
||||||
syscall.NewCallback(dialogHookProc), 0, tid)
|
syscall.NewCallback(dialogHookProc), 0, uintptr(tid))
|
||||||
if hk == 0 {
|
if hk == 0 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -171,14 +167,14 @@ func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd w
|
||||||
go hook.wait()
|
go hook.wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
saveBackRef(tid, unsafe.Pointer(&hook))
|
saveBackRef(uintptr(tid), unsafe.Pointer(&hook))
|
||||||
return &hook, nil
|
return &hook, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
|
func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
|
||||||
if lparam.Message == 0x0110 { // WM_INITDIALOG
|
if lparam.Message == 0x0110 { // WM_INITDIALOG
|
||||||
tid, _, _ := getCurrentThreadId.Call()
|
tid := win.GetCurrentThreadId()
|
||||||
hook := (*dialogHook)(loadBackRef(tid))
|
hook := (*dialogHook)(loadBackRef(uintptr(tid)))
|
||||||
atomic.StoreUintptr(&hook.wnd, uintptr(lparam.Wnd))
|
atomic.StoreUintptr(&hook.wnd, uintptr(lparam.Wnd))
|
||||||
if hook.ctx != nil && hook.ctx.Err() != nil {
|
if hook.ctx != nil && hook.ctx.Err() != nil {
|
||||||
win.SendMessage(lparam.Wnd, win.WM_SYSCOMMAND, _SC_CLOSE, 0)
|
win.SendMessage(lparam.Wnd, win.WM_SYSCOMMAND, _SC_CLOSE, 0)
|
||||||
|
@ -204,7 +200,7 @@ func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *dialogHook) unhook() {
|
func (h *dialogHook) unhook() {
|
||||||
deleteBackRef(h.tid)
|
deleteBackRef(uintptr(h.tid))
|
||||||
if h.done != nil {
|
if h.done != nil {
|
||||||
close(h.done)
|
close(h.done)
|
||||||
}
|
}
|
||||||
|
@ -422,9 +418,8 @@ func messageLoop(wnd uintptr) error {
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/4308503/how-to-enable-visual-styles-without-a-manifest
|
// https://stackoverflow.com/questions/4308503/how-to-enable-visual-styles-without-a-manifest
|
||||||
func enableVisualStyles() (cookie uintptr) {
|
func enableVisualStyles() (cookie uintptr) {
|
||||||
var dir [260]uint16
|
dir, err := win.GetSystemDirectory()
|
||||||
n, _, _ := getSystemDirectory.Call(uintptr(unsafe.Pointer(&dir[0])), uintptr(len(dir)))
|
if err != nil {
|
||||||
if n == 0 || int(n) >= len(dir) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +427,7 @@ func enableVisualStyles() (cookie uintptr) {
|
||||||
ctx.Size = uint32(unsafe.Sizeof(ctx))
|
ctx.Size = uint32(unsafe.Sizeof(ctx))
|
||||||
ctx.Flags = 0x01c // ACTCTX_FLAG_RESOURCE_NAME_VALID|ACTCTX_FLAG_SET_PROCESS_DEFAULT|ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
|
ctx.Flags = 0x01c // ACTCTX_FLAG_RESOURCE_NAME_VALID|ACTCTX_FLAG_SET_PROCESS_DEFAULT|ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
|
||||||
ctx.Source = syscall.StringToUTF16Ptr("shell32.dll")
|
ctx.Source = syscall.StringToUTF16Ptr("shell32.dll")
|
||||||
ctx.AssemblyDirectory = &dir[0]
|
ctx.AssemblyDirectory = syscall.StringToUTF16Ptr(dir)
|
||||||
ctx.ResourceName = 124
|
ctx.ResourceName = 124
|
||||||
|
|
||||||
if h, _, _ := createActCtx.Call(uintptr(unsafe.Pointer(&ctx))); h != 0 {
|
if h, _, _ := createActCtx.Call(uintptr(unsafe.Pointer(&ctx))); h != 0 {
|
||||||
|
|
Loading…
Reference in a new issue