privacy selector

This commit is contained in:
KingKDot
2026-07-10 23:44:46 -05:00
parent 43ee5a7d4b
commit 9adcbb24a5
9 changed files with 704 additions and 3 deletions
@@ -0,0 +1,54 @@
package privacy
import (
"sync"
"sync/atomic"
)
const inputMarker uintptr = 0x00D5E7B00B5
type Manager struct {
mu sync.Mutex
enabled int32
}
var global = &Manager{}
func Get() *Manager { return global }
func (m *Manager) IsEnabled() bool {
return atomic.LoadInt32(&m.enabled) != 0
}
func (m *Manager) Enable() error {
m.mu.Lock()
defer m.mu.Unlock()
if atomic.LoadInt32(&m.enabled) != 0 {
return nil
}
if err := enablePlatform(); err != nil {
atomic.StoreInt32(&m.enabled, 0)
return err
}
atomic.StoreInt32(&m.enabled, 1)
return nil
}
func (m *Manager) Disable() {
m.mu.Lock()
defer m.mu.Unlock()
if atomic.SwapInt32(&m.enabled, 0) == 0 {
return
}
disablePlatform()
}
func Start() error { return Get().Enable() }
func Stop() { Get().Disable() }
func IsEnabled() bool { return Get().IsEnabled() }
func InputMarker() uintptr { return inputMarker }
@@ -0,0 +1,11 @@
//go:build !windows
package privacy
import "errors"
func enablePlatform() error {
return errors.New("privacy mode is only supported on Windows")
}
func disablePlatform() {}
@@ -0,0 +1,530 @@
//go:build windows
package privacy
import (
"log"
"runtime"
"sync"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
const (
WS_EX_TOPMOST = 0x00000008
WS_EX_TOOLWINDOW = 0x00000080
WS_EX_NOACTIVATE = 0x08000000
WS_EX_TRANSPARENT = 0x00000020
WS_EX_LAYERED = 0x00080000
WS_POPUP = 0x80000000
WS_VISIBLE = 0x10000000
WDA_EXCLUDEFROMCAPTURE = 0x00000011
WH_KEYBOARD_LL = 13
WH_MOUSE_LL = 14
WM_QUIT = 0x0012
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
WM_SYSKEYDOWN = 0x0104
WM_SYSKEYUP = 0x0105
LLKHF_INJECTED = 0x00000010
LLMHF_INJECTED = 0x00000001
VK_CONTROL = 0x11
VK_P = 0x50
VK_LCONTROL = 0xA2
VK_RCONTROL = 0xA3
SW_HIDE = 0
SW_SHOW = 5
SWP_NOSIZE = 0x0001
SWP_NOMOVE = 0x0002
SWP_NOACTIVATE = 0x0010
SWP_SHOWWINDOW = 0x0040
LWA_ALPHA = 0x00000002
SM_XVIRTUALSCREEN = 76
SM_YVIRTUALSCREEN = 77
SM_CXVIRTUALSCREEN = 78
SM_CYVIRTUALSCREEN = 79
)
var (
user32 = syscall.NewLazyDLL("user32.dll")
procCreateWindowExW = user32.NewProc("CreateWindowExW")
procDefWindowProcW = user32.NewProc("DefWindowProcW")
procDestroyWindow = user32.NewProc("DestroyWindow")
procGetMessageW = user32.NewProc("GetMessageW")
procTranslateMessage = user32.NewProc("TranslateMessage")
procDispatchMessageW = user32.NewProc("DispatchMessageW")
procPostThreadMessageW = user32.NewProc("PostThreadMessageW")
procRegisterClassExW = user32.NewProc("RegisterClassExW")
procSetWindowDisplayAffinity = user32.NewProc("SetWindowDisplayAffinity")
procSetWindowsHookExW = user32.NewProc("SetWindowsHookExW")
procUnhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
procCallNextHookEx = user32.NewProc("CallNextHookEx")
procShowWindow = user32.NewProc("ShowWindow")
procUpdateWindow = user32.NewProc("UpdateWindow")
procSetWindowPos = user32.NewProc("SetWindowPos")
procSetLayeredWindowAttributes = user32.NewProc("SetLayeredWindowAttributes")
procEnumDisplayMonitors = user32.NewProc("EnumDisplayMonitors")
procShowCursor = user32.NewProc("ShowCursor")
procGetSystemMetrics = user32.NewProc("GetSystemMetrics")
procGetAsyncKeyState = user32.NewProc("GetAsyncKeyState")
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetModuleHandleW = kernel32.NewProc("GetModuleHandleW")
procGetCurrentThreadID = kernel32.NewProc("GetCurrentThreadId")
gdi32 = syscall.NewLazyDLL("gdi32.dll")
procCreateSolidBrush = gdi32.NewProc("CreateSolidBrush")
keyboardHook uintptr
mouseHook uintptr
privacyWindows []windows.HWND
privacyWindowsMu sync.Mutex
platformMu sync.Mutex
platform *platformState
cursorHideOps int
ctrlPressed bool
)
type platformState struct {
ready chan error
done chan struct{}
threadID uint32
}
type wndClassExW struct {
cbSize uint32
style uint32
lpfnWndProc uintptr
cbClsExtra int32
cbWndExtra int32
hInstance windows.Handle
hIcon windows.Handle
hCursor windows.Handle
hbrBackground windows.Handle
lpszMenuName *uint16
lpszClassName *uint16
hIconSm windows.Handle
}
type point struct {
x int32
y int32
}
type msg struct {
hwnd windows.HWND
message uint32
wParam uintptr
lParam uintptr
time uint32
pt point
}
type kbdllhookstruct struct {
vkCode uint32
scanCode uint32
flags uint32
time uint32
dwExtraInfo uintptr
}
type msllhookstruct struct {
pt point
mouseData uint32
flags uint32
time uint32
dwExtraInfo uintptr
}
func enablePlatform() error {
platformMu.Lock()
if platform != nil {
platformMu.Unlock()
return nil
}
st := &platformState{
ready: make(chan error, 1),
done: make(chan struct{}),
}
platform = st
go runPlatformThread(st)
platformMu.Unlock()
if err := <-st.ready; err != nil {
platformMu.Lock()
if platform == st {
platform = nil
}
platformMu.Unlock()
return err
}
return nil
}
func disablePlatform() {
platformMu.Lock()
st := platform
platform = nil
platformMu.Unlock()
if st == nil {
return
}
if st.threadID != 0 {
procPostThreadMessageW.Call(uintptr(st.threadID), WM_QUIT, 0, 0)
}
<-st.done
}
func runPlatformThread(st *platformState) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
defer close(st.done)
st.threadID = currentThreadID()
if err := createPrivacyWindows(); err != nil {
st.ready <- err
return
}
if err := installInputHooks(); err != nil {
destroyPrivacyWindows()
st.ready <- err
return
}
hideCursor()
st.ready <- nil
messagePump()
restoreCursor()
uninstallInputHooks()
destroyPrivacyWindows()
}
func currentThreadID() uint32 {
ret, _, _ := procGetCurrentThreadID.Call()
return uint32(ret)
}
func createPrivacyWindows() error {
className, err := syscall.UTF16PtrFromString("OverlordPrivacyWindow")
if err != nil {
return err
}
hInstance := getModuleHandle()
brush, _, _ := procCreateSolidBrush.Call(0x00000000)
wndClass := wndClassExW{
cbSize: uint32(unsafe.Sizeof(wndClassExW{})),
style: 0,
lpfnWndProc: syscall.NewCallback(defWindowProcCallback),
hInstance: windows.Handle(hInstance),
hCursor: 0,
hbrBackground: windows.Handle(brush),
lpszClassName: className,
}
ret, _, _ := procRegisterClassExW.Call(uintptr(unsafe.Pointer(&wndClass)))
if ret == 0 {
if err := syscall.GetLastError(); err != windows.ERROR_CLASS_ALREADY_EXISTS {
return err
}
}
monitors := enumerateMonitors()
if len(monitors) == 0 {
left := getSystemMetric(SM_XVIRTUALSCREEN)
top := getSystemMetric(SM_YVIRTUALSCREEN)
width := getSystemMetric(SM_CXVIRTUALSCREEN)
height := getSystemMetric(SM_CYVIRTUALSCREEN)
if width > 0 && height > 0 {
monitors = append(monitors, monitorRect{
left: left,
top: top,
right: left + width,
bottom: top + height,
})
}
}
for _, mon := range monitors {
hwnd, _, _ := procCreateWindowExW.Call(
uintptr(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_NOACTIVATE|WS_EX_TRANSPARENT|WS_EX_LAYERED),
uintptr(unsafe.Pointer(className)),
0,
uintptr(WS_POPUP|WS_VISIBLE),
uintptr(mon.left),
uintptr(mon.top),
uintptr(mon.right-mon.left),
uintptr(mon.bottom-mon.top),
0, 0, uintptr(hInstance), 0,
)
if hwnd == 0 {
log.Printf("privacy: failed to create window for monitor [%d %d %d %d]: %v",
mon.left, mon.top, mon.right, mon.bottom, syscall.GetLastError())
continue
}
procSetWindowDisplayAffinity.Call(hwnd, uintptr(WDA_EXCLUDEFROMCAPTURE))
procSetLayeredWindowAttributes.Call(hwnd, 0, 255, uintptr(LWA_ALPHA))
procSetWindowPos.Call(
hwnd,
^uintptr(0),
uintptr(mon.left),
uintptr(mon.top),
uintptr(mon.right-mon.left),
uintptr(mon.bottom-mon.top),
uintptr(SWP_NOACTIVATE|SWP_SHOWWINDOW),
)
procShowWindow.Call(hwnd, SW_SHOW)
procUpdateWindow.Call(hwnd)
privacyWindowsMu.Lock()
privacyWindows = append(privacyWindows, windows.HWND(hwnd))
privacyWindowsMu.Unlock()
}
if len(privacyWindows) == 0 {
return syscall.GetLastError()
}
log.Printf("privacy: created %d privacy window(s)", len(privacyWindows))
return nil
}
func getSystemMetric(index int32) int32 {
ret, _, _ := procGetSystemMetrics.Call(uintptr(index))
return int32(ret)
}
func hideCursor() {
cursorHideOps = 0
for {
count := showCursor(false)
cursorHideOps++
if count < 0 || cursorHideOps > 32 {
break
}
}
}
func restoreCursor() {
for i := 0; i < cursorHideOps; i++ {
showCursor(true)
}
cursorHideOps = 0
}
func showCursor(show bool) int32 {
arg := uintptr(0)
if show {
arg = 1
}
ret, _, _ := procShowCursor.Call(arg)
return int32(ret)
}
func destroyPrivacyWindows() {
privacyWindowsMu.Lock()
windows := privacyWindows
privacyWindows = nil
privacyWindowsMu.Unlock()
for _, hwnd := range windows {
procShowWindow.Call(uintptr(hwnd), SW_HIDE)
procDestroyWindow.Call(uintptr(hwnd))
}
log.Printf("privacy: destroyed %d privacy window(s)", len(windows))
}
type monitorRect struct {
left, top, right, bottom int32
}
func enumerateMonitors() []monitorRect {
var monitors []monitorRect
var mu sync.Mutex
cb := syscall.NewCallback(func(hMonitor, hdc, lprcMonitor, lparam uintptr) uintptr {
rc := (*rect)(unsafe.Pointer(lprcMonitor))
mu.Lock()
monitors = append(monitors, monitorRect{
left: rc.left,
top: rc.top,
right: rc.right,
bottom: rc.bottom,
})
mu.Unlock()
return 1
})
procEnumDisplayMonitors.Call(0, 0, cb, 0)
return monitors
}
type rect struct {
left int32
top int32
right int32
bottom int32
}
func defWindowProcCallback(hwnd windows.HWND, msg uint32, wParam uintptr, lParam uintptr) uintptr {
ret, _, _ := procDefWindowProcW.Call(uintptr(hwnd), uintptr(msg), wParam, lParam)
return ret
}
func getModuleHandle() windows.Handle {
ret, _, _ := procGetModuleHandleW.Call(0)
return windows.Handle(ret)
}
func installInputHooks() error {
hInstance := getModuleHandle()
kbCb := syscall.NewCallback(keyboardHookProc)
kh, _, err := procSetWindowsHookExW.Call(
uintptr(WH_KEYBOARD_LL),
kbCb,
uintptr(hInstance),
0,
)
if kh == 0 {
return err
}
keyboardHook = kh
mCb := syscall.NewCallback(mouseHookProc)
mh, _, err := procSetWindowsHookExW.Call(
uintptr(WH_MOUSE_LL),
mCb,
uintptr(hInstance),
0,
)
if mh == 0 {
procUnhookWindowsHookEx.Call(keyboardHook)
keyboardHook = 0
return err
}
mouseHook = mh
log.Printf("privacy: input hooks installed (kb=%d mouse=%d)", keyboardHook, mouseHook)
return nil
}
func uninstallInputHooks() {
if keyboardHook != 0 {
procUnhookWindowsHookEx.Call(keyboardHook)
keyboardHook = 0
}
if mouseHook != 0 {
procUnhookWindowsHookEx.Call(mouseHook)
mouseHook = 0
}
log.Printf("privacy: input hooks removed")
}
func keyboardHookProc(nCode int, wParam uintptr, lParam uintptr) uintptr {
if nCode < 0 {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
m := Get()
if !m.IsEnabled() {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
kb := (*kbdllhookstruct)(unsafe.Pointer(lParam))
if kb.dwExtraInfo == InputMarker() {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
if kb.flags&LLKHF_INJECTED != 0 {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
switch kb.vkCode {
case VK_CONTROL, VK_LCONTROL, VK_RCONTROL:
if wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN {
ctrlPressed = true
} else {
ctrlPressed = false
}
return 1
}
return 1
}
func mouseHookProc(nCode int, wParam uintptr, lParam uintptr) uintptr {
if nCode < 0 {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
if !Get().IsEnabled() {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
ms := (*msllhookstruct)(unsafe.Pointer(lParam))
if ms.dwExtraInfo == InputMarker() {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
if ms.flags&LLMHF_INJECTED != 0 {
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
return ret
}
return 1
}
func messagePump() {
log.Printf("privacy: message pump starting")
var m msg
for {
ret, _, _ := procGetMessageW.Call(
uintptr(unsafe.Pointer(&m)),
0, 0, 0,
)
if ret == 0 || ret == ^uintptr(0) {
break
}
procTranslateMessage.Call(uintptr(unsafe.Pointer(&m)))
procDispatchMessageW.Call(uintptr(unsafe.Pointer(&m)))
}
log.Printf("privacy: message pump stopped")
}