70 lines
2.3 KiB
Go
70 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
var user32 = syscall.NewLazyDLL("user32.dll")
|
|
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
|
|
func configureProcess(c *exec.Cmd) {
|
|
c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
|
user32.NewProc("SetThreadDpiAwarenessContext").Call(^uintptr(3))
|
|
}
|
|
func windowOwned(pid, hwnd int64) bool {
|
|
var actual uint32
|
|
r, _, _ := user32.NewProc("IsWindow").Call(uintptr(hwnd))
|
|
if r == 0 {
|
|
return false
|
|
}
|
|
user32.NewProc("GetWindowThreadProcessId").Call(uintptr(hwnd), uintptr(unsafe.Pointer(&actual)))
|
|
return int64(actual) == pid
|
|
}
|
|
func verifyWindow(pid, hwnd int64, b obj) (obj, bool) {
|
|
if !windowOwned(pid, hwnd) {
|
|
return nil, false
|
|
}
|
|
var r struct{ L, T, R, B int32 }
|
|
code, _, _ := syscall.NewLazyDLL("dwmapi.dll").NewProc("DwmGetWindowAttribute").Call(uintptr(hwnd), 9, uintptr(unsafe.Pointer(&r)), unsafe.Sizeof(r))
|
|
if code != 0 {
|
|
return nil, false
|
|
}
|
|
// Cua uses DWM physical bounds; refuse evidence after a window move/resize.
|
|
if int64(r.L) != num(b["left"]) || int64(r.T) != num(b["top"]) || int64(r.R-r.L) != num(b["width"]) || int64(r.B-r.T) != num(b["height"]) {
|
|
return nil, false
|
|
}
|
|
metric := func(n uintptr) int64 { x, _, _ := user32.NewProc("GetSystemMetrics").Call(n); return int64(int32(x)) }
|
|
return obj{"left": metric(76), "top": metric(77), "width": metric(78), "height": metric(79)}, true
|
|
}
|
|
func ownProcess(pid int) (uintptr, error) {
|
|
job, _, e := kernel32.NewProc("CreateJobObjectW").Call(0, 0)
|
|
if job == 0 {
|
|
return 0, e
|
|
}
|
|
// JOBOBJECT_EXTENDED_LIMIT_INFORMATION, Windows x64. Kill the entire owned
|
|
// child tree when the adapter dies, including Cua's UIA helper.
|
|
data := make([]byte, 144)
|
|
*(*uint32)(unsafe.Pointer(&data[16])) = 0x2000
|
|
ok, _, _ := kernel32.NewProc("SetInformationJobObject").Call(job, 9, uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)))
|
|
h, _, _ := kernel32.NewProc("OpenProcess").Call(0x0101, 0, uintptr(pid))
|
|
if h == 0 || ok == 0 {
|
|
closeJob(job)
|
|
return 0, fmt.Errorf("cannot own driver process")
|
|
}
|
|
defer kernel32.NewProc("CloseHandle").Call(h)
|
|
ok, _, e = kernel32.NewProc("AssignProcessToJobObject").Call(job, h)
|
|
if ok == 0 {
|
|
closeJob(job)
|
|
return 0, e
|
|
}
|
|
return job, nil
|
|
}
|
|
func closeJob(h uintptr) {
|
|
if h != 0 {
|
|
kernel32.NewProc("CloseHandle").Call(h)
|
|
}
|
|
}
|