/* 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 . */ #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include "dxwnd.h" #include "dxwcore.hpp" #include "TlHelp32.h" #define VERSION "2.04.21" #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] && (iAllowMultiTask)){ 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]; }