master
John Lauer v2.0.382 (insiders): Insiders tier, corrected to the fleet convention (John: a separate private page is wiki-bloat): th… e7b1214 2mo ago
'use strict';
// In-process Win32 calls for window identity (v2.0.310). John: "i frown upon running powershell
// scripts cuz they're heavy and slow." Every PowerShell spawn cost a process + an Add-Type compile
// (hundreds of ms). These are direct user32 calls through koffi (prebuilt FFI, no build step): a
// SetProp or a full EnumWindows+GetProp sweep is microseconds, synchronous, and leaves no trace in
// ab's activity log. Identity doctrine (dev-skills/pup-no-wiggle): the window PROPERTY is the id.
//
// Every export degrades to null/false when koffi is unavailable (non-Windows, or the module failed
// to install), so callers can fall back to the PowerShell path and nothing hard-fails.

// Call accounting (John, 2026-08-23: moving calls out of ab's activity log removes his radar for
// misbehaving loops, so every in-process Win32 call is counted here and reported on /status).
const calls = {};
function tick(name) { calls[name] = (calls[name] || 0) + 1; }
function stats() { return { ...calls }; }
let user32 = null;
let fn = null;
let loadError = null;

function load() {
  if (fn || loadError) return !!fn;
  if (process.platform !== 'win32') { loadError = 'not win32'; return false; }
  try {
    const koffi = require('koffi');
    user32 = koffi.load('user32.dll');
    const EnumProc = koffi.proto('bool __stdcall PupEnumProc(intptr_t hwnd, intptr_t lparam)');
    fn = {
      koffi,
      SetPropW: user32.func('bool __stdcall SetPropW(intptr_t hwnd, const char16_t* name, intptr_t data)'),
      GetPropW: user32.func('intptr_t __stdcall GetPropW(intptr_t hwnd, const char16_t* name)'),
      RemovePropW: user32.func('intptr_t __stdcall RemovePropW(intptr_t hwnd, const char16_t* name)'),
      EnumWindows: user32.func('bool __stdcall EnumWindows(PupEnumProc* cb, intptr_t lparam)'),
      IsWindow: user32.func('bool __stdcall IsWindow(intptr_t hwnd)'),
      GetWindowThreadProcessId: user32.func('uint32_t __stdcall GetWindowThreadProcessId(intptr_t hwnd, _Out_ uint32_t* pid)'),
      GetWindowTextW: user32.func('int __stdcall GetWindowTextW(intptr_t hwnd, void* buf, int n)'),
      GetClassNameW: user32.func('int __stdcall GetClassNameW(intptr_t hwnd, void* buf, int n)'),
      IsWindowVisible: user32.func('bool __stdcall IsWindowVisible(intptr_t hwnd)'),
      IsIconic: user32.func('bool __stdcall IsIconic(intptr_t hwnd)'),
      ShowWindow: user32.func('bool __stdcall ShowWindow(intptr_t hwnd, int cmd)'),
      GetWindowLongW: user32.func('int32_t __stdcall GetWindowLongW(intptr_t hwnd, int idx)'),
      GetSystemMetrics: user32.func('int __stdcall GetSystemMetrics(int idx)'),
      SetWindowPos: user32.func('bool __stdcall SetWindowPos(intptr_t hwnd, intptr_t after, int x, int y, int cx, int cy, uint32_t flags)'),
      GetWindowRect: user32.func('bool __stdcall GetWindowRect(intptr_t hwnd, void* rect)'),
      GetWindowPlacement: user32.func('bool __stdcall GetWindowPlacement(intptr_t hwnd, void* wp)'),
      EnumProc,
    };
    return true;
  } catch (e) { loadError = e && e.message ? e.message : String(e); fn = null; return false; }
}

// Tag a window with a named property (value 1). The property lives with the window, in Chrome's
// process, so it outlives pup restarts. Returns true on success, null when koffi is unavailable.
function setProp(hwnd, name) {
  if (!load()) return null; tick('SetProp');
  try { return !!fn.SetPropW(Number(hwnd), String(name), 1); } catch (e) { return false; }
}

function hasProp(hwnd, name) {
  if (!load()) return null; tick('GetProp');
  try { return Number(fn.GetPropW(Number(hwnd), String(name))) !== 0; } catch (e) { return false; }
}

function removeProp(hwnd, name) {
  if (!load()) return null; tick('RemoveProp');
  try { fn.RemovePropW(Number(hwnd), String(name)); return true; } catch (e) { return false; }
}

function isWindow(hwnd) {
  if (!load()) return null; tick('IsWindow');
  try { return !!fn.IsWindow(Number(hwnd)); } catch (e) { return false; }
}

function windowPid(hwnd) {
  if (!load()) return null;
  try { const out = [0]; fn.GetWindowThreadProcessId(Number(hwnd), out); return Number(out[0]) || null; } catch (e) { return null; }
}

// Find the ONE top-level window carrying the property. Only pup ever sets these names, so no class
// or geometry test is needed: the property IS the proof. Returns the hwnd, 0 when none, null when
// koffi is unavailable.
function findWindowByProp(name) {
  if (!load()) return null; tick('EnumWindows:byProp');
  let found = 0;
  const cb = fn.koffi.register((hwnd) => {
    try { if (Number(fn.GetPropW(Number(hwnd), String(name))) !== 0) { found = Number(hwnd); return false; } } catch (e) {}
    return true;
  }, fn.koffi.pointer(fn.EnumProc));
  try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }
  return found;
}

// Rebuild the whole sessionId -> hwnd map in one sweep: every top-level window whose property
// name starts with the prefix. Used at recovery so a restart never enumerates more than once.
function findAllByPropPrefix(prefix, candidates) {
  tick('EnumWindows:allByProp');
  // Win32 has no "list my props by prefix" without EnumPropsEx; callers pass the sessionIds they
  // want resolved (cheap: one GetProp per (window, sessionId) pair, all in-process).
  if (!load()) return null;
  const out = new Map();
  const names = candidates.map(s => [s, prefix + s]);
  const cb = fn.koffi.register((hwnd) => {
    for (const [sid, nm] of names) {
      try { if (!out.has(sid) && Number(fn.GetPropW(Number(hwnd), nm)) !== 0) { out.set(sid, Number(hwnd)); break; } } catch (e) {}
    }
    return out.size < names.length;
  }, fn.koffi.pointer(fn.EnumProc));
  try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }
  return out;
}

// UTF-16 out-buffers: pass a Buffer as the void* and decode exactly the returned length.
function windowText(hwnd) {
  if (!load()) return null;
  try { const buf = Buffer.alloc(1024); const n = fn.GetWindowTextW(Number(hwnd), buf, 512); return n > 0 ? buf.toString('utf16le', 0, n * 2) : ''; } catch (e) { return ''; }
}
function className(hwnd) {
  if (!load()) return null;
  try { const buf = Buffer.alloc(256); const n = fn.GetClassNameW(Number(hwnd), buf, 128); return n > 0 ? buf.toString('utf16le', 0, n * 2) : ''; } catch (e) { return ''; }
}
// Find the top-level Chrome frame whose title contains `token` (the unique birth title). Returns
// {hwnd, pid} or null when none; undefined when koffi is unavailable. One in-process pass.
function findChromeWindowByTitle(token) {
  if (!load()) return undefined; tick('EnumWindows:byTitle');
  let hit = null;
  const cb = fn.koffi.register((hwnd) => {
    try {
      if (className(hwnd) !== 'Chrome_WidgetWin_1') return true;
      const t = windowText(hwnd);
      if (t && t.includes(token)) { hit = { hwnd: Number(hwnd), pid: windowPid(hwnd) }; return false; }
    } catch (e) {}
    return true;
  }, fn.koffi.pointer(fn.EnumProc));
  try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }
  return hit;
}
function windowRect(hwnd) {
  if (!load()) return null;
  try { const b = Buffer.alloc(16); if (!fn.GetWindowRect(Number(hwnd), b)) return null; return { L: b.readInt32LE(0), T: b.readInt32LE(4), R: b.readInt32LE(8), B: b.readInt32LE(12) }; } catch (e) { return null; }
}
// The restore rect from WINDOWPLACEMENT (a minimized window reports the -32000 placeholder from
// GetWindowRect, so position must be judged from the placement's rcNormalPosition).
function normalRect(hwnd) {
  if (!load()) return null;
  try { const b = Buffer.alloc(44); b.writeInt32LE(44, 0); if (!fn.GetWindowPlacement(Number(hwnd), b)) return null; return { L: b.readInt32LE(28), T: b.readInt32LE(32), R: b.readInt32LE(36), B: b.readInt32LE(40) }; } catch (e) { return null; }
}
// The visibility invariant, in-process (v2.0.314; was one PowerShell + Add-Type per 30s sweep): no
// titled, captioned top-level window of a pup-owned Chrome process may be HIDDEN or OFF-SCREEN.
// Hidden -> SW_SHOWNOACTIVATE. Off the virtual desktop -> moved back at (vx+10, vy+10) without
// activation or z-change. Minimized is the user's choice and is left alone. Returns repair records.
function fixHiddenOrOffscreen(pids) {
  if (!load()) return null; tick('EnumWindows:visibility');
  const pidSet = new Set(pids.map(Number));
  const out = [];
  const vx = fn.GetSystemMetrics(76), vy = fn.GetSystemMetrics(77), vw = fn.GetSystemMetrics(78), vh = fn.GetSystemMetrics(79);
  const cb = fn.koffi.register((hwnd) => {
    try {
      const h = Number(hwnd);
      if (!pidSet.has(windowPid(h))) return true;
      if ((fn.GetWindowLongW(h, -16) & 0x00C00000) === 0) return true;   // WS_CAPTION: real windows only
      const title = windowText(h); if (!title) return true;
      if (!fn.IsWindowVisible(h)) { fn.ShowWindow(h, 4); out.push({ kind: fn.IsWindowVisible(h) ? 'RESHOWN' : 'RESHOW-FAILED', hwnd: h, title }); return true; }
      if (fn.IsIconic(h)) return true;
      const r = normalRect(h); if (!r) return true;
      const L = r.L, T = r.T, W = r.R - r.L, H = r.B - r.T;
      if (L < vx + vw && L + W > vx && T < vy + vh && T + H > vy) return true;   // overlaps the desktop: fine
      const nw = (W > 200 && W <= vw) ? W : (vw - 20), nh = (H > 200 && H <= vh) ? H : (vh - 20);
      fn.SetWindowPos(h, 0, vx + 10, vy + 10, nw, nh, 0x14);   // NOACTIVATE | NOZORDER
      const c = windowRect(h);
      const fixedNow = !!(c && c.L < vx + vw && c.R > vx && c.T < vy + vh && c.B > vy);
      out.push({ kind: fixedNow ? 'MOVED-ONSCREEN' : 'MOVE-FAILED', hwnd: h, title });
    } catch (e) {}
    return true;
  }, fn.koffi.pointer(fn.EnumProc));
  try { fn.EnumWindows(cb, 0); } catch (e) {} finally { try { fn.koffi.unregister(cb); } catch (e) {} }
  return out;
}
function available() { return load(); }
function why() { return loadError; }

module.exports = { available, why, stats, setProp, hasProp, removeProp, isWindow, windowPid, windowText, className, findWindowByProp, findAllByPropPrefix, findChromeWindowByTitle, windowRect, normalRect, fixHiddenOrOffscreen };