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: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
|
||||
|
|
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)
|
||||
}
|
||||
|
||||
func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) {
|
||||
return windows.GetWindowThreadProcessId(hwnd, pid)
|
||||
}
|
||||
|
||||
//sys GetDlgCtrlID(wnd HWND) (ret int) = user32.GetDlgCtrlID
|
||||
//sys SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uintptr) = user32.SendMessageW
|
||||
//sys SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW
|
||||
|
|
|
@ -41,6 +41,7 @@ var (
|
|||
modcomctl32 = windows.NewLazySystemDLL("comctl32.dll")
|
||||
modcomdlg32 = windows.NewLazySystemDLL("comdlg32.dll")
|
||||
modgdi32 = windows.NewLazySystemDLL("gdi32.dll")
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
||||
modshell32 = windows.NewLazySystemDLL("shell32.dll")
|
||||
|
@ -55,6 +56,8 @@ var (
|
|||
procCreateFontIndirectW = modgdi32.NewProc("CreateFontIndirectW")
|
||||
procDeleteObject = modgdi32.NewProc("DeleteObject")
|
||||
procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps")
|
||||
procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow")
|
||||
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
|
||||
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
|
||||
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
|
||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||
|
@ -117,6 +120,21 @@ func GetDeviceCaps(dc Handle, index int) (cap int) {
|
|||
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) {
|
||||
syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(major)), uintptr(unsafe.Pointer(minor)), uintptr(unsafe.Pointer(build)))
|
||||
return
|
||||
|
|
|
@ -20,13 +20,10 @@ var (
|
|||
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
user32 = windows.NewLazySystemDLL("user32.dll")
|
||||
|
||||
activateActCtx = kernel32.NewProc("ActivateActCtx")
|
||||
createActCtx = kernel32.NewProc("CreateActCtxW")
|
||||
deactivateActCtx = kernel32.NewProc("DeactivateActCtx")
|
||||
getConsoleWindow = kernel32.NewProc("GetConsoleWindow")
|
||||
getCurrentThreadId = kernel32.NewProc("GetCurrentThreadId")
|
||||
getModuleHandle = kernel32.NewProc("GetModuleHandleW")
|
||||
getSystemDirectory = kernel32.NewProc("GetSystemDirectoryW")
|
||||
activateActCtx = kernel32.NewProc("ActivateActCtx")
|
||||
createActCtx = kernel32.NewProc("CreateActCtxW")
|
||||
deactivateActCtx = kernel32.NewProc("DeactivateActCtx")
|
||||
getModuleHandle = kernel32.NewProc("GetModuleHandleW")
|
||||
|
||||
callNextHookEx = user32.NewProc("CallNextHookEx")
|
||||
createIconFromResource = user32.NewProc("CreateIconFromResource")
|
||||
|
@ -43,7 +40,6 @@ var (
|
|||
getWindowRect = user32.NewProc("GetWindowRect")
|
||||
getWindowText = user32.NewProc("GetWindowTextW")
|
||||
getWindowTextLength = user32.NewProc("GetWindowTextLengthW")
|
||||
getWindowThreadProcessId = user32.NewProc("GetWindowThreadProcessId")
|
||||
isDialogMessage = user32.NewProc("IsDialogMessageW")
|
||||
loadIcon = user32.NewProc("LoadIconW")
|
||||
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 setup() context.CancelFunc {
|
||||
var wnd uintptr
|
||||
var wnd win.HWND
|
||||
win.EnumWindows(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd)))
|
||||
if wnd == 0 {
|
||||
wnd, _, _ = getConsoleWindow.Call()
|
||||
wnd = win.GetConsoleWindow()
|
||||
}
|
||||
if wnd != 0 {
|
||||
setForegroundWindow.Call(wnd)
|
||||
setForegroundWindow.Call(uintptr(wnd))
|
||||
}
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
@ -118,9 +114,9 @@ func setup() context.CancelFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func setupEnumCallback(wnd uintptr, lparam *uintptr) uintptr {
|
||||
var pid uintptr
|
||||
getWindowThreadProcessId.Call(wnd, uintptr(unsafe.Pointer(&pid)))
|
||||
func setupEnumCallback(wnd win.HWND, lparam *win.HWND) uintptr {
|
||||
var pid uint32
|
||||
win.GetWindowThreadProcessId(wnd, &pid)
|
||||
if int(pid) == os.Getpid() {
|
||||
*lparam = wnd
|
||||
return 0 // stop enumeration
|
||||
|
@ -141,7 +137,7 @@ func hookDialog(ctx context.Context, icon any, title *string, init func(wnd win.
|
|||
|
||||
type dialogHook struct {
|
||||
ctx context.Context
|
||||
tid uintptr
|
||||
tid uint32
|
||||
wnd uintptr
|
||||
hook uintptr
|
||||
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) {
|
||||
tid, _, _ := getCurrentThreadId.Call()
|
||||
tid := win.GetCurrentThreadId()
|
||||
hk, _, err := setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
|
||||
syscall.NewCallback(dialogHookProc), 0, tid)
|
||||
syscall.NewCallback(dialogHookProc), 0, uintptr(tid))
|
||||
if hk == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -171,14 +167,14 @@ func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd w
|
|||
go hook.wait()
|
||||
}
|
||||
|
||||
saveBackRef(tid, unsafe.Pointer(&hook))
|
||||
saveBackRef(uintptr(tid), unsafe.Pointer(&hook))
|
||||
return &hook, nil
|
||||
}
|
||||
|
||||
func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
|
||||
if lparam.Message == 0x0110 { // WM_INITDIALOG
|
||||
tid, _, _ := getCurrentThreadId.Call()
|
||||
hook := (*dialogHook)(loadBackRef(tid))
|
||||
tid := win.GetCurrentThreadId()
|
||||
hook := (*dialogHook)(loadBackRef(uintptr(tid)))
|
||||
atomic.StoreUintptr(&hook.wnd, uintptr(lparam.Wnd))
|
||||
if hook.ctx != nil && hook.ctx.Err() != nil {
|
||||
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() {
|
||||
deleteBackRef(h.tid)
|
||||
deleteBackRef(uintptr(h.tid))
|
||||
if h.done != nil {
|
||||
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
|
||||
func enableVisualStyles() (cookie uintptr) {
|
||||
var dir [260]uint16
|
||||
n, _, _ := getSystemDirectory.Call(uintptr(unsafe.Pointer(&dir[0])), uintptr(len(dir)))
|
||||
if n == 0 || int(n) >= len(dir) {
|
||||
dir, err := win.GetSystemDirectory()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -432,7 +427,7 @@ func enableVisualStyles() (cookie uintptr) {
|
|||
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.Source = syscall.StringToUTF16Ptr("shell32.dll")
|
||||
ctx.AssemblyDirectory = &dir[0]
|
||||
ctx.AssemblyDirectory = syscall.StringToUTF16Ptr(dir)
|
||||
ctx.ResourceName = 124
|
||||
|
||||
if h, _, _ := createActCtx.Call(uintptr(unsafe.Pointer(&ctx))); h != 0 {
|
||||
|
|
Loading…
Reference in a new issue