mirror of
https://github.com/SK8-ENGINE/skate-3-rust-engine.git
synced 2026-10-26 19:47:44 +00:00
32 lines
1.6 KiB
Python
32 lines
1.6 KiB
Python
"""Release file locks only for executables owned by this installation."""
|
|
import os
|
|
|
|
def close_programs(root, names):
|
|
if os.name != 'nt': return
|
|
import ctypes as c
|
|
from ctypes import wintypes as w
|
|
root=root.resolve()
|
|
targets={os.path.normcase(str(root/name)) for name in names if name.lower().endswith('.exe')}
|
|
k=c.WinDLL('kernel32',use_last_error=True)
|
|
ps=c.WinDLL('psapi',use_last_error=True)
|
|
k.OpenProcess.argtypes=[w.DWORD,w.BOOL,w.DWORD];k.OpenProcess.restype=w.HANDLE
|
|
k.QueryFullProcessImageNameW.argtypes=[w.HANDLE,w.DWORD,w.LPWSTR,c.POINTER(w.DWORD)]
|
|
k.TerminateProcess.argtypes=[w.HANDLE,w.UINT]
|
|
k.WaitForSingleObject.argtypes=[w.HANDLE,w.DWORD]
|
|
k.CloseHandle.argtypes=[w.HANDLE]
|
|
ps.EnumProcesses.argtypes=[c.POINTER(w.DWORD),w.DWORD,c.POINTER(w.DWORD)]
|
|
pids=(w.DWORD*65536)();used=w.DWORD()
|
|
if not ps.EnumProcesses(pids,c.sizeof(pids),c.byref(used)):
|
|
raise OSError('Could not check running game processes')
|
|
for pid in pids[:used.value//c.sizeof(w.DWORD)]:
|
|
if pid==os.getpid():continue
|
|
# Query and terminate through the same handle, avoiding PID-reuse races.
|
|
h=k.OpenProcess(0x1000|0x0001|0x100000,False,pid)
|
|
if not h:continue
|
|
try:
|
|
text=c.create_unicode_buffer(32768);size=w.DWORD(len(text))
|
|
if k.QueryFullProcessImageNameW(h,0,text,c.byref(size)) and os.path.normcase(text.value) in targets:
|
|
if not k.TerminateProcess(h,0):raise OSError('Could not close '+text.value)
|
|
if k.WaitForSingleObject(h,10000)!=0:raise OSError('Timed out closing '+text.value)
|
|
finally:k.CloseHandle(h)
|