Add Windows card reader, code-signing helpers and playlist diagnostics
- windows/win_card_reader.py: Windows-native card reader via the Raw Input API with a low-level keyboard-hook fallback. - windows/sign_exe.ps1: sign the built executable with a .pfx certificate. - windows/create_self_signed_cert.ps1: generate a self-signed cert for local testing (not trusted by Smart App Control). - windows/verify_sendinput_fix.py: verification helper for the SendInput foreground-unlock fix in run_win.py. - documentation/CODE_SIGNING_SMART_APP_CONTROL.md: signing guidance. - working_files/execute_playlist_retrieve.py, working_files/raw_server_playlist.json: playlist retrieval diagnostics. Note: windows/archive_list.txt and windows/build_last.txt are build output and were committed by request rather than by convention.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Rigorous verification: is the fixed SendInput code in the compiled run_win?"""
|
||||
import marshal
|
||||
import types
|
||||
import dis
|
||||
from PyInstaller.archive.readers import CArchiveReader
|
||||
|
||||
EXE = r'dist\KiwySignagePlayer\KiwySignagePlayer.exe'
|
||||
|
||||
|
||||
def collect_strings(code, acc):
|
||||
for c in code.co_consts:
|
||||
if isinstance(c, str):
|
||||
acc.append(c)
|
||||
elif isinstance(c, types.CodeType):
|
||||
collect_strings(c, acc)
|
||||
|
||||
|
||||
def collect_codes(code, acc):
|
||||
acc.append(code)
|
||||
for c in code.co_consts:
|
||||
if isinstance(c, types.CodeType):
|
||||
collect_codes(c, acc)
|
||||
|
||||
|
||||
def main():
|
||||
arc = CArchiveReader(EXE)
|
||||
data = arc.extract('run_win')
|
||||
code = marshal.loads(data)
|
||||
|
||||
all_codes = []
|
||||
collect_codes(code, all_codes)
|
||||
strings = []
|
||||
collect_strings(code, strings)
|
||||
|
||||
# 1) c_ulonglong can ONLY come from the fixed code (old used c_ulong + POINTER)
|
||||
has_c_ulonglong = any('c_ulonglong' in c.co_names for c in all_codes)
|
||||
print(f'c_ulonglong in co_names of any code object: {has_c_ulonglong}')
|
||||
|
||||
# 2) INPUTUNION should be STORE_DEREF/STORE_NAME'd inside
|
||||
# _force_foreground_sendinput (classes are defined in a closure,
|
||||
# so they're stored via STORE_DEREF).
|
||||
store_names = set()
|
||||
for c in all_codes:
|
||||
for instr in dis.get_instructions(c):
|
||||
if instr.opname in ('STORE_NAME', 'STORE_FAST', 'STORE_DEREF'):
|
||||
store_names.add(instr.argval)
|
||||
print(f'INPUTUNION stored: {"INPUTUNION" in store_names}')
|
||||
print(f'KEYBDINPUT stored: {"KEYBDINPUT" in store_names}')
|
||||
print(f'MOUSEINPUT stored: {"MOUSEINPUT" in store_names}')
|
||||
print(f'HARDWAREINPUT stored: {"HARDWAREINPUT" in store_names}')
|
||||
|
||||
# 3) The new code uses INPUT() + field assignment (type, u.ki.wVk, u.ki.dwFlags)
|
||||
names = set()
|
||||
for c in all_codes:
|
||||
names.update(c.co_names)
|
||||
print(f'Has "u" attribute usage: {"u" in names}')
|
||||
|
||||
# 4) string markers
|
||||
print(f'string "undersized buffer": {any("undersized buffer" in s for s in strings)}')
|
||||
print(f'string "real Win32 x64": {any("real Win32 x64" in s for s in strings)}')
|
||||
print(f'string "ULONG_PTR": {any("ULONG_PTR" in s for s in strings)}')
|
||||
|
||||
# 5) Console-window fix in _find_kivy_hwnd: cellvars/freevars + tuple consts
|
||||
find_kv = [c for c in all_codes if c.co_name == '_find_kivy_hwnd']
|
||||
cell_vars = set()
|
||||
for c in find_kv:
|
||||
cell_vars.update(c.co_cellvars)
|
||||
cell_vars.update(c.co_freevars)
|
||||
enum_cb = [c for c in all_codes
|
||||
if c.co_name == '_enum_cb' and 'SDL_CLASSES' in c.co_freevars]
|
||||
tuple_strs = set()
|
||||
for c in enum_cb:
|
||||
for x in c.co_consts:
|
||||
if isinstance(x, tuple):
|
||||
tuple_strs.update(str(v) for v in x)
|
||||
print(f'_find_kivy_hwnd cell/free vars (SDL_CLASSES/sdl_windows/our_pid): '
|
||||
f'{"SDL_CLASSES" in cell_vars and "sdl_windows" in cell_vars and "our_pid" in cell_vars}')
|
||||
print(f'console class excluded (ConsoleWindowClass in _enum_cb tuple): '
|
||||
f'{"ConsoleWindowClass" in tuple_strs}')
|
||||
|
||||
verdict = has_c_ulonglong and 'INPUTUNION' in store_names
|
||||
console_fix = ('SDL_CLASSES' in cell_vars and 'ConsoleWindowClass' in tuple_strs)
|
||||
print(f'\nVerdict SendInput: {"FIX PRESENT" if verdict else "FIX ABSENT - rebuild needed"}')
|
||||
print(f'Verdict console-hwnd: {"FIX PRESENT" if console_fix else "FIX ABSENT - rebuild needed"}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user