mirror of
https://github.com/DxWnd/DxWnd.reloaded
synced 2024-12-30 09:25:35 +01:00
v2_02_25_src
Former-commit-id: 173807aaa1600e77d30c5fd3c2290db1e5f5c0a3
This commit is contained in:
parent
1cf12b8d03
commit
1e8566300a
@ -87,6 +87,7 @@
|
||||
#define FORCE16BPP 0x00000040 // Forces 16BPP desktop color depth
|
||||
#define BLACKWHITE 0x00000080 // Simulate a B&W screen monitor mapping colors to grayscales
|
||||
#define SAVECAPS 0x00000100 // Saves and restores original surface flags & capabilities
|
||||
#define SINGLEPROCAFFINITY 0x00000200 // Set Process Affinity to a single core
|
||||
|
||||
// logging Tflags DWORD:
|
||||
#define OUTTRACE 0x00000001 // enables tracing to dxwnd.log in general
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bce7a60e60155037cd12e0c1383f1078103923d7ba43a349e368606025bec75a
|
||||
size 343040
|
||||
oid sha256:89c569d050fd740aedc07bce2d7c3708b13aa127300a83332e8a0d1dde02fdb1
|
||||
size 344064
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:920bc90915cbde2b59ef55c17b59fe4b741720c68c65491186044fa50ebb4985
|
||||
size 521216
|
||||
oid sha256:62dacd099414e7a8a4cfa4a1623aa5d55f7728bab0c61ea2a5ab5dfe1c7a43c2
|
||||
size 524800
|
||||
|
@ -870,8 +870,8 @@ title51=Daikatana
|
||||
path51=D:\Games\Daikatana\daikatana.exe
|
||||
module51=
|
||||
ver51=12
|
||||
flag51=806486530
|
||||
flagg51=131585
|
||||
flag51=806429218
|
||||
flagg51=537002496
|
||||
tflag51=2
|
||||
initx51=0
|
||||
inity51=0
|
||||
@ -1632,12 +1632,12 @@ posy95=50
|
||||
sizx95=800
|
||||
sizy95=600
|
||||
title96=Grand Prix World
|
||||
path96=D:\Games\Grand Prix World\gpwxp3.exe
|
||||
path96=D:\Games\Grand Prix World\gpwxp2.exe
|
||||
module96=
|
||||
ver96=0
|
||||
flag96=-2011168605
|
||||
flagg96=134217856
|
||||
tflag96=258
|
||||
flag96=-2011037534
|
||||
flagg96=134217864
|
||||
tflag96=259
|
||||
initx96=0
|
||||
inity96=0
|
||||
minx96=0
|
||||
@ -4540,8 +4540,8 @@ flagh38=0
|
||||
flagi38=0
|
||||
flagh39=0
|
||||
flagi39=0
|
||||
flagh40=-842150435
|
||||
flagi40=-842150451
|
||||
flagh40=221
|
||||
flagi40=0
|
||||
flagh41=0
|
||||
flagi41=0
|
||||
flagh42=0
|
||||
@ -4652,7 +4652,7 @@ flagh94=0
|
||||
flagi94=0
|
||||
flagh95=0
|
||||
flagi95=0
|
||||
flagh96=93
|
||||
flagh96=92
|
||||
flagi96=0
|
||||
flagh97=0
|
||||
flagi97=0
|
||||
@ -5401,7 +5401,7 @@ coord227=0
|
||||
coord228=0
|
||||
coord229=0
|
||||
coord230=0
|
||||
coord231=1
|
||||
coord231=0
|
||||
coord232=0
|
||||
coord233=0
|
||||
coord234=0
|
||||
@ -5682,7 +5682,7 @@ sizy246=600
|
||||
maxfps246=0
|
||||
initts246=0
|
||||
[window]
|
||||
posx=934
|
||||
posy=634
|
||||
sizx=400
|
||||
sizy=300
|
||||
posx=-32008
|
||||
posy=-32050
|
||||
sizx=16
|
||||
sizy=58
|
||||
|
@ -139,5 +139,15 @@ Improved the primary emulation capacity to handle 3D games
|
||||
Added the "preserve surface capabilities" flag
|
||||
Fixed an hooking bug for user32.dll
|
||||
|
||||
v2.02.23/24.fix1
|
||||
Fixed a few things to make Grand Prix World playable in emulation mode - sorry, no movies!
|
||||
v2.02.25
|
||||
CORE:
|
||||
Added 'Single CPU Process Affinity' flag to let old games run on a single CPU core.
|
||||
Fixed bug causing possible crash using 'preserve surface caps' flag
|
||||
Switched lpDDSBack reference when backbuffer is upgraded through QueryInterface
|
||||
Eliminated lpDDSBack clearing when refcount is zero - why is this working better? Needs further investigation
|
||||
Added DDSCAPS_3DDEVICE capability when in EMULATED mode
|
||||
GUI:
|
||||
Added Kill process by name functionality (right click menu on program's list)
|
||||
Fixed GUI initial position: now checks for desktop size to fit GUI within visible borders
|
||||
Added single cpu process affinity checkbox in compatibility tab
|
||||
|
||||
|
@ -53,8 +53,8 @@ static char *Flag2Names[32]={
|
||||
static char *Flag3Names[32]={
|
||||
"FORCEHOOKOPENGL", "MARKBLIT", "HOOKDLLS", "SUPPRESSD3DEXT",
|
||||
"HOOKENABLED", "FIXD3DFRAME", "FORCE16BPP", "BLACKWHITE",
|
||||
"SAVECAPS", "", "", "",
|
||||
"", "", "", "",
|
||||
"SAVECAPS", "SINGLEPROCAFFINITY", "Flag3:11", "Flag3:12",
|
||||
"Flag3:13", "Flag3:14", "Flag3:15", "Flag3:16",
|
||||
"", "", "", "",
|
||||
"", "", "", "",
|
||||
"", "", "", "",
|
||||
@ -1256,6 +1256,24 @@ void DisableIME()
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetSingleProcessAffinity(void)
|
||||
{
|
||||
int i;
|
||||
DWORD ProcessAffinityMask, SystemAffinityMask;
|
||||
if(!GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask, &SystemAffinityMask))
|
||||
OutTraceE("GetProcessAffinityMask: ERROR err=%d\n", GetLastError());
|
||||
OutTraceD("Process affinity=%x\n", ProcessAffinityMask);
|
||||
for (i=0; i<(8 * sizeof(DWORD)); i++){
|
||||
if (ProcessAffinityMask & 0x1) break;
|
||||
ProcessAffinityMask >>= 1;
|
||||
}
|
||||
OutTraceD("First process affinity bit=%d\n", i);
|
||||
ProcessAffinityMask &= 0x1;
|
||||
for (; i; i--) ProcessAffinityMask <<= 1;
|
||||
OutTraceD("Process affinity=%x\n", ProcessAffinityMask);
|
||||
if (!SetProcessAffinityMask(GetCurrentProcess(), ProcessAffinityMask))
|
||||
OutTraceE("SetProcessAffinityMask: ERROR err=%d\n", GetLastError());
|
||||
}
|
||||
|
||||
int HookInit(TARGETMAP *target, HWND hwnd)
|
||||
{
|
||||
@ -1291,6 +1309,7 @@ int HookInit(TARGETMAP *target, HWND hwnd)
|
||||
}
|
||||
|
||||
base=GetModuleHandle(NULL);
|
||||
if(dxw.dwFlags3 & SINGLEPROCAFFINITY) SetSingleProcessAffinity();
|
||||
if(dxw.dwFlags1 & HANDLEEXCEPTIONS) HookExceptionHandler();
|
||||
if (dxw.dwTFlags & OUTIMPORTTABLE) DumpImportTable(base);
|
||||
//if(dxw.dwFlags2 & SUPPRESSIME) DisableIME();
|
||||
|
@ -24,7 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "dxwnd.h"
|
||||
#include "dxwcore.hpp"
|
||||
|
||||
#define VERSION "2.02.24.f1"
|
||||
#define VERSION "2.02.25"
|
||||
|
||||
LRESULT CALLBACK HookProc(int ncode, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
@ -209,7 +209,6 @@ void InjectHook()
|
||||
if(!strncmp(name, pMapping[i].path, strlen(name))){
|
||||
if (pMapping[i].flags2 & STARTDEBUG){
|
||||
OutTrace("InjectHook: task[%d]=\"%s\" hooked\n", i, pMapping[i].path);
|
||||
dxw.InitTarget(&pMapping[i]);
|
||||
HookInit(&pMapping[i],NULL);
|
||||
}
|
||||
break;
|
||||
|
Binary file not shown.
@ -286,7 +286,7 @@ static void DumpSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line)
|
||||
LogSurfaceAttributes(lpddsd, label, line);
|
||||
}
|
||||
|
||||
#define CAPSHASHSIZE 100
|
||||
#define CAPSHASHSIZE 113
|
||||
|
||||
typedef struct {
|
||||
LPDIRECTDRAWSURFACE lpdds;
|
||||
@ -294,14 +294,15 @@ typedef struct {
|
||||
DWORD Caps;
|
||||
DDPIXELFORMAT PixelFormat;
|
||||
} CapsHash_Type;
|
||||
static CapsHash_Type CapsHash[CAPSHASHSIZE];
|
||||
static CapsHash_Type *CapsHash;
|
||||
|
||||
static void PushCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds)
|
||||
{
|
||||
static BOOL DoFirst = TRUE;
|
||||
int i;
|
||||
if (DoFirst) { // initialize
|
||||
memset(CapsHash, 0, sizeof(CapsHash));
|
||||
CapsHash=(CapsHash_Type *)malloc(CAPSHASHSIZE * sizeof(CapsHash_Type));
|
||||
memset(CapsHash, 0, CAPSHASHSIZE * sizeof(CapsHash_Type));
|
||||
DoFirst = FALSE;
|
||||
}
|
||||
if(IsDebug){
|
||||
@ -311,7 +312,7 @@ static void PushCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds)
|
||||
lpddsd->ddpfPixelFormat.dwRBitMask, lpddsd->ddpfPixelFormat.dwGBitMask, lpddsd->ddpfPixelFormat.dwBBitMask, lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask);
|
||||
OutTrace("\n");
|
||||
}
|
||||
i = (DWORD)lpdds % CAPSHASHSIZE;
|
||||
i = ((DWORD)lpdds >> 3) % CAPSHASHSIZE;
|
||||
if(CapsHash[i].lpdds && (CapsHash[i].lpdds != lpdds)) {
|
||||
char sMsg[80];
|
||||
sprintf(sMsg, "PushCaps CONFLICT %x:%x\n", lpdds, CapsHash[i].lpdds);
|
||||
@ -329,8 +330,7 @@ static void PushCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds)
|
||||
static int PopCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds)
|
||||
{
|
||||
int i;
|
||||
//DWORD Flags;
|
||||
i = (DWORD)lpdds % 100;
|
||||
i = ((DWORD)lpdds >> 3) % CAPSHASHSIZE;
|
||||
if(lpdds != CapsHash[i].lpdds){
|
||||
char sMsg[80];
|
||||
sprintf(sMsg, "PopCaps MISMATCH %x:%x\n", lpdds, CapsHash[i].lpdds);
|
||||
@ -338,13 +338,11 @@ static int PopCaps(LPDDSURFACEDESC2 lpddsd, LPDIRECTDRAWSURFACE lpdds)
|
||||
if (IsAssertEnabled) MessageBox(0, sMsg, "PopCaps", MB_OK | MB_ICONEXCLAMATION);
|
||||
return FALSE;
|
||||
}
|
||||
//Flags = lpddsd->ddpfPixelFormat.dwFlags;
|
||||
if (lpddsd->dwSize > (DWORD)&((LPDDSURFACEDESC2)NULL)->dwFlags) lpddsd->dwFlags = CapsHash[i].Flags;
|
||||
if (lpddsd->dwSize > (DWORD)&((LPDDSURFACEDESC2)NULL)->ddsCaps.dwCaps) lpddsd->ddsCaps.dwCaps = CapsHash[i].Caps;
|
||||
if ((lpddsd->dwFlags & DDSD_PIXELFORMAT) && (lpddsd->dwSize > (DWORD)&((LPDDSURFACEDESC2)NULL)->ddpfPixelFormat))
|
||||
memcpy(&(lpddsd->ddpfPixelFormat), (void *)&CapsHash[i].PixelFormat, sizeof(DDPIXELFORMAT));
|
||||
//lpddsd->ddpfPixelFormat.dwFlags = Flags;
|
||||
|
||||
|
||||
if(IsDebug){
|
||||
OutTrace("PopCaps: lpdds=%x dwFlags=%x dwCaps=%x", lpdds, lpddsd->dwFlags, lpddsd->ddsCaps.dwCaps);
|
||||
if (lpddsd->dwFlags & DDSD_PIXELFORMAT) OutTrace(" PF.dwFlags=%x PF.dwFourCC=%x PF.dwRGBBitCount=%x RGBA=(%x,%x,%x,%x)",
|
||||
@ -1532,6 +1530,8 @@ HRESULT WINAPI extQueryInterfaceS(void *lpdds, REFIID riid, LPVOID *obp)
|
||||
DDSURFACEDESC2 ddsd;
|
||||
if (PopCaps(&ddsd, (LPDIRECTDRAWSURFACE)lpdds)) PushCaps(&ddsd, (LPDIRECTDRAWSURFACE)*obp);
|
||||
}
|
||||
|
||||
if(lpdds == lpDDSBack) lpDDSBack = (LPDIRECTDRAWSURFACE)*obp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3112,12 +3112,15 @@ HRESULT WINAPI extGetDC(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
|
||||
HRESULT WINAPI extReleaseDC(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
|
||||
{
|
||||
HRESULT res;
|
||||
BOOL IsPrim;
|
||||
POINT p = {0, 0};
|
||||
RECT client;
|
||||
|
||||
// this must cope with the action policy of GetDC.
|
||||
|
||||
OutTraceD("ReleaseDC: lpdds=%x hdc=%x\n",lpdds, hdc);
|
||||
IsPrim=dxw.IsAPrimarySurface(lpdds);
|
||||
OutTraceD("ReleaseDC: lpdss=%x%s hdc=%x\n",lpdds, IsPrim?"(PRIM)":"", hdc);
|
||||
|
||||
res=(*pReleaseDC)(lpdds,hdc);
|
||||
if (res==DD_OK) return res;
|
||||
|
||||
@ -3438,10 +3441,10 @@ HRESULT WINAPI extReleaseS(LPDIRECTDRAWSURFACE lpdds)
|
||||
// if primary, clean primay surface list
|
||||
if(IsPrim) dxw.UnmarkPrimarySurface(lpdds);
|
||||
// service surfaces cleanup
|
||||
//if(lpdds==lpDDSBack) { // v2.02.24fixed: to be investigated
|
||||
// OutTraceD("Release(S): Clearing lpDDSBack pointer\n");
|
||||
// lpDDSBack=NULL;
|
||||
//}
|
||||
if(lpdds==lpDDSBack) {
|
||||
OutTraceD("Release(S): NOT Clearing lpDDSBack pointer\n");
|
||||
//lpDDSBack=NULL;
|
||||
}
|
||||
if (dxw.dwFlags1 & EMULATESURFACE) {
|
||||
if(lpdds==lpDDSEmu_Prim) {
|
||||
OutTraceD("Release(S): Clearing lpDDSEmu_Prim pointer\n");
|
||||
@ -3782,9 +3785,9 @@ HRESULT WINAPI extGetSurfaceDesc(GetSurfaceDesc_Type pGetSurfaceDesc, LPDIRECTDR
|
||||
if (PopCaps((LPDDSURFACEDESC2)lpddsd, lpdds)) IsFixed=TRUE;
|
||||
if (lpddsd->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) lpddsd->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
|
||||
}
|
||||
|
||||
lpddsd->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
|
||||
|
||||
|
||||
if(dxw.dwFlags1 & EMULATESURFACE) lpddsd->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
|
||||
|
||||
if(IsFixed) DumpSurfaceAttributes(lpddsd, "GetSurfaceDesc [FIXED]", __LINE__);
|
||||
return DD_OK;
|
||||
}
|
||||
|
316
host/KillProc.cpp
Normal file
316
host/KillProc.cpp
Normal file
@ -0,0 +1,316 @@
|
||||
// Exam28.cpp
|
||||
// 9/21/2000 (rk)
|
||||
// Last modified: 3/10/2002 (RK)
|
||||
// test the routine KILL_PROC_BY_NAME to terminate a process
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
int KillProcByName(char *szToTerminate)
|
||||
// Created: 6/23/2000 (RK)
|
||||
// Last modified: 3/10/2002 (RK)
|
||||
// Please report any problems or bugs to kochhar@physiology.wisc.edu
|
||||
// The latest version of this routine can be found at:
|
||||
// http://www.neurophys.wisc.edu/ravi/software/killproc/
|
||||
// Terminate the process "szToTerminate" if it is currently running
|
||||
// This works for Win/95/98/ME and also Win/NT/2000/XP
|
||||
// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE"
|
||||
// will both work (for szToTerminate)
|
||||
// Return codes are as follows:
|
||||
// 0 = Process was successfully terminated
|
||||
// 603 = Process was not currently running
|
||||
// 604 = No permission to terminate process
|
||||
// 605 = Unable to load PSAPI.DLL
|
||||
// 602 = Unable to terminate process for some other reason
|
||||
// 606 = Unable to identify system type
|
||||
// 607 = Unsupported OS
|
||||
// 632 = Invalid process name
|
||||
// 700 = Unable to get procedure address from PSAPI.DLL
|
||||
// 701 = Unable to get process list, EnumProcesses failed
|
||||
// 702 = Unable to load KERNEL32.DLL
|
||||
// 703 = Unable to get procedure address from KERNEL32.DLL
|
||||
// 704 = CreateToolhelp32Snapshot failed
|
||||
// Change history:
|
||||
// modified 3/8/2002 - Borland-C compatible if BORLANDC is defined as
|
||||
// suggested by Bob Christensen
|
||||
// modified 3/10/2002 - Removed memory leaks as suggested by
|
||||
// Jonathan Richard-Brochu (handles to Proc and Snapshot
|
||||
// were not getting closed properly in some cases)
|
||||
{
|
||||
BOOL bResult,bResultm;
|
||||
DWORD aiPID[1000],iCb=1000,iNumProc,iV2000=0;
|
||||
DWORD iCbneeded,i,iFound=0;
|
||||
char szName[MAX_PATH],szToTermUpper[MAX_PATH];
|
||||
HANDLE hProc,hSnapShot,hSnapShotm;
|
||||
OSVERSIONINFO osvi;
|
||||
HINSTANCE hInstLib;
|
||||
int iLen,iLenP,indx;
|
||||
HMODULE hMod;
|
||||
PROCESSENTRY32 procentry;
|
||||
MODULEENTRY32 modentry;
|
||||
|
||||
// Transfer Process name into "szToTermUpper" and
|
||||
// convert it to upper case
|
||||
iLenP=strlen(szToTerminate);
|
||||
if(iLenP<1 || iLenP>MAX_PATH) return 632;
|
||||
for(indx=0;indx<iLenP;indx++)
|
||||
szToTermUpper[indx]=toupper(szToTerminate[indx]);
|
||||
szToTermUpper[iLenP]=0;
|
||||
|
||||
// PSAPI Function Pointers.
|
||||
BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
|
||||
BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
|
||||
DWORD, LPDWORD );
|
||||
DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE,
|
||||
LPTSTR, DWORD );
|
||||
|
||||
// ToolHelp Function Pointers.
|
||||
HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
|
||||
BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
|
||||
BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
|
||||
BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ;
|
||||
BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ;
|
||||
|
||||
// First check what version of Windows we're in
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
bResult=GetVersionEx(&osvi);
|
||||
if(!bResult) // Unable to identify system version
|
||||
return 606;
|
||||
|
||||
// At Present we only support Win/NT/2000/XP or Win/9x/ME
|
||||
if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) &&
|
||||
(osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS))
|
||||
return 607;
|
||||
|
||||
if(osvi.dwPlatformId>=VER_PLATFORM_WIN32_NT)
|
||||
{
|
||||
// Win/NT or 2000 or XP or greater
|
||||
|
||||
// Load library and get the procedures explicitly. We do
|
||||
// this so that we don't have to worry about modules using
|
||||
// this code failing to load under Windows 9x, because
|
||||
// it can't resolve references to the PSAPI.DLL.
|
||||
hInstLib = LoadLibraryA("PSAPI.DLL");
|
||||
if(hInstLib == NULL)
|
||||
return 605;
|
||||
|
||||
// Get procedure addresses.
|
||||
lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
|
||||
GetProcAddress( hInstLib, "EnumProcesses" ) ;
|
||||
lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
|
||||
DWORD, LPDWORD)) GetProcAddress( hInstLib,
|
||||
"EnumProcessModules" ) ;
|
||||
lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE,
|
||||
LPTSTR, DWORD )) GetProcAddress( hInstLib,
|
||||
"GetModuleBaseNameA" ) ;
|
||||
|
||||
if(lpfEnumProcesses == NULL ||
|
||||
lpfEnumProcessModules == NULL ||
|
||||
lpfGetModuleBaseName == NULL)
|
||||
{
|
||||
FreeLibrary(hInstLib);
|
||||
return 700;
|
||||
}
|
||||
|
||||
bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded);
|
||||
if(!bResult)
|
||||
{
|
||||
// Unable to get process list, EnumProcesses failed
|
||||
FreeLibrary(hInstLib);
|
||||
return 701;
|
||||
}
|
||||
|
||||
// How many processes are there?
|
||||
iNumProc=iCbneeded/sizeof(DWORD);
|
||||
|
||||
// Get and match the name of each process
|
||||
for(i=0;i<iNumProc;i++)
|
||||
{
|
||||
// Get the (module) name for this process
|
||||
|
||||
strcpy(szName,"Unknown");
|
||||
// First, get a handle to the process
|
||||
hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
|
||||
aiPID[i]);
|
||||
// Now, get the process name
|
||||
if(hProc)
|
||||
{
|
||||
if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) )
|
||||
{
|
||||
iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
|
||||
}
|
||||
}
|
||||
CloseHandle(hProc);
|
||||
// We will match regardless of lower or upper case
|
||||
#ifdef BORLANDC
|
||||
if(strcmp(strupr(szName),szToTermUpper)==0)
|
||||
#else
|
||||
if(strcmp(_strupr(szName),szToTermUpper)==0)
|
||||
#endif
|
||||
{
|
||||
// Process found, now terminate it
|
||||
iFound=1;
|
||||
// First open for termination
|
||||
hProc=OpenProcess(PROCESS_TERMINATE,FALSE,aiPID[i]);
|
||||
if(hProc)
|
||||
{
|
||||
if(TerminateProcess(hProc,0))
|
||||
{
|
||||
// process terminated
|
||||
CloseHandle(hProc);
|
||||
FreeLibrary(hInstLib);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unable to terminate process
|
||||
CloseHandle(hProc);
|
||||
FreeLibrary(hInstLib);
|
||||
return 602;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unable to open process for termination
|
||||
FreeLibrary(hInstLib);
|
||||
return 604;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
|
||||
{
|
||||
// Win/95 or 98 or ME
|
||||
|
||||
hInstLib = LoadLibraryA("Kernel32.DLL");
|
||||
if( hInstLib == NULL )
|
||||
return 702;
|
||||
|
||||
// Get procedure addresses.
|
||||
// We are linking to these functions of Kernel32
|
||||
// explicitly, because otherwise a module using
|
||||
// this code would fail to load under Windows NT,
|
||||
// which does not have the Toolhelp32
|
||||
// functions in the Kernel 32.
|
||||
lpfCreateToolhelp32Snapshot=
|
||||
(HANDLE(WINAPI *)(DWORD,DWORD))
|
||||
GetProcAddress( hInstLib,
|
||||
"CreateToolhelp32Snapshot" ) ;
|
||||
lpfProcess32First=
|
||||
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
|
||||
GetProcAddress( hInstLib, "Process32First" ) ;
|
||||
lpfProcess32Next=
|
||||
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
|
||||
GetProcAddress( hInstLib, "Process32Next" ) ;
|
||||
lpfModule32First=
|
||||
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
|
||||
GetProcAddress( hInstLib, "Module32First" ) ;
|
||||
lpfModule32Next=
|
||||
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
|
||||
GetProcAddress( hInstLib, "Module32Next" ) ;
|
||||
if( lpfProcess32Next == NULL ||
|
||||
lpfProcess32First == NULL ||
|
||||
lpfModule32Next == NULL ||
|
||||
lpfModule32First == NULL ||
|
||||
lpfCreateToolhelp32Snapshot == NULL )
|
||||
{
|
||||
FreeLibrary(hInstLib);
|
||||
return 703;
|
||||
}
|
||||
|
||||
// The Process32.. and Module32.. routines return names in all uppercase
|
||||
|
||||
// Get a handle to a Toolhelp snapshot of all the systems processes.
|
||||
|
||||
hSnapShot = lpfCreateToolhelp32Snapshot(
|
||||
TH32CS_SNAPPROCESS, 0 ) ;
|
||||
if( hSnapShot == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
FreeLibrary(hInstLib);
|
||||
return 704;
|
||||
}
|
||||
|
||||
// Get the first process' information.
|
||||
procentry.dwSize = sizeof(PROCESSENTRY32);
|
||||
bResult=lpfProcess32First(hSnapShot,&procentry);
|
||||
|
||||
// While there are processes, keep looping and checking.
|
||||
while(bResult)
|
||||
{
|
||||
// Get a handle to a Toolhelp snapshot of this process.
|
||||
hSnapShotm = lpfCreateToolhelp32Snapshot(
|
||||
TH32CS_SNAPMODULE, procentry.th32ProcessID) ;
|
||||
if( hSnapShotm == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
CloseHandle(hSnapShot);
|
||||
FreeLibrary(hInstLib);
|
||||
return 704;
|
||||
}
|
||||
// Get the module list for this process
|
||||
modentry.dwSize=sizeof(MODULEENTRY32);
|
||||
bResultm=lpfModule32First(hSnapShotm,&modentry);
|
||||
|
||||
// While there are modules, keep looping and checking
|
||||
while(bResultm)
|
||||
{
|
||||
if(strcmp(modentry.szModule,szToTermUpper)==0)
|
||||
{
|
||||
// Process found, now terminate it
|
||||
iFound=1;
|
||||
// First open for termination
|
||||
hProc=OpenProcess(PROCESS_TERMINATE,FALSE,procentry.th32ProcessID);
|
||||
if(hProc)
|
||||
{
|
||||
if(TerminateProcess(hProc,0))
|
||||
{
|
||||
// process terminated
|
||||
CloseHandle(hSnapShotm);
|
||||
CloseHandle(hSnapShot);
|
||||
CloseHandle(hProc);
|
||||
FreeLibrary(hInstLib);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unable to terminate process
|
||||
CloseHandle(hSnapShotm);
|
||||
CloseHandle(hSnapShot);
|
||||
CloseHandle(hProc);
|
||||
FreeLibrary(hInstLib);
|
||||
return 602;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unable to open process for termination
|
||||
CloseHandle(hSnapShotm);
|
||||
CloseHandle(hSnapShot);
|
||||
FreeLibrary(hInstLib);
|
||||
return 604;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Look for next modules for this process
|
||||
modentry.dwSize=sizeof(MODULEENTRY32);
|
||||
bResultm=lpfModule32Next(hSnapShotm,&modentry);
|
||||
}
|
||||
}
|
||||
|
||||
//Keep looking
|
||||
CloseHandle(hSnapShotm);
|
||||
procentry.dwSize = sizeof(PROCESSENTRY32);
|
||||
bResult = lpfProcess32Next(hSnapShot,&procentry);
|
||||
}
|
||||
CloseHandle(hSnapShot);
|
||||
}
|
||||
if(iFound==0)
|
||||
{
|
||||
FreeLibrary(hInstLib);
|
||||
return 603;
|
||||
}
|
||||
FreeLibrary(hInstLib);
|
||||
return 0;
|
||||
}
|
||||
|
@ -105,12 +105,21 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
||||
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
|
||||
{
|
||||
char InitPath[MAX_PATH];
|
||||
RECT DesktopRect;
|
||||
GetCurrentDirectory(MAX_PATH, InitPath);
|
||||
strcat_s(InitPath, sizeof(InitPath), "\\dxwnd.ini");
|
||||
cs.x = GetPrivateProfileInt("window", "posx", 50, InitPath);
|
||||
cs.y = GetPrivateProfileInt("window", "posy", 50, InitPath);
|
||||
cs.cx = GetPrivateProfileInt("window", "sizx", 320, InitPath);
|
||||
cs.cy = GetPrivateProfileInt("window", "sizy", 200, InitPath);
|
||||
|
||||
// keep window inside desktop boundaries
|
||||
::GetWindowRect(::GetDesktopWindow(), &DesktopRect);
|
||||
if(cs.x < DesktopRect.left) cs.x = DesktopRect.left;
|
||||
if(cs.y < DesktopRect.top) cs.y = DesktopRect.top;
|
||||
if(cs.x+cs.cx > DesktopRect.right) cs.x = DesktopRect.right - cs.cx;
|
||||
if(cs.y+cs.cy > DesktopRect.bottom) cs.y = DesktopRect.bottom - cs.cy;
|
||||
|
||||
if( !CFrameWnd::PreCreateWindow(cs) )
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
|
@ -152,6 +152,7 @@
|
||||
#define IDC_TIMESLIDER 1108
|
||||
#define IDC_BLACKWHITE 1109
|
||||
#define IDC_SAVECAPS 1110
|
||||
#define IDC_SINGLEPROCAFFINITY 1111
|
||||
#define ID_MODIFY 32771
|
||||
#define ID_DELETE 32772
|
||||
#define ID_ADD 32773
|
||||
@ -192,6 +193,7 @@
|
||||
#define ID_FILE_IMPORT 32820
|
||||
#define ID_INDEX0_EXPORT 32821
|
||||
#define ID_PEXPORT 32822
|
||||
#define ID_PKILL 32823
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
@ -199,7 +201,7 @@
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_3D_CONTROLS 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 156
|
||||
#define _APS_NEXT_COMMAND_VALUE 32823
|
||||
#define _APS_NEXT_COMMAND_VALUE 32825
|
||||
#define _APS_NEXT_CONTROL_VALUE 1091
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
@ -29,6 +29,7 @@ void CTabCompat::DoDataExchange(CDataExchange* pDX)
|
||||
CTargetDlg *cTarget = ((CTargetDlg *)(this->GetParent()->GetParent()));
|
||||
DDX_Check(pDX, IDC_FAKEVERSION, cTarget->m_FakeVersion);
|
||||
DDX_LBIndex(pDX, IDC_LISTFAKE, cTarget->m_FakeVersionId);
|
||||
DDX_Check(pDX, IDC_SINGLEPROCAFFINITY, cTarget->m_SingleProcAffinity);
|
||||
DDX_Check(pDX, IDC_HANDLEEXCEPTIONS, cTarget->m_HandleExceptions);
|
||||
DDX_Check(pDX, IDC_LIMITRESOURCES, cTarget->m_LimitResources);
|
||||
DDX_Check(pDX, IDC_SUPPRESSIME, cTarget->m_SuppressIME);
|
||||
|
@ -39,6 +39,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/)
|
||||
m_SuppressD3DExt = FALSE;
|
||||
m_SetCompatibility = FALSE;
|
||||
m_SaveCaps = FALSE;
|
||||
m_SingleProcAffinity = FALSE;
|
||||
m_LimitResources = FALSE;
|
||||
m_UnNotify = FALSE;
|
||||
m_Windowize = TRUE; // default true !!
|
||||
|
@ -105,6 +105,7 @@ public:
|
||||
BOOL m_SuppressIME;
|
||||
BOOL m_SetCompatibility;
|
||||
BOOL m_SaveCaps;
|
||||
BOOL m_SingleProcAffinity;
|
||||
BOOL m_WireFrame;
|
||||
BOOL m_BlackWhite;
|
||||
BOOL m_SuppressD3DExt;
|
||||
|
@ -1,28 +0,0 @@
|
||||
[window]
|
||||
posx=1104
|
||||
posy=310
|
||||
sizx=303
|
||||
sizy=138
|
||||
[target]
|
||||
title0=speeddemo.exe
|
||||
path0=D:\Games\Need For Speed Underground Demo\speeddemo.exe
|
||||
module0=
|
||||
opengllib0=
|
||||
ver0=0
|
||||
flag0=0
|
||||
flagg0=134217728
|
||||
flagh0=-842150435
|
||||
flagi0=-842150451
|
||||
tflag0=0
|
||||
initx0=0
|
||||
inity0=0
|
||||
minx0=0
|
||||
miny0=0
|
||||
maxx0=0
|
||||
maxy0=0
|
||||
posx0=0
|
||||
posy0=0
|
||||
sizx0=800
|
||||
sizy0=600
|
||||
maxfps0=0
|
||||
initts0=0
|
Binary file not shown.
@ -137,6 +137,7 @@ BEGIN
|
||||
MENUITEM "&Delete", ID_PLOG_DELETE
|
||||
END
|
||||
MENUITEM "e&Xport ...", ID_PEXPORT
|
||||
MENUITEM "&Kill", ID_PKILL
|
||||
END
|
||||
END
|
||||
|
||||
@ -417,10 +418,12 @@ BEGIN
|
||||
GROUPBOX "Fake Version",IDC_STATIC,7,3,139,64
|
||||
CONTROL "",IDC_FAKEVERSION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,26,12,10
|
||||
LISTBOX IDC_LISTFAKE,39,15,98,43,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "Handle Exceptions",IDC_HANDLEEXCEPTIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,201,109,12
|
||||
CONTROL "Handle Exceptions",IDC_HANDLEEXCEPTIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,200,109,12
|
||||
CONTROL "Limit available resources",IDC_LIMITRESOURCES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,212,109,12
|
||||
CONTROL "Suppress IME",IDC_SUPPRESSIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,190,109,12
|
||||
CONTROL "Suppress d3d9 extensions",IDC_SUPPRESSD3DEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,179,109,12
|
||||
CONTROL "Suppress IME",IDC_SUPPRESSIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,188,109,12
|
||||
CONTROL "Suppress d3d9 extensions",IDC_SUPPRESSD3DEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,176,109,12
|
||||
CONTROL "Set single core process affinity",IDC_SINGLEPROCAFFINITY,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,164,109,12
|
||||
END
|
||||
|
||||
IDD_TAB_GDI DIALOGEX 0, 0, 300, 240
|
||||
|
Binary file not shown.
@ -311,6 +311,10 @@
|
||||
RelativePath=".\Inject.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\KillProc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MainFrm.cpp"
|
||||
>
|
||||
|
@ -28,6 +28,7 @@ extern UINT m_StartToTray;
|
||||
extern UINT m_InitialState;
|
||||
extern char m_ConfigFileName[20+1];
|
||||
extern BOOL Inject(DWORD, const char *);
|
||||
extern int KillProcByName(char *);
|
||||
|
||||
PRIVATEMAP *pTitles; // global ptr: get rid of it!!
|
||||
TARGETMAP *pTargets; // idem.
|
||||
@ -49,6 +50,7 @@ BEGIN_MESSAGE_MAP(CDxwndhostView, CListView)
|
||||
ON_COMMAND(ID_ADD, OnAdd)
|
||||
ON_COMMAND(ID_MODIFY, OnModify)
|
||||
ON_COMMAND(ID_PEXPORT, OnExport)
|
||||
ON_COMMAND(ID_PKILL, OnProcessKill)
|
||||
ON_COMMAND(ID_FILE_IMPORT, OnImport)
|
||||
ON_COMMAND(ID_DELETE, OnDelete)
|
||||
ON_COMMAND(ID_FILE_SORTPROGRAMSLIST, OnSort)
|
||||
@ -525,6 +527,7 @@ void CDxwndhostView::OnModify()
|
||||
dlg.m_SuppressD3DExt = TargetMaps[i].flags3 & SUPPRESSD3DEXT ? 1 : 0;
|
||||
dlg.m_SetCompatibility = TargetMaps[i].flags2 & SETCOMPATIBILITY ? 1 : 0;
|
||||
dlg.m_SaveCaps = TargetMaps[i].flags3 & SAVECAPS ? 1 : 0;
|
||||
dlg.m_SingleProcAffinity = TargetMaps[i].flags3 & SINGLEPROCAFFINITY ? 1 : 0;
|
||||
dlg.m_LimitResources = TargetMaps[i].flags2 & LIMITRESOURCES ? 1 : 0;
|
||||
dlg.m_SaveLoad = TargetMaps[i].flags & SAVELOAD ? 1 : 0;
|
||||
dlg.m_SlowDown = TargetMaps[i].flags & SLOWDOWN ? 1 : 0;
|
||||
@ -646,6 +649,7 @@ void CDxwndhostView::OnModify()
|
||||
if(dlg.m_SuppressD3DExt) TargetMaps[i].flags3 |= SUPPRESSD3DEXT;
|
||||
if(dlg.m_SetCompatibility) TargetMaps[i].flags2 |= SETCOMPATIBILITY;
|
||||
if(dlg.m_SaveCaps) TargetMaps[i].flags3 |= SAVECAPS;
|
||||
if(dlg.m_SingleProcAffinity) TargetMaps[i].flags3 |= SINGLEPROCAFFINITY;
|
||||
if(dlg.m_SaveLoad) TargetMaps[i].flags |= SAVELOAD;
|
||||
if(dlg.m_SlowDown) TargetMaps[i].flags |= SLOWDOWN;
|
||||
if(dlg.m_BlitFromBackBuffer) TargetMaps[i].flags |= BLITFROMBACKBUFFER;
|
||||
@ -922,7 +926,6 @@ void CDxwndhostView::OnResume()
|
||||
{
|
||||
CTargetDlg dlg;
|
||||
HRESULT res;
|
||||
HANDLE TargetHandle;
|
||||
char sMsg[128+1];
|
||||
DXWNDSTATUS DxWndStatus;
|
||||
if ((GetHookStatus(&DxWndStatus) != DXW_RUNNING) || (DxWndStatus.hWnd==NULL)) {
|
||||
@ -970,6 +973,34 @@ void CDxwndhostView::OnKill()
|
||||
RevertScreenChanges(&this->InitDevMode);
|
||||
}
|
||||
|
||||
void CDxwndhostView::OnProcessKill()
|
||||
{
|
||||
int i;
|
||||
POSITION pos;
|
||||
CListCtrl& listctrl = GetListCtrl();
|
||||
char FilePath[MAX_PATH+1];
|
||||
char *lpProcName, *lpNext;
|
||||
HRESULT res;
|
||||
char sMsg[128+1];
|
||||
|
||||
if(!listctrl.GetSelectedCount()) return ;
|
||||
pos = listctrl.GetFirstSelectedItemPosition();
|
||||
i = listctrl.GetNextSelectedItem(pos);
|
||||
|
||||
strncpy(FilePath,TargetMaps[i].path,MAX_PATH);
|
||||
sprintf_s(sMsg, 128, "Do you want to kill \nthe \"%s\" task?", TitleMaps[i].title);
|
||||
res=MessageBoxEx(0, sMsg, "Warning", MB_YESNO | MB_ICONQUESTION, NULL);
|
||||
if(res!=IDYES) return;
|
||||
|
||||
lpProcName=FilePath;
|
||||
while (lpNext=strchr(lpProcName,'\\')) lpProcName=lpNext+1;
|
||||
|
||||
KillProcByName(lpProcName);
|
||||
|
||||
ClipCursor(NULL);
|
||||
RevertScreenChanges(&this->InitDevMode);
|
||||
}
|
||||
|
||||
void CDxwndhostView::OnAdd()
|
||||
{
|
||||
// TODO: Please add a command handler code here.
|
||||
@ -1037,6 +1068,7 @@ void CDxwndhostView::OnAdd()
|
||||
if(dlg.m_SuppressD3DExt) TargetMaps[i].flags3 |= SUPPRESSD3DEXT;
|
||||
if(dlg.m_SetCompatibility) TargetMaps[i].flags2 |= SETCOMPATIBILITY;
|
||||
if(dlg.m_SaveCaps) TargetMaps[i].flags3 |= SAVECAPS;
|
||||
if(dlg.m_SingleProcAffinity) TargetMaps[i].flags3 |= SINGLEPROCAFFINITY;
|
||||
if(dlg.m_LimitResources) TargetMaps[i].flags2 |= LIMITRESOURCES;
|
||||
if(dlg.m_SaveLoad) TargetMaps[i].flags |= SAVELOAD;
|
||||
if(dlg.m_SlowDown) TargetMaps[i].flags |= SLOWDOWN;
|
||||
@ -1390,6 +1422,9 @@ void CDxwndhostView::OnRButtonDown(UINT nFlags, CPoint point)
|
||||
case ID_TASK_KILL:
|
||||
OnKill();
|
||||
break;
|
||||
case ID_PKILL:
|
||||
OnProcessKill();
|
||||
break;
|
||||
case ID_TASK_PAUSE:
|
||||
OnPause();
|
||||
break;
|
||||
@ -1475,11 +1510,17 @@ DWORD WINAPI StartDebug(void *p)
|
||||
li->hFile, GetFileNameFromHandle(li->hFile));
|
||||
res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL);
|
||||
if(res!=IDYES) step=FALSE;
|
||||
if(!Inject(pinfo.dwProcessId, path)){
|
||||
sprintf(DebugMessage,"Injection error: pid=%x dll=%s", pinfo.dwProcessId, path);
|
||||
MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
//li=(LOAD_DLL_DEBUG_INFO *)&debug_event.u;
|
||||
//if(strstr(GetFileNameFromHandle(li->hFile), "ddraw.dll")){
|
||||
// res=MessageBoxEx(0, GetFileNameFromHandle(li->hFile), "ddraw.dll intercepted", MB_OK, NULL);
|
||||
// GetFullPathName("dxwnd.dll", MAX_PATH, path, NULL);
|
||||
// if(!Inject(pinfo.dwProcessId, path)){
|
||||
// sprintf(DebugMessage,"Injection error: pid=%x dll=%s", pinfo.dwProcessId, path);
|
||||
// MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL);
|
||||
// }
|
||||
//}
|
||||
break;
|
||||
case UNLOAD_DLL_DEBUG_EVENT:
|
||||
SetWindowText(Ghwnd, "UNLOAD DLL");
|
||||
|
@ -67,6 +67,7 @@ protected:
|
||||
afx_msg void OnDelete();
|
||||
afx_msg void OnExplore();
|
||||
afx_msg void OnKill();
|
||||
afx_msg void OnProcessKill();
|
||||
afx_msg void OnPause();
|
||||
afx_msg void OnResume();
|
||||
afx_msg void OnSort();
|
||||
|
1
release/.gitattributes
vendored
1
release/.gitattributes
vendored
@ -1 +0,0 @@
|
||||
*.{dll,exe} filter=lfs diff=lfs merge=lfs -text
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bce7a60e60155037cd12e0c1383f1078103923d7ba43a349e368606025bec75a
|
||||
size 343040
|
Loading…
x
Reference in New Issue
Block a user