"""Capture a local, limited diagnostic dump of the exact selected game. No input/debug attach."""
import argparse
import ctypes as c
from ctypes import wintypes as w
from pathlib import Path
import hashlib
import json
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--pid',type=int,required=True)
p.add_argument('--output',type=Path,required=True)
a=p.parse_args()
k=c.WinDLL('kernel32',use_last_error=True)
d=c.WinDLL(r'C:\Windows\System32\dbghelp.dll',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.CreateFileW.argtypes=[w.LPCWSTR,w.DWORD,w.DWORD,c.c_void_p,w.DWORD,w.DWORD,w.HANDLE];k.CreateFileW.restype=w.HANDLE
k.CloseHandle.argtypes=[w.HANDLE]
d.MiniDumpWriteDump.argtypes=[w.HANDLE,w.DWORD,w.HANDLE,w.DWORD,c.c_void_p,c.c_void_p,c.c_void_p];d.MiniDumpWriteDump.restype=w.BOOL
process=k.OpenProcess(0x410,False,a.pid)
if not process:raise c.WinError(c.get_last_error())
try:
name=c.create_unicode_buffer(32768);length=w.DWORD(len(name))
if not k.QueryFullProcessImageNameW(process,0,name,c.byref(length)):raise c.WinError(c.get_last_error())
game=Path(r'D:\SteamLibrary\steamapps\common\Elite Dangerous\Products\elite-dangerous-odyssey-64\EliteDangerous64.exe')
if Path(name.value)!=game or hashlib.sha256(game.read_bytes()).hexdigest()!='6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93':raise ValueError('Unexpected game identity')
file=k.CreateFileW(str(a.output.resolve()),0x40000000,0,None,1,0,None)
if file==c.c_void_p(-1).value:raise c.WinError(c.get_last_error())
try:
flags=0x1|0x20|0x40|0x800|0x1000
if not d.MiniDumpWriteDump(process,a.pid,file,flags,None,None,None):raise c.WinError(c.get_last_error())
finally:k.CloseHandle(file)
finally:k.CloseHandle(process)
print(json.dumps({'processId':a.pid,'dump':str(a.output.resolve()),'length':a.output.stat().st_size,'sha256':hashlib.sha256(a.output.read_bytes()).hexdigest(),'fullMemory':False,'debuggerAttached':False,'inputsSent':0}))
"""Capture a local, limited diagnostic dump of the exact selected game. No input/debug attach."""
import argparse
import ctypes as c
from ctypes import wintypes as w
from pathlib import Path
import hashlib
import json
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--pid',type=int,required=True)
p.add_argument('--output',type=Path,required=True)
a=p.parse_args()
k=c.WinDLL('kernel32',use_last_error=True)
d=c.WinDLL(r'C:\Windows\System32\dbghelp.dll',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.CreateFileW.argtypes=[w.LPCWSTR,w.DWORD,w.DWORD,c.c_void_p,w.DWORD,w.DWORD,w.HANDLE];k.CreateFileW.restype=w.HANDLE
k.CloseHandle.argtypes=[w.HANDLE]
d.MiniDumpWriteDump.argtypes=[w.HANDLE,w.DWORD,w.HANDLE,w.DWORD,c.c_void_p,c.c_void_p,c.c_void_p];d.MiniDumpWriteDump.restype=w.BOOL
process=k.OpenProcess(0x410,False,a.pid)
if not process:raise c.WinError(c.get_last_error())
try:
name=c.create_unicode_buffer(32768);length=w.DWORD(len(name))
if not k.QueryFullProcessImageNameW(process,0,name,c.byref(length)):raise c.WinError(c.get_last_error())
game=Path(r'D:\SteamLibrary\steamapps\common\Elite Dangerous\Products\elite-dangerous-odyssey-64\EliteDangerous64.exe')
if Path(name.value)!=game or hashlib.sha256(game.read_bytes()).hexdigest()!='6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93':raise ValueError('Unexpected game identity')
file=k.CreateFileW(str(a.output.resolve()),0x40000000,0,None,1,0,None)
if file==c.c_void_p(-1).value:raise c.WinError(c.get_last_error())
try:
flags=0x1|0x20|0x40|0x800|0x1000
if not d.MiniDumpWriteDump(process,a.pid,file,flags,None,None,None):raise c.WinError(c.get_last_error())
finally:k.CloseHandle(file)
finally:k.CloseHandle(process)
print(json.dumps({'processId':a.pid,'dump':str(a.output.resolve()),'length':a.output.stat().st_size,'sha256':hashlib.sha256(a.output.read_bytes()).hexdigest(),'fullMemory':False,'debuggerAttached':False,'inputsSent':0}))