mirror of
https://github.com/DxWnd/DxWnd.reloaded
synced 2024-12-30 09:25:35 +01:00
406 lines
14 KiB
C++
406 lines
14 KiB
C++
/*
|
|
DXWnd/dxwnd.cpp
|
|
DirectX Hook Module
|
|
Copyright(C) 2004-2016 SFB7/GHO
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include "dxwnd.h"
|
|
#include "dxwcore.hpp"
|
|
|
|
#include "TlHelp32.h"
|
|
|
|
#define VERSION "2.04.20"
|
|
|
|
#define DDTHREADLOCK 1
|
|
|
|
LRESULT CALLBACK HookProc(int ncode, WPARAM wparam, LPARAM lparam);
|
|
|
|
HINSTANCE hInst;
|
|
HHOOK hHook;
|
|
HHOOK hMouseHook;
|
|
HANDLE hMapping;
|
|
TARGETMAP *pMapping;
|
|
DXWNDSTATUS *pStatus;
|
|
HANDLE hMutex;
|
|
HANDLE hTraceMutex;
|
|
HANDLE hLockMutex;
|
|
HANDLE hDDLockMutex;
|
|
HANDLE hKillMutex;
|
|
int HookStatus=DXW_IDLE;
|
|
static int TaskIndex=-1;
|
|
DXWNDSTATUS DxWndStatus;
|
|
|
|
void InjectHook();
|
|
|
|
BOOL APIENTRY DllMain( HANDLE hmodule,
|
|
DWORD dwreason,
|
|
LPVOID preserved
|
|
)
|
|
{
|
|
HANDLE hCurrentThread;
|
|
|
|
if(dwreason == DLL_PROCESS_DETACH){
|
|
//if(pInvalidateRect && pGetDesktopWindow) (*pInvalidateRect)((*pGetDesktopWindow)(), NULL, FALSE); // invalidate full desktop, no erase.
|
|
if(pInvalidateRect) (*pInvalidateRect)(0, NULL, FALSE); // invalidate full desktop, no erase.
|
|
UnmapViewOfFile(pMapping);
|
|
CloseHandle(hMapping);
|
|
}
|
|
|
|
if(dwreason != DLL_PROCESS_ATTACH) return TRUE;
|
|
|
|
hCurrentThread = GetCurrentThread();
|
|
SetThreadPriority(hCurrentThread, THREAD_PRIORITY_HIGHEST); // trick to reduce concurrency problems at program startup
|
|
|
|
hInst = (HINSTANCE)hmodule;
|
|
// optimization: disables DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the specified DLL
|
|
DisableThreadLibraryCalls((HMODULE)hmodule);
|
|
hMapping = CreateFileMapping((HANDLE)0xffffffff, NULL, PAGE_READWRITE,
|
|
0, sizeof(DxWndStatus)+sizeof(TARGETMAP)*MAXTARGETS, "UniWind_TargetList");
|
|
if(!hMapping) {
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
|
|
return false;
|
|
}
|
|
// v2.0.2.75: beware: some tasks (namely, Flash player) get dxwnd.dll loaded, but can't create the file mapping
|
|
// this situation has to be intercepted, or it can cause the dll to cause faults that may crash the program.
|
|
pStatus = (DXWNDSTATUS *)MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(DXWNDSTATUS)+sizeof(TARGETMAP)*MAXTARGETS);
|
|
if(!pStatus) return false;
|
|
pMapping = (TARGETMAP *)((char *)pStatus + sizeof(DXWNDSTATUS));
|
|
hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "UniWind_Mutex");
|
|
if(!hMutex) hMutex = CreateMutex(0, FALSE, "UniWind_Mutex");
|
|
hTraceMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "Trace_Mutex");
|
|
if(!hTraceMutex) hTraceMutex = CreateMutex(0, FALSE, "Trace_Mutex");
|
|
hLockMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "Lock_Mutex");
|
|
if(!hLockMutex) hLockMutex = CreateMutex(0, FALSE, "Lock_Mutex");
|
|
if(DDTHREADLOCK){
|
|
hDDLockMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "DDLock_Mutex");
|
|
if(!hDDLockMutex) hDDLockMutex = CreateMutex(0, FALSE, "DDLock_Mutex");
|
|
}
|
|
InjectHook();
|
|
|
|
SetThreadPriority(hCurrentThread, THREAD_PRIORITY_NORMAL);
|
|
CloseHandle(hCurrentThread);
|
|
return true;
|
|
}
|
|
|
|
static BOOL GetMultiTaskEnabling(){
|
|
char inipath[MAX_PATH];
|
|
GetModuleFileName(GetModuleHandle("dxwnd"), inipath, MAX_PATH);
|
|
inipath[strlen(inipath)-strlen("dxwnd.dll")] = 0; // terminate the string just before "dxwnd.dll"
|
|
strcat(inipath, "dxwnd.ini");
|
|
return GetPrivateProfileInt("window", "multiprocesshook", 0, inipath);
|
|
}
|
|
|
|
int SetTarget(DXWNDSTATUS *statusmap, TARGETMAP *targets){
|
|
int i;
|
|
char path[MAX_PATH+1];
|
|
|
|
WaitForSingleObject(hMutex, INFINITE);
|
|
pStatus->Status=DXW_IDLE;
|
|
pStatus->IsFullScreen=FALSE;
|
|
pStatus->TaskIdx=0;
|
|
pStatus->hWnd=NULL;
|
|
pStatus->ColorDepth=0;
|
|
memset((void *)&(pStatus->pfd), 0, sizeof(DDPIXELFORMAT));
|
|
pStatus->Height = pStatus->Width = 0;
|
|
pStatus->DXVersion = 0;
|
|
pStatus->AllowMultiTask=GetMultiTaskEnabling();
|
|
//pStatus->VJoyStatus=VJOYENABLED|CROSSENABLED|INVERTYAXIS;
|
|
if(statusmap) {
|
|
pStatus->VJoyStatus=statusmap->VJoyStatus;
|
|
pStatus->VJoySensivity=statusmap->VJoySensivity;
|
|
}
|
|
for(i = 0; targets[i].path[0]; i ++){
|
|
char *c;
|
|
pMapping[i] = targets[i];
|
|
c = targets[i].path;
|
|
if(*c == '*')
|
|
strcpy(path, targets[i].path);
|
|
else
|
|
GetFullPathName(targets[i].path, MAX_PATH, path, NULL);
|
|
for(c = path; *c; c++) *c = tolower(*c);
|
|
strcpy(pMapping[i].path, path);
|
|
}
|
|
pMapping[i].path[0] = 0;
|
|
ReleaseMutex(hMutex);
|
|
return i;
|
|
}
|
|
|
|
int StartHook(void)
|
|
{
|
|
hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInst, 0);
|
|
HookStatus=DXW_ACTIVE;
|
|
return 0;
|
|
}
|
|
|
|
int EndHook(void)
|
|
{
|
|
UnhookWindowsHookEx(hHook);
|
|
UnhookWindowsHookEx(hMouseHook);
|
|
HookStatus=DXW_IDLE;
|
|
return 0;
|
|
}
|
|
|
|
void GetDllVersion(char *dest)
|
|
{
|
|
strcpy_s(dest, strlen(VERSION)+1, VERSION);
|
|
}
|
|
|
|
int GetHookStatus(DXWNDSTATUS *s)
|
|
{
|
|
DWORD ret;
|
|
ret=WaitForSingleObject(hLockMutex, 0);
|
|
ReleaseMutex(hLockMutex);
|
|
if(ret==WAIT_TIMEOUT) {
|
|
if (s) *s = *pStatus;
|
|
return DXW_RUNNING;
|
|
}
|
|
return HookStatus;
|
|
}
|
|
|
|
DXWNDSTATUS *GetHookInfo()
|
|
{
|
|
return pStatus;
|
|
}
|
|
|
|
void SetFPS(int fps)
|
|
{
|
|
pStatus->FPSCount=fps;
|
|
}
|
|
|
|
LRESULT CALLBACK HookProc(int ncode, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
char name[MAX_PATH+1];
|
|
HWND hwnd;
|
|
int i;
|
|
static int DoOnce = FALSE;
|
|
|
|
// don't do more than once per process
|
|
if(DoOnce) return CallNextHookEx(hHook, ncode, wparam, lparam);
|
|
|
|
// take care here: if anything stops or delays the execution logic, the whole
|
|
// operating system hangs, since it can't activate new windows!
|
|
|
|
// could use WM_NCCREATE instead of WM_CREATE. Are there differences?
|
|
hwnd = ((CWPSTRUCT *)lparam)->hwnd;
|
|
if(((CWPSTRUCT *)lparam)->message == WM_CREATE){
|
|
int iNameLength;
|
|
name[MAX_PATH]=0; // string terminator
|
|
GetModuleFileName(0, name, MAX_PATH);
|
|
for(i = 0; name[i]; i ++) name[i] = tolower(name[i]);
|
|
iNameLength = strlen(name);
|
|
WaitForSingleObject(hMutex, INFINITE);
|
|
for(i = 0; pMapping[i].path[0] && (i<MAXTARGETS); i++){
|
|
register BOOL bMatched;
|
|
if (!(pMapping[i].flags3 & HOOKENABLED)) continue;
|
|
if(pMapping[i].path[0]=='*')
|
|
bMatched=!strncmp(&name[iNameLength-strlen(pMapping[i].path)+1], &pMapping[i].path[1], iNameLength);
|
|
else
|
|
bMatched=!strncmp(name, pMapping[i].path, iNameLength);
|
|
if(bMatched)
|
|
{
|
|
// V.68 late fix:
|
|
// check for locking thread (and hook) just once per process.
|
|
// This callback is invoked per each process' thread.
|
|
|
|
DoOnce = TRUE;
|
|
extern HHOOK hHook;
|
|
UnhookWindowsHookEx(hHook);
|
|
|
|
// V.68: concurrency check. One game at a time, or exiting.
|
|
// no good trying to insert fancy dialog boxes: the window
|
|
// isn't ready yet, and the operation fails.
|
|
|
|
// V2.03.07: allow multiple process hooking depending on config
|
|
if(!(pStatus->AllowMultiTask)){
|
|
if(WaitForSingleObject(hLockMutex, 0)==WAIT_TIMEOUT){
|
|
ReleaseMutex(hMutex);
|
|
exit(0);
|
|
}
|
|
}
|
|
else
|
|
WaitForSingleObject(hLockMutex, 0);
|
|
|
|
pStatus->Status=DXW_RUNNING;
|
|
pStatus->TaskIdx=i;
|
|
pStatus->OrigIdx=pMapping[i].index;
|
|
pStatus->IsFullScreen=FALSE;
|
|
pStatus->hWnd=hwnd;
|
|
pStatus->dwPid=GetProcessId(GetCurrentProcess());
|
|
pStatus->TimeShift=pMapping[i].InitTS;
|
|
pStatus->CursorX = pStatus->CursorY = 0;
|
|
memset((void *)&(pStatus->pfd), 0, sizeof(DDPIXELFORMAT));
|
|
DxWndStatus = *pStatus;
|
|
HookInit(&pMapping[i], hwnd);
|
|
}
|
|
}
|
|
ReleaseMutex(hMutex);
|
|
}
|
|
return CallNextHookEx(hHook, ncode, wparam, lparam);
|
|
}
|
|
|
|
void UnhookProc()
|
|
{
|
|
// used to unhook DxWnd from the current process and allow another one (a son) to be managed
|
|
//ReleaseMutex(hMutex);
|
|
ReleaseMutex(hLockMutex);
|
|
UnmapViewOfFile(pMapping);
|
|
CloseHandle(hMapping);
|
|
}
|
|
|
|
void InjectHook()
|
|
{
|
|
char name[MAX_PATH+1];
|
|
int i;
|
|
GetModuleFileName(0, name, MAX_PATH);
|
|
name[MAX_PATH]=0; // terminator
|
|
for(char *c = name; *c; c++) *c = tolower(*c);
|
|
for(i = 0; pMapping[i].path[0]; i ++){
|
|
if(pMapping[i].flags3 & HOOKENABLED){
|
|
if(!strncmp(name, pMapping[i].path, strlen(name))){
|
|
if ((pMapping[i].flags2 & STARTDEBUG) || (pMapping[i].flags7 & INJECTSUSPENDED)) {
|
|
HookInit(&pMapping[i],NULL);
|
|
// beware: logging is possible only AFTER HookInit execution
|
|
OutTrace("InjectHook: task[%d]=\"%s\" hooked\n", i, pMapping[i].path);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static char *FlagNames[11][32] ={{
|
|
// Flags1
|
|
"UNNOTIFY", "EMULATESURFACE", "CLIPCURSOR", "NEEDADMINCAPS",
|
|
"HOOKDI", "MODIFYMOUSE", "HANDLEEXCEPTIONS", "SAVELOAD",
|
|
"EMULATEBUFFER", "HOOKDI8", "BLITFROMBACKBUFFER", "SUPPRESSCLIPPING",
|
|
"AUTOREFRESH", "FIXWINFRAME", "HIDEHWCURSOR", "SLOWDOWN",
|
|
"DISABLECLIPPING", "LOCKWINSTYLE", "MAPGDITOPRIMARY", "FIXTEXTOUT",
|
|
"KEEPCURSORWITHIN", "USERGB565", "SUPPRESSDXERRORS", "PREVENTMAXIMIZE",
|
|
"LOCKEDSURFACE", "FIXPARENTWIN", "SWITCHVIDEOMEMORY", "CLIENTREMAPPING",
|
|
"HANDLEALTF4", "LOCKWINPOS", "HOOKCHILDWIN", "MESSAGEPROC"
|
|
},{
|
|
// Flags2
|
|
"RECOVERSCREENMODE", "REFRESHONRESIZE", "BACKBUFATTACH", "MODALSTYLE",
|
|
"KEEPASPECTRATIO", "INIT8BPP", "FORCEWINRESIZE", "INIT16BPP",
|
|
"KEEPCURSORFIXED", "DISABLEGAMMARAMP", "INDEPENDENTREFRESH", "FIXNCHITTEST",
|
|
"LIMITFPS", "SKIPFPS", "SHOWFPS", "HIDEMULTIMONITOR",
|
|
"TIMESTRETCH", "HOOKOPENGL", "LOCKEDSIZE", "SHOWHWCURSOR",
|
|
"GDISTRETCHED", "SHOWFPSOVERLAY", "FAKEVERSION", "FULLRECTBLT",
|
|
"NOPALETTEUPDATE", "SUPPRESSIME", "NOBANNER", "WINDOWIZE",
|
|
"LIMITRESOURCES", "STARTDEBUG", "SETCOMPATIBILITY", "WIREFRAME",
|
|
},{
|
|
// Flags3
|
|
"FORCEHOOKOPENGL", "MARKBLIT", "HOOKDLLS", "SUPPRESSD3DEXT",
|
|
"HOOKENABLED", "FIXD3DFRAME", "FORCE16BPP", "BLACKWHITE",
|
|
"MARKLOCK", "SINGLEPROCAFFINITY", "EMULATEREGISTRY", "CDROMDRIVETYPE",
|
|
"NOWINDOWMOVE", "FORCECLIPPER", "LOCKSYSCOLORS", "GDIEMULATEDC",
|
|
"FULLSCREENONLY", "FONTBYPASS", "MINIMALCAPS", "DEFAULTMESSAGES",
|
|
"BUFFEREDIOFIX", "FILTERMESSAGES", "PEEKALLMESSAGES", "SURFACEWARN",
|
|
"ANALYTICMODE", "FORCESHEL", "CAPMASK", "COLORFIX",
|
|
"NODDRAWBLT", "NODDRAWFLIP", "NOGDIBLT", "NOPIXELFORMAT",
|
|
},{
|
|
// Flags4
|
|
"NOALPHACHANNEL", "SUPPRESSCHILD", "FIXREFCOUNTER", "SHOWTIMESTRETCH",
|
|
"ZBUFFERCLEAN", "ZBUFFER0CLEAN", "ZBUFFERALWAYS", "DISABLEFOGGING",
|
|
"NOPOWER2FIX", "NOPERFCOUNTER", "BILINEAR2XFILTER", "INTERCEPTRDTSC",
|
|
"LIMITSCREENRES", "NOFILLRECT", "HOOKGLIDE", "HIDEDESKTOP",
|
|
"STRETCHTIMERS", "NOFLIPEMULATION", "NOTEXTURES", "RETURNNULLREF",
|
|
"FINETIMING", "NATIVERES", "SUPPORTSVGA", "SUPPORTHDTV",
|
|
"RELEASEMOUSE", "ENABLETIMEFREEZE", "HOTPATCH", "ENABLEHOTKEYS",
|
|
"HOTPATCHALWAYS", "NOD3DRESET", "OVERRIDEREGISTRY", "HIDECDROMEMPTY",
|
|
},{
|
|
// Flags5
|
|
"DIABLOTWEAK", "CLEARTARGET", "NOWINPOSCHANGES", "ANSIWIDE",
|
|
"NOBLT", "USELASTCORE", "DOFASTBLT", "AEROBOOST",
|
|
"QUARTERBLT", "NOIMAGEHLP", "BILINEARFILTER", "REPLACEPRIVOPS",
|
|
"REMAPMCI", "TEXTUREHIGHLIGHT", "TEXTUREDUMP", "TEXTUREHACK",
|
|
"TEXTURETRANSP", "NORMALIZEPERFCOUNT", "HYBRIDMODE", "GDICOLORCONV",
|
|
"INJECTSON", "ENABLESONHOOK", "FREEZEINJECTEDSON", "GDIMODE",
|
|
"CENTERTOWIN", "STRESSRESOURCES", "MESSAGEPUMP", "TEXTUREFORMAT",
|
|
"DEINTERLACE", "LOCKRESERVEDPALETTE", "UNLOCKZORDER", "EASPORTSHACK",
|
|
},{
|
|
// Flags6
|
|
"FORCESWAPEFFECT", "LEGACYALLOC", "NODESTROYWINDOW", "NOMOVIES",
|
|
"SUPPRESSRELEASE", "FIXMOVIESCOLOR", "WOW64REGISTRY", "DISABLEMAXWINMODE",
|
|
"FIXPITCH", "POWER2WIDTH", "HIDETASKBAR", "ACTIVATEAPP",
|
|
"NOSYSMEMPRIMARY", "NOSYSMEMBACKBUF", "CONFIRMONCLOSE", "TERMINATEONCLOSE",
|
|
"FLIPEMULATION", "SETZBUFFERBITDEPTHS", "SHAREDDC", "WOW32REGISTRY",
|
|
"STRETCHMOVIES", "BYPASSMCI", "FIXPIXELZOOM", "---REUSEEMULATEDDC---",
|
|
"CREATEDESKTOP", "NOWINDOWHOOKS", "SYNCPALETTE", "VIRTUALJOYSTICK",
|
|
"UNACQUIRE", "HOOKGOGLIBS", "BYPASSGOGLIBS", "EMULATERELMOUSE",
|
|
},{
|
|
// Flags7
|
|
"LIMITDDRAW", "DISABLEDISABLEALTTAB", "FIXCLIPPERAREA", "HOOKDIRECTSOUND",
|
|
"HOOKSMACKW32", "BLOCKPRIORITYCLASS", "CPUSLOWDOWN", "CPUMAXUSAGE",
|
|
"NOWINERRORS", "SUPPRESSOVERLAY", "INIT24BPP", "INIT32BPP",
|
|
"FIXGLOBALUNLOCK", "SHOWHINTS", "SKIPDEVTYPEHID", "INJECTSUSPENDED",
|
|
"SSUPPRESSDIERRORS", "HOOKNORUN", "FIXBINDTEXTURE", "ENUM16BITMODES",
|
|
"SHAREDKEYBOARD", "HOOKNOUPDATE", "HOOKGLUT32", "INITIALRES",
|
|
"MAXIMUMRES", "LOCKCOLORDEPTH", "FIXSMACKLOOP", "FIXFREELIBRARY",
|
|
"ANCHORED", "CLEARTEXTUREFOURCC", "NODDEXCLUSIVEMODE", "COPYNOSHIMS",
|
|
},{
|
|
// Flags8
|
|
"FORCEWAIT", "FORCENOWAIT", "FORCEVSYNC", "FORCENOVSYNC",
|
|
"VSYNCSCANLINES", "TRIMTEXTUREFORMATS", "NOHALDEVICE", "CLIPLOCK",
|
|
"PRETENDVISIBLE", "RAWFORMAT", "WININSULATION", "FIXMOUSEHOOK",
|
|
"DDSFORMAT", "HOOKWING32", "SEQUENCEDIAT", "D3D8BACK16",
|
|
"MARKWING32", "DYNAMICZCLEAN", "MARKGDI32", "DUMPDIBSECTION",
|
|
"DUMPDEVCONTEXT", "QUALITYFONTS", "ALLOWSYSMEMON3DDEV", "CLIPMENU",
|
|
"BACKGROUNDPRIORITY", "OFFSCREENZBUFFER", "VIRTUALHEAP", "ZBUFFERHARDCLEAN",
|
|
"LOADLIBRARYERR", "SHAREDDCHYBRID", "FIXADJUSTWINRECT", "HOOKDLGWIN",
|
|
},{
|
|
// Flags9
|
|
"FIXTHINFRAME", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "", },{
|
|
// Flags10
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "", },{
|
|
// TFlags
|
|
"OUTTRACE", "OUTDDRAWTRACE", "OUTWINMESSAGES", "OUTCURSORTRACE",
|
|
"OUTSEPARATED", "**", "ASSERTDIALOG", "OUTIMPORTTABLE",
|
|
"OUTDEBUG", "OUTREGISTRY", "TRACEHOOKS", "OUTD3DTRACE",
|
|
"OUTDXWINTRACE", "OUTWINGTRACE", "OUTOGLTRACE", "",
|
|
"", "", "", "",
|
|
"", "", "", "",
|
|
"", "", "", "ADDRELATIVETIME",
|
|
"**", "ADDTIMESTAMP", "OUTDEBUGSTRING", "ERASELOGFILE",
|
|
}};
|
|
|
|
LPCSTR GetFlagCaption(int flag, int bit)
|
|
{
|
|
//if((flag<0) || (flag>(9*32))) return "";
|
|
//return FlagNames[flag >> 5][flag & 0x1F];
|
|
if((flag<0) || (flag>10)) return "";
|
|
if((bit<0) || (bit>31)) return "";
|
|
return FlagNames[flag][bit];
|
|
} |