1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-13 15:57:14 +03:00

[1805] Pull In Code from 1808

This commit is contained in:
David Sangrey 2024-06-18 09:51:36 -04:00
parent 85f5c3283d
commit 81a3b4fd5f
No known key found for this signature in database
GPG Key ID: 3AEADBB0186884BC

View File

@ -15,7 +15,7 @@ import sys
import threading
from calendar import timegm
from collections import defaultdict
from os import SEEK_END, SEEK_SET, listdir
from os import SEEK_END, SEEK_SET, listdir, environ
from os.path import basename, expanduser, getctime, isdir, join
from time import gmtime, localtime, mktime, sleep, strftime, strptime, time
from typing import TYPE_CHECKING, Any, BinaryIO, MutableMapping
@ -35,18 +35,16 @@ MAX_NAVROUTE_DISCREPANCY = 5 # Timestamp difference in seconds
MAX_FCMATERIALS_DISCREPANCY = 5 # Timestamp difference in seconds
if sys.platform == 'win32':
import ctypes
from ctypes.wintypes import BOOL, HWND, LPARAM
import win32process
import win32con
import win32security
import win32gui
import win32api
import pywintypes
from watchdog.events import FileSystemEventHandler, FileSystemEvent
from watchdog.observers import Observer
from watchdog.observers.api import BaseObserver
EnumWindowsProc = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
GetProcessHandleFromHwnd = ctypes.windll.oleacc.GetProcessHandleFromHwnd
else:
# Linux's inotify doesn't work over CIFS or NFS, so poll
FileSystemEventHandler = object # dummy
@ -113,6 +111,13 @@ class EDLogs(FileSystemEventHandler):
# be >= for Live, and < for Legacy.
self.live_galaxy_base_version = semantic_version.Version('4.0.0')
if sys.platform == 'win32':
# Get the SID of the user we're running as for later use in
# `game_running()`
self.user_sid, self.user_domain, self.user_type = win32security.LookupAccountName(
None, environ['USERNAME']
)
self.__init_state()
def __init_state(self) -> None:
@ -2123,23 +2128,57 @@ class EDLogs(FileSystemEventHandler):
if sys.platform == 'win32':
def WindowTitle(h): # noqa: N802
if h:
length = win32gui.GetWindowTextLength(h) + 1
buf = ctypes.create_unicode_buffer(length)
if win32gui.GetWindowText(h):
return buf.value
return win32gui.GetWindowText(h)
return None
def callback(hWnd, lParam): # noqa: N803
name = WindowTitle(hWnd)
def callback(hwnd, hwnds): # noqa: N803
name = WindowTitle(hwnd)
if name and name.startswith('Elite - Dangerous'):
handle = GetProcessHandleFromHwnd(hWnd)
if handle: # If GetProcessHandleFromHwnd succeeds then the app is already running as this user
win32api.CloseHandle(handle)
return False # stop enumeration
# We've found a window that *looks* like an ED game process, but now we need to check
# if it's owned by the current user.
# Get the process_id of the window we found
# <https://mhammond.github.io/pywin32/win32process__GetWindowThreadProcessId_meth.html>
thread_id, process_id = win32process.GetWindowThreadProcessId(hwnd)
# Use that to get a process handle
# <https://mhammond.github.io/pywin32/win32api__OpenProcess_meth.html>
# The first arg can't simply be `0`, and `win32con.PROCESS_TERMINATE` works
handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, False, process_id)
if handle:
# We got the handle OK, now we need a token for it
process_token = win32security.OpenProcessToken(handle, win32security.TOKEN_QUERY)
# So we can use that to get information about the User
token_information, i = win32security.GetTokenInformation(
process_token, win32security.TokenUser
)
# And lastly check if token_information, which should be a PySID object, matches
# that of the current user we looked up in `__init__()`.
if token_information == self.user_sid:
# This can be used to convert the token to username, domain name, and account type
# user, domain, name_use = win32security.LookupAccountSid(None, token_information)
hwnds.append(hwnd)
return False # Indicate window found, so stop iterating
return True
return not win32gui.EnumWindows(EnumWindowsProc(callback), 0)
# Ref: <http://timgolden.me.uk/python/win32_how_do_i/find-the-window-for-my-subprocess.html>
ed_windows: list[int] = []
try:
win32gui.EnumWindows(callback, ed_windows)
except pywintypes.error as e:
# Ref: <https://lists.archive.carbon60.com/python/python/135503>
# Because False is returned in the callback to indicate "found the window, stop
# processing", this causes EnumWindows() to return `0`, which is generically
# treated as an error, so exception is raised.
# So, check the exception's .winerror, and ignore if `0`.
if e.winerror != 0:
logger.exception("EnumWindows exception:")
bacon = bool(ed_windows)
print(bacon)
return bacon
return False