diff --git a/Include/dxwnd.h b/Include/dxwnd.h index d1ac928..bd9aee0 100644 --- a/Include/dxwnd.h +++ b/Include/dxwnd.h @@ -216,6 +216,7 @@ // seventh flags DWORD dxw.dwFlags7: #define LIMITDDRAW 0x00000001 // Limit the maximum available ddraw object version +#define DISABLEDISABLEALTTAB 0x00000002 // Disables the compatibility patch that disables the Alt-Tab key and other special combinations // eighth flags DWORD dxw.dwFlags8: diff --git a/build/dxwnd.0.ini b/build/dxwnd.0.ini deleted file mode 100644 index be2c649..0000000 --- a/build/dxwnd.0.ini +++ /dev/null @@ -1,31 +0,0 @@ -[window] -posx=50 -posy=50 -sizx=320 -sizy=200 -lang=default -;lang=automatic -;updatepaths=1 -;debug=1 -;multiprocesshook=0 -;checkadmin=0 -[texture] -MinTexX=16 -MaxTexX=0 -MinTexY=16 -MaxTexY=0 -[keymapping] -timetoggle=0x72 -altf4=0x73 -timeslow=0x74 -timefast=0x75 -cliptoggle= -refresh= -logtoggle= -plocktoggle= -fpstoggle= -printscreen=0x7B -corner=0x7A -freezetime=0x79 - - diff --git a/build/dxwnd.dll b/build/dxwnd.dll index 8b2a2c0..db4fbd5 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:935f85ba0560e2c0a319ea4a007c0f24de314cc7207710fdcd4d41e6a4fbb39a -size 593920 +oid sha256:b9f75f7b545dbfc03a38bf99d8260cbbe4dee01c82b7955c61769a126c643b82 +size 622080 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index 71ed249..a1deeb2 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82bd1f60071207b5033f2deade63c46438a048357e3cb0e4d5aa5b379da92186 -size 545792 +oid sha256:91dd24684d705c58f1e0bb5870715a997c93b285d02075571f0f8ef87068adec +size 548352 diff --git a/build/exports/Age of Empires III.dxw b/build/exports/Age of Empires III.dxw index b52c0c3..229b1b7 100644 --- a/build/exports/Age of Empires III.dxw +++ b/build/exports/Age of Empires III.dxw @@ -5,11 +5,11 @@ module0= opengllib0= ver0=0 coord0=0 -flag0=-394124766 +flag0=1753358370 flagg0=134217728 flagh0=20 -flagi0=4194304 -tflag0=0 +flagi0=0 +tflag0=3 initx0=0 inity0=0 minx0=0 @@ -22,14 +22,3 @@ sizx0=800 sizy0=600 maxfps0=0 initts0=0 -launchpath0= -notes0= -registry0= -flagj0=0 -flagk0=0 -flagl0=0 -flagm0=0 -winver0=0 -maxres0=0 -swapeffect0=0 -maxddinterface0=7 diff --git a/build/exports/Age of Wonders.dxw b/build/exports/Age of Wonders.dxw index 0162307..9468df5 100644 --- a/build/exports/Age of Wonders.dxw +++ b/build/exports/Age of Wonders.dxw @@ -6,7 +6,7 @@ module0= opengllib0= ver0=0 coord0=0 -flag0=679477794 +flag0=679477792 flagg0=1207959552 flagh0=20 flagi0=205520900 @@ -26,10 +26,3 @@ initts0=0 winver0=0 maxres0=-1 flagj0=128 -notes0= -registry0= -flagk0=65536 -flagl0=0 -flagm0=0 -swapeffect0=0 -maxddinterface0=7 diff --git a/build/exports/Dark Colony (16 bit).dxw b/build/exports/Dark Colony (16 bit).dxw deleted file mode 100644 index 93cc224..0000000 --- a/build/exports/Dark Colony (16 bit).dxw +++ /dev/null @@ -1,29 +0,0 @@ -[target] -title0=Dark Colony (16 bit) -path0=D:\Games\DarkColony\DCOLONY\DC16.EXE -launchpath0= -module0= -opengllib0= -notes0= -registry0= -ver0=0 -coord0=0 -flag0=134234166 -flagg0=1207959552 -flagh0=20 -flagi0=4194308 -flagj0=67108992 -flagk0=0 -flagl0=0 -flagm0=0 -tflag0=0 -posx0=50 -posy0=50 -sizx0=800 -sizy0=600 -maxfps0=0 -initts0=0 -winver0=0 -maxres0=-1 -swapeffect0=0 -maxddinterface0=7 diff --git a/build/exports/Dark Colony.dxw b/build/exports/Dark Colony.dxw index 6a44e7b..f23cefd 100644 --- a/build/exports/Dark Colony.dxw +++ b/build/exports/Dark Colony.dxw @@ -5,7 +5,7 @@ module0= opengllib0= ver0=0 coord0=0 -flag0=134234166 +flag0=134218274 flagg0=1207959552 flagh0=20 flagi0=4194308 @@ -30,6 +30,3 @@ notes0= registry0= flagk0=0 swapeffect0=0 -flagl0=0 -flagm0=0 -maxddinterface0=7 diff --git a/build/exports/Nox (GOG).dxw b/build/exports/Nox (GOG).dxw deleted file mode 100644 index 15381e8..0000000 --- a/build/exports/Nox (GOG).dxw +++ /dev/null @@ -1,28 +0,0 @@ -[target] -title0=Nox (GOG) -path0=D:\Games\Nox GOG\Game.exe -launchpath0= -module0= -opengllib0= -notes0= -registry0= -ver0=0 -coord0=0 -flag0=681574434 -flagg0=1207959552 -flagh0=20 -flagi0=134217732 -flagj0=4224 -flagk0=65536 -flagl0=0 -flagm0=0 -tflag0=0 -posx0=50 -posy0=50 -sizx0=800 -sizy0=600 -maxfps0=0 -initts0=0 -winver0=0 -maxres0=-1 -swapeffect0=0 diff --git a/build/exports/Nox (RIP).dxw b/build/exports/Nox (RIP).dxw deleted file mode 100644 index 494e2fd..0000000 --- a/build/exports/Nox (RIP).dxw +++ /dev/null @@ -1,28 +0,0 @@ -[target] -title0=Nox (RIP) -path0=D:\Games\Nox RIP\GAME.EXE -launchpath0= -module0= -opengllib0= -notes0= -registry0= -ver0=0 -coord0=2 -flag0=681574434 -flagg0=1207959568 -flagh0=20 -flagi0=138412036 -flagj0=5248 -flagk0=65536 -flagl0=0 -flagm0=0 -tflag0=0 -posx0=50 -posy0=50 -sizx0=800 -sizy0=600 -maxfps0=0 -initts0=0 -winver0=0 -maxres0=-1 -swapeffect0=0 diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index aa60f11..4614622 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -1022,4 +1022,11 @@ fix: used fake resolutions also in USER32 EnumDisplaySettings fix: avoid hooking directinput dlls if not requested when loaded dynamically fix: added recovery of lost device in DirectInput GetDeviceData method fix: changed SetHook so that it can get function pointers without necessarily replacing them -add: option "Limit ddraw interface" to exclude support for IDirectDrawInterface greater than limit (range 1-7) \ No newline at end of file +add: option "Limit ddraw interface" to exclude support for IDirectDrawInterface greater than limit (range 1-7) + +v2.03.53(skipped) +v2.03.54 +add: syslib shared dc mode preliminary implementation, thank to Narzoul's ideas. Works for "MS Golf 98" and "Deadlock II rel. 1.2" +fix: handling of cursor hide/show for programs that don't go through the message window ("Deadlock II rel. 1.2") +add: /R:n command line option to automatically start DxWnd in icon tray, run the n-th program in configuration and terminate. +add: option to disable the disabling of Alt-Tab key through SetWindowHooks through WH_KEYBOARD_LL event. Mae it posssible to use Alt-Tab key on "Dungeon Kepper II". \ No newline at end of file diff --git a/dll/ddraw.cpp b/dll/ddraw.cpp index df09254..81d3510 100644 --- a/dll/ddraw.cpp +++ b/dll/ddraw.cpp @@ -148,6 +148,8 @@ DirectDrawCreateEx_Type pDirectDrawCreateEx = NULL; DirectDrawEnumerate_Type pDirectDrawEnumerate = NULL; DirectDrawEnumerateEx_Type pDirectDrawEnumerateEx = NULL; DirectDrawCreateClipper_Type pDirectDrawCreateClipper = NULL; +HandleDDThreadLock_Type pAcquireDDThreadLock = NULL; +HandleDDThreadLock_Type pReleaseDDThreadLock = NULL; /* DirectDraw hook pointers */ QueryInterface_Type pQueryInterfaceD1; @@ -310,6 +312,8 @@ static HookEntry_Type ddHooks[]={ {HOOK_HOT_CANDIDATE, "DirectDrawEnumerateA", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerate, (FARPROC)extDirectDrawEnumerate}, {HOOK_HOT_CANDIDATE, "DirectDrawEnumerateExA", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerateEx, (FARPROC)extDirectDrawEnumerateEx}, {HOOK_HOT_CANDIDATE, "DirectDrawCreateClipper", (FARPROC)NULL, (FARPROC *)&pDirectDrawCreateClipper, (FARPROC)extDirectDrawCreateClipper}, + {HOOK_HOT_CANDIDATE, "AcquireDDThreadLock", (FARPROC)NULL, (FARPROC *)&pAcquireDDThreadLock, (FARPROC)NULL}, + {HOOK_HOT_CANDIDATE, "ReleaseDDThreadLock", (FARPROC)NULL, (FARPROC *)&pReleaseDDThreadLock, (FARPROC)NULL}, //{HOOK_IAT_CANDIDATE, "DirectDrawEnumerateW", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerateW, (FARPROC)extDirectDrawCreate}, //{HOOK_IAT_CANDIDATE, "DirectDrawEnumerateExW", (FARPROC)NULL, (FARPROC *)&pDirectDrawEnumerateExW, (FARPROC)extDirectDrawCreate}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator diff --git a/dll/dxhelper.cpp b/dll/dxhelper.cpp index 9b7dcac..60a1b9f 100644 --- a/dll/dxhelper.cpp +++ b/dll/dxhelper.cpp @@ -1907,4 +1907,27 @@ char *ExplainPixelFormat(LPDDPIXELFORMAT ddpfPixelFormat) strcat(sBuf, sItem); } return sBuf; +} + +char *GetObjectTypeStr(HDC hdc) +{ + char *s; + switch (GetObjectType(hdc)){ + case OBJ_PEN: s="PEN"; break; + case OBJ_BRUSH: s="BRUSH"; break; + case OBJ_DC: s="DC"; break; + case OBJ_METADC: s="METADC"; break; + case OBJ_PAL: s="PAL"; break; + case OBJ_FONT: s="FONT"; break; + case OBJ_BITMAP: s="BITMAP"; break; + case OBJ_REGION: s="REGION"; break; + case OBJ_METAFILE: s="METAFILE"; break; + case OBJ_MEMDC: s="MEMDC"; break; + case OBJ_EXTPEN: s="EXTPEN"; break; + case OBJ_ENHMETADC: s="ENHMETADC"; break; + case OBJ_ENHMETAFILE: s="ENHMETAFILE"; break; + case OBJ_COLORSPACE: s="COLORSPACE"; break; + default: s="unknown"; break; + } + return s; } \ No newline at end of file diff --git a/dll/dxhelper.h b/dll/dxhelper.h index 7eadb97..c116b48 100644 --- a/dll/dxhelper.h +++ b/dll/dxhelper.h @@ -54,3 +54,4 @@ extern char *ExplainDICooperativeFlags(DWORD); extern char *ExplainRegionType(DWORD); extern char *ExplainPixelFormat(LPDDPIXELFORMAT); extern char *ExplainZBufferBitDepths(DWORD); +extern char *GetObjectTypeStr(HDC); diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp index 1c3461e..5ea5551 100644 --- a/dll/dxhook.cpp +++ b/dll/dxhook.cpp @@ -8,6 +8,7 @@ #include #include "dxwnd.h" #include "dxwcore.hpp" +#include "shareddc.hpp" #include "dxhook.h" #include "glhook.h" #include "glidehook.h" @@ -28,6 +29,7 @@ dxwCore dxw; dxwSStack dxwss; dxwWStack dxwws; +dxwSDC sdc; extern LRESULT CALLBACK MessageHook(int, WPARAM, LPARAM); @@ -1368,7 +1370,7 @@ void HookInit(TARGETMAP *target, HWND hwnd) InitScreenParameters(); if(hwnd) HookWindowProc(hwnd); // in fullscreen mode, messages seem to reach and get processed by the parent window - if((!dxw.Windowize) && hwnd) HookWindowProc(GetParent(hwnd)); + if((!dxw.Windowize) && hwnd) HookWindowProc(dxw.hParentWnd); // initialize window: if // 1) not in injection mode (hwnd != 0) and @@ -1409,8 +1411,9 @@ FARPROC RemapLibrary(LPCSTR proc, HMODULE hModule, HookEntry_Type *Hooks) void *remapped_addr; for(; Hooks->APIName; Hooks++){ if (!strcmp(proc,Hooks->APIName)){ - if((((dxw.dwFlags4 & HOTPATCH) && (Hooks->HookStatus == HOOK_HOT_CANDIDATE)) || // hot patch candidate still to process - or - ((dxw.dwFlags4 & HOTPATCHALWAYS) && (Hooks->HookStatus != HOOK_HOT_LINKED)))){ // force hot patch and not already hooked + if ((Hooks->HookStatus == HOOK_HOT_REQUIRED) || + ((dxw.dwFlags4 & HOTPATCH) && (Hooks->HookStatus == HOOK_HOT_CANDIDATE)) || // hot patch candidate still to process - or + ((dxw.dwFlags4 & HOTPATCHALWAYS) && (Hooks->HookStatus != HOOK_HOT_LINKED))){ // force hot patch and not already hooked if(!Hooks->OriginalAddress) { Hooks->OriginalAddress=(*pGetProcAddress)(hModule, Hooks->APIName); @@ -1462,7 +1465,8 @@ void HookLibrary(HMODULE hModule, HookEntry_Type *Hooks, char *DLLName) // continue; //} - if((((dxw.dwFlags4 & HOTPATCH) && (Hooks->HookStatus == HOOK_HOT_CANDIDATE)) || // hot patch candidate still to process - or + if(((Hooks->HookStatus == HOOK_HOT_REQUIRED) || + ((dxw.dwFlags4 & HOTPATCH) && (Hooks->HookStatus == HOOK_HOT_CANDIDATE)) || // hot patch candidate still to process - or ((dxw.dwFlags4 & HOTPATCHALWAYS) && (Hooks->HookStatus != HOOK_HOT_LINKED))) // force hot patch and not already hooked && Hooks->StoreAddress){ // and save ptr available diff --git a/dll/dxhook.h b/dll/dxhook.h index db3cd1e..aab2799 100644 --- a/dll/dxhook.h +++ b/dll/dxhook.h @@ -47,6 +47,7 @@ extern FARPROC Remap_DInput8_ProcAddress(LPCSTR, HMODULE); typedef enum { HOOK_IAT_CANDIDATE = 0, HOOK_HOT_CANDIDATE, + HOOK_HOT_REQUIRED, HOOK_IAT_LINKED, HOOK_HOT_LINKED } HookEntry_Status; diff --git a/dll/dxwcore.cpp b/dll/dxwcore.cpp index 0a70508..bfd77f2 100644 --- a/dll/dxwcore.cpp +++ b/dll/dxwcore.cpp @@ -11,6 +11,7 @@ #include "d3d9.h" extern GetDC_Type pGetDC; extern ReleaseDC_Type pReleaseDC; +extern HandleDDThreadLock_Type pReleaseDDThreadLock; /* ------------------------------------------------------------------ */ // Internal function pointers @@ -72,8 +73,12 @@ void dxwCore::SetFullScreen(BOOL fs) BOOL dxwCore::IsFullScreen() { - //if(!Windowize) return FALSE; - return FullScreen; + return (Windowize && FullScreen); +} + +BOOL dxwCore::IsToRemap(HDC hdc) +{ + return (Windowize && FullScreen && (OBJ_DC == (*pGetObjectType)(hdc))); } void dxwCore::InitTarget(TARGETMAP *target) @@ -128,9 +133,10 @@ void dxwCore::InitTarget(TARGETMAP *target) iRatioX = iSizX ? iSizX : 800; iRatioY = iSizY ? iSizY : 600; - GDIEmulationMode = GDIMODE_STRETCHED; // default + GDIEmulationMode = GDIMODE_NONE; // default if (dwFlags2 & GDISTRETCHED) GDIEmulationMode = GDIMODE_STRETCHED; if (dwFlags3 & GDIEMULATEDC) GDIEmulationMode = GDIMODE_EMULATED; + if (dwFlags6 & SHAREDDC) GDIEmulationMode = GDIMODE_SHAREDDC; } void dxwCore::SetScreenSize(void) @@ -367,19 +373,6 @@ POINT dxwCore::FixCursorPos(POINT prev) if (h) curr.y = (curr.y * dxw.GetScreenHeight()) / h; } - //if(dxw.dwFlags4 & FRAMECOMPENSATION){ - // static int dx, dy, todo=TRUE; - // if (todo){ - // POINT FrameOffset = dxw.GetFrameOffset(); - // dx=FrameOffset.x; - // dy=FrameOffset.y; - // OutTraceC("GetCursorPos: frame compensation=(%d,%d)\n", dx, dy); - // todo=FALSE; - // } - // curr.x += dx; - // curr.y += dy; - //} - if((dxw.dwFlags1 & ENABLECLIPPING) && lpClipRegion){ // v2.1.93: // in clipping mode, avoid the cursor position to lay outside the valid rect @@ -400,14 +393,6 @@ POINT dxwCore::FixCursorPos(POINT prev) if (curr.y >= (LONG)dxw.GetScreenHeight()-CLIP_TOLERANCE) curr.y=dxw.GetScreenHeight()-1; } - //if(0){ // Scrolling Slow-down - // if( (curr.x <= 0) || - // (curr.x >= (LONG)(dxw.GetScreenWidth()-1)) || - // (curr.y <= 0) || - // (curr.y >= (LONG)(dxw.GetScreenHeight()-1))) - // (*pSleep)(800); - //} - return curr; } @@ -1632,7 +1617,7 @@ void dxwCore::ResetEmulatedDC() BOOL dxwCore::IsVirtual(HDC hdc) { - return (hdc==VirtualHDC) && (dwFlags3 & GDIEMULATEDC); + return (hdc==VirtualHDC) && (GDIEmulationMode == GDIMODE_EMULATED); } HDC dxwCore::AcquireSharedDC(HWND hwnd) @@ -1640,12 +1625,15 @@ HDC dxwCore::AcquireSharedDC(HWND hwnd) extern HDC hFlippedDC; LPDIRECTDRAWSURFACE lpDDSPrim; lpDDSPrim = dxwss.GetPrimarySurface(); - if (lpDDSPrim) (*pGetDC)(lpDDSPrim, &hFlippedDC); - while((hFlippedDC == NULL) && lpDDSPrim) { - OutTraceDW("AcquireSharedDC: found primary surface with no DC, unref lpdds=%x\n", lpDDSPrim); - dxwss.UnrefSurface(lpDDSPrim); - lpDDSPrim = dxwss.GetPrimarySurface(); - if (lpDDSPrim) (*pGetDC)(lpDDSPrim, &hFlippedDC); + if (lpDDSPrim) { + if(pReleaseDDThreadLock)(*pReleaseDDThreadLock)(); + (*pGetDC)(lpDDSPrim, &hFlippedDC); + while((hFlippedDC == NULL) && lpDDSPrim) { + OutTraceDW("AcquireSharedDC: found primary surface with no DC, unref lpdds=%x\n", lpDDSPrim); + dxwss.UnrefSurface(lpDDSPrim); + lpDDSPrim = dxwss.GetPrimarySurface(); + if (lpDDSPrim) (*pGetDC)(lpDDSPrim, &hFlippedDC); + } } if (!(hwnd == dxw.GethWnd())) { POINT father, child, offset; diff --git a/dll/dxwcore.hpp b/dll/dxwcore.hpp index 238e441..611be01 100644 --- a/dll/dxwcore.hpp +++ b/dll/dxwcore.hpp @@ -56,6 +56,7 @@ public: // methods void SetFullScreen(BOOL); void SetFullScreen(BOOL, int); BOOL IsFullScreen(); + BOOL IsToRemap(HDC); BOOL IsDesktop(HWND); BOOL IsRealDesktop(HWND); POINT FixCursorPos(POINT); @@ -357,8 +358,12 @@ typedef enum { DXVK_SIZE }; -#define GDIMODE_STRETCHED 0 -#define GDIMODE_EMULATED 1 +typedef enum { + GDIMODE_NONE = 0, + GDIMODE_STRETCHED, + GDIMODE_EMULATED, + GDIMODE_SHAREDDC +}; typedef HRESULT (WINAPI *ColorConversion_Type)(LPDIRECTDRAWSURFACE, RECT, LPDIRECTDRAWSURFACE *); extern ColorConversion_Type pColorConversion; diff --git a/dll/dxwnd.aps b/dll/dxwnd.aps index ea03d65..7123e81 100644 Binary files a/dll/dxwnd.aps and b/dll/dxwnd.aps differ diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index babde65..56f8f1e 100644 --- a/dll/dxwnd.cpp +++ b/dll/dxwnd.cpp @@ -27,7 +27,7 @@ along with this program. If not, see . #include "TlHelp32.h" -#define VERSION "2.03.52" +#define VERSION "2.03.54" #define DDTHREADLOCK 1 //#define LOCKTHREADS diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index 1c97efc..997cf29 100644 Binary files a/dll/dxwnd.vs2008.suo and b/dll/dxwnd.vs2008.suo differ diff --git a/dll/dxwnd.vs2008.vcproj b/dll/dxwnd.vs2008.vcproj index 1ab5fc5..9115aa3 100644 --- a/dll/dxwnd.vs2008.vcproj +++ b/dll/dxwnd.vs2008.vcproj @@ -445,6 +445,10 @@ RelativePath=".\msghook.cpp" > + + @@ -457,6 +461,10 @@ RelativePath=".\opengl.cpp" > + + @@ -526,6 +534,10 @@ RelativePath=".\resource.h" > + + diff --git a/dll/gdi32.cpp b/dll/gdi32.cpp index e48a5b2..4c9c8d3 100644 --- a/dll/gdi32.cpp +++ b/dll/gdi32.cpp @@ -6,9 +6,12 @@ #include "hddraw.h" #include "dxhook.h" #include "dxhelper.h" +#include "shareddc.hpp" #include "stdio.h" +static BOOL bGDIRecursionFlag = FALSE; + static void Stopper(char *s, int line) { char sMsg[81]; @@ -19,7 +22,7 @@ static void Stopper(char *s, int line) //#define STOPPER_TEST // comment out to eliminate #ifdef STOPPER_TEST #define STOPPER(s) Stopper(s, __LINE__) -#else +#elsedxw #define STOPPER(s) #endif @@ -29,6 +32,8 @@ ResizePalette_Type pResizePalette = NULL; BOOL WINAPI extResizePalette(HPALETTE, UINT); #endif +#define _Warn(s) MessageBox(0, s, "to do", MB_ICONEXCLAMATION) + /* typedef COLORREF (WINAPI *SetBkColor_Type)(HDC, COLORREF); typedef COLORREF (WINAPI *SetTextColor_Type)(HDC hdc, COLORREF crColor); @@ -45,6 +50,81 @@ int WINAPI extSetBkMode(HDC, int); typedef int (WINAPI *SetDIBits_Type)(HDC, HBITMAP, UINT, UINT, const VOID *, const BITMAPINFO *, UINT); int WINAPI extSetDIBits(HDC, HBITMAP, UINT, UINT, const VOID *, const BITMAPINFO *, UINT); SetDIBits_Type pSetDIBits = NULL; +typedef int (WINAPI *OffsetRgn_Type)(HRGN, int, int); +OffsetRgn_Type pOffsetRgn = NULL; +int WINAPI extOffsetRgn(HRGN, int, int); +typedef COLORREF (WINAPI *GetPixel_Type)(HDC, int, int); +GetPixel_Type pGetPixel = NULL; +COLORREF WINAPI extGetPixel(HDC, int, int); +typedef BOOL (WINAPI *PlgBlt_Type)(HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int); +PlgBlt_Type pPlgBlt = NULL; +BOOL WINAPI extPlgBlt(HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int); +typedef BOOL (WINAPI *SetPixelV_Type)(HDC, int, int, COLORREF); +SetPixelV_Type pSetPixelV = NULL; +BOOL WINAPI extSetPixelV(HDC, int, int, COLORREF); +typedef BOOL (WINAPI *Chord_Type)(HDC, int, int, int, int, int, int, int, int); +Chord_Type pChord = NULL; +BOOL WINAPI extChord(HDC, int, int, int, int, int, int, int, int); +typedef BOOL (WINAPI *PolyTextOutA_Type)(HDC, const POLYTEXTA *, int); +PolyTextOutA_Type pPolyTextOutA = NULL; +BOOL WINAPI extPolyTextOutA(HDC, const POLYTEXTA *, int); +typedef BOOL (WINAPI *PolyTextOutW_Type)(HDC, const POLYTEXTW *, int); +PolyTextOutW_Type pPolyTextOutW = NULL; +BOOL WINAPI extPolyTextOutW(HDC, const POLYTEXTW *, int); +typedef int (WINAPI *GetDIBits_Type)(HDC, HBITMAP, UINT, UINT, LPVOID, LPBITMAPINFO, UINT); +GetDIBits_Type pGetDIBits = NULL; +int WINAPI extGetDIBits(HDC, HBITMAP, UINT, UINT, LPVOID, LPBITMAPINFO, UINT); +typedef HBITMAP (WINAPI *CreateDIBitmap_Type)(HDC, BITMAPINFOHEADER *, DWORD, const VOID *, const BITMAPINFO *, UINT); +CreateDIBitmap_Type pCreateDIBitmap = NULL; +HBITMAP WINAPI extCreateDIBitmap(HDC, BITMAPINFOHEADER *, DWORD, const VOID *, const BITMAPINFO *, UINT); +typedef HBITMAP (WINAPI *CreateDIBSection_Type)(HDC, const BITMAPINFO *, UINT, VOID **, HANDLE, DWORD); +CreateDIBSection_Type pCreateDIBSection = NULL; +HBITMAP WINAPI extCreateDIBSection(HDC, const BITMAPINFO *, UINT, VOID **, HANDLE, DWORD); +typedef HBITMAP (WINAPI *CreateDiscardableBitmap_Type)(HDC, int, int); +CreateDiscardableBitmap_Type pCreateDiscardableBitmap = NULL; +HBITMAP WINAPI extCreateDiscardableBitmap(HDC, int, int); +typedef BOOL (WINAPI *ExtFloodFill_Type)(HDC, int, int, COLORREF, UINT); +ExtFloodFill_Type pExtFloodFill = NULL; +BOOL WINAPI extExtFloodFill(HDC, int, int, COLORREF, UINT); +typedef BOOL (WINAPI *GdiAlphaBlend_Type)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION); +GdiAlphaBlend_Type pGdiAlphaBlend = NULL; +BOOL WINAPI extGdiAlphaBlend(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION); +typedef BOOL (WINAPI *GdiGradientFill_Type)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG); +GdiGradientFill_Type pGdiGradientFill = NULL; +BOOL WINAPI extGdiGradientFill(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG); +typedef BOOL (WINAPI *GdiTransparentBlt_Type)(HDC, int, int, int, int, HDC, int, int, int, int, UINT); +GdiTransparentBlt_Type pGdiTransparentBlt = NULL; +BOOL WINAPI extGdiTransparentBlt(HDC, int, int, int, int, HDC, int, int, int, int, UINT); +typedef BOOL (WINAPI *Pie_Type)(HDC, int, int, int, int, int, int, int, int); +Pie_Type pPie = NULL; +BOOL WINAPI extPie(HDC, int, int, int, int, int, int, int, int); +typedef BOOL (WINAPI *AngleArc_Type)(HDC, int, int, DWORD, FLOAT, FLOAT); +AngleArc_Type pAngleArc = NULL; +BOOL WINAPI extAngleArc(HDC, int, int, DWORD, FLOAT, FLOAT); +typedef BOOL (WINAPI *PolyPolyline_Type)(HDC, const POINT *, const DWORD *, DWORD); +PolyPolyline_Type pPolyPolyline = NULL; +BOOL WINAPI extPolyPolyline(HDC, const POINT *, const DWORD *, DWORD); +typedef BOOL (WINAPI *FillRgn_Type)(HDC, HRGN, HBRUSH); +FillRgn_Type pFillRgn = NULL; +BOOL WINAPI extFillRgn(HDC, HRGN, HBRUSH); +typedef BOOL (WINAPI *FrameRgn_Type)(HDC, HRGN, HBRUSH, int, int); +FrameRgn_Type pFrameRgn = NULL; +BOOL WINAPI extFrameRgn(HDC, HRGN, HBRUSH, int, int); +typedef BOOL (WINAPI *InvertRgn_Type)(HDC, HRGN); +InvertRgn_Type pInvertRgn = NULL; +BOOL WINAPI extInvertRgn(HDC, HRGN); +typedef BOOL (WINAPI *PaintRgn_Type)(HDC, HRGN); +PaintRgn_Type pPaintRgn = NULL; +BOOL WINAPI extPaintRgn(HDC, HRGN); +typedef int (WINAPI *SetMapMode_Type)(HDC, int); +SetMapMode_Type pSetMapMode = NULL; +int WINAPI extSetMapMode(HDC, int); +typedef BOOL (WINAPI *RoundRect_Type)(HDC, int, int, int, int, int, int); +RoundRect_Type pRoundRect = NULL; +BOOL WINAPI extRoundRect(HDC, int, int, int, int, int, int); +typedef BOOL (WINAPI *PolyPolygon_Type)(HDC, const POINT *, const INT *, int); +PolyPolygon_Type pPolyPolygon = NULL; +BOOL WINAPI extPolyPolygon(HDC, const POINT *, const INT *, int); static HookEntry_Type Hooks[]={ @@ -58,87 +138,109 @@ static HookEntry_Type Hooks[]={ {HOOK_HOT_CANDIDATE, "RealizePalette", (FARPROC)RealizePalette, (FARPROC *)&pGDIRealizePalette, (FARPROC)extRealizePalette}, {HOOK_HOT_CANDIDATE, "GetSystemPaletteEntries", (FARPROC)GetSystemPaletteEntries, (FARPROC *)&pGDIGetSystemPaletteEntries, (FARPROC)extGetSystemPaletteEntries}, {HOOK_HOT_CANDIDATE, "SetSystemPaletteUse", (FARPROC)SetSystemPaletteUse, (FARPROC *)&pSetSystemPaletteUse, (FARPROC)extSetSystemPaletteUse}, - {HOOK_IAT_CANDIDATE, "StretchDIBits", (FARPROC)StretchDIBits, (FARPROC *)&pStretchDIBits, (FARPROC)extStretchDIBits}, - //{HOOK_IAT_CANDIDATE, "CreateCompatibleBitmap", (FARPROC)NULL, (FARPROC *)&pCreateCompatibleBitmap, (FARPROC)extCreateCompatibleBitmap}, - //{HOOK_IAT_CANDIDATE, "SetMapMode", (FARPROC)NULL, (FARPROC *)NULL, (FARPROC)extSetMapMode}, {HOOK_IAT_CANDIDATE, "SetPixelFormat", (FARPROC)NULL, (FARPROC *)&pGDISetPixelFormat, (FARPROC)extGDISetPixelFormat}, {HOOK_IAT_CANDIDATE, "GetPixelFormat", (FARPROC)NULL, (FARPROC *)&pGDIGetPixelFormat, (FARPROC)extGDIGetPixelFormat}, {HOOK_IAT_CANDIDATE, "ChoosePixelFormat", (FARPROC)NULL, (FARPROC *)&pChoosePixelFormat, (FARPROC)extChoosePixelFormat}, {HOOK_IAT_CANDIDATE, "DescribePixelFormat", (FARPROC)NULL, (FARPROC *)&pDescribePixelFormat, (FARPROC)extDescribePixelFormat}, {HOOK_HOT_CANDIDATE, "GetPaletteEntries", (FARPROC)GetPaletteEntries, (FARPROC *)&pGetPaletteEntries, (FARPROC)extGetPaletteEntries}, {HOOK_HOT_CANDIDATE, "GetSystemPaletteUse", (FARPROC)GetSystemPaletteUse, (FARPROC *)&pGetSystemPaletteUse, (FARPROC)extGetSystemPaletteUse}, + {HOOK_HOT_CANDIDATE, "CreateICA", (FARPROC)CreateICA, (FARPROC *)&pCreateICA, (FARPROC)extCreateICA}, // Riven #ifdef TRACEPALETTE {HOOK_IAT_CANDIDATE, "ResizePalette", (FARPROC)ResizePalette, (FARPROC *)&pResizePalette, (FARPROC)extResizePalette}, -#endif - {HOOK_HOT_CANDIDATE, "CreateICA", (FARPROC)CreateICA, (FARPROC *)&pCreateICA, (FARPROC)extCreateICA}, // Riven +#endif {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; - + static HookEntry_Type RemapHooks[]={ {HOOK_IAT_CANDIDATE, "SetViewportOrgEx", (FARPROC)SetViewportOrgEx, (FARPROC *)&pSetViewportOrgEx, (FARPROC)extSetViewportOrgEx}, // needed in ShowBanner - {HOOK_IAT_CANDIDATE, "SetViewportExtEx", (FARPROC)NULL, (FARPROC *)&pSetViewportExtEx, (FARPROC)extSetViewportExtEx}, - {HOOK_IAT_CANDIDATE, "GetViewportOrgEx", (FARPROC)NULL, (FARPROC *)&pGetViewportOrgEx, (FARPROC)extGetViewportOrgEx}, - {HOOK_IAT_CANDIDATE, "GetViewportExtEx", (FARPROC)NULL, (FARPROC *)&pGetViewportExtEx, (FARPROC)extGetViewportExtEx}, - {HOOK_IAT_CANDIDATE, "GetWindowOrgEx", (FARPROC)NULL, (FARPROC *)&pGetWindowOrgEx, (FARPROC)extGetWindowOrgEx}, - {HOOK_IAT_CANDIDATE, "SetWindowOrgEx", (FARPROC)NULL, (FARPROC *)&pSetWindowOrgEx, (FARPROC)extSetWindowOrgEx}, - {HOOK_IAT_CANDIDATE, "GetCurrentPositionEx", (FARPROC)NULL, (FARPROC *)&pGetCurrentPositionEx, (FARPROC)extGetCurrentPositionEx}, - {HOOK_IAT_CANDIDATE, "SetDIBitsToDevice", (FARPROC)NULL, (FARPROC *)&pSetDIBitsToDevice, (FARPROC)extSetDIBitsToDevice}, // does the stretching - {HOOK_IAT_CANDIDATE, "GetRgnBox", (FARPROC)NULL, (FARPROC *)&pGetRgnBox, (FARPROC)extGetRgnBox}, + {HOOK_IAT_CANDIDATE, "SetViewportExtEx", (FARPROC)SetViewportExtEx, (FARPROC *)&pSetViewportExtEx, (FARPROC)extSetViewportExtEx}, + {HOOK_IAT_CANDIDATE, "GetViewportOrgEx", (FARPROC)GetViewportOrgEx, (FARPROC *)&pGetViewportOrgEx, (FARPROC)extGetViewportOrgEx}, + {HOOK_IAT_CANDIDATE, "GetViewportExtEx", (FARPROC)GetViewportExtEx, (FARPROC *)&pGetViewportExtEx, (FARPROC)extGetViewportExtEx}, + {HOOK_IAT_CANDIDATE, "GetWindowOrgEx", (FARPROC)GetWindowOrgEx, (FARPROC *)&pGetWindowOrgEx, (FARPROC)extGetWindowOrgEx}, + {HOOK_IAT_CANDIDATE, "SetWindowOrgEx", (FARPROC)SetWindowOrgEx, (FARPROC *)&pSetWindowOrgEx, (FARPROC)extSetWindowOrgEx}, + {HOOK_IAT_CANDIDATE, "GetCurrentPositionEx", (FARPROC)GetCurrentPositionEx, (FARPROC *)&pGetCurrentPositionEx, (FARPROC)extGetCurrentPositionEx}, + {HOOK_IAT_CANDIDATE, "GetRgnBox", (FARPROC)GetRgnBox, (FARPROC *)&pGetRgnBox, (FARPROC)extGetRgnBox}, //{HOOK_IAT_CANDIDATE, "GetRegionData", (FARPROC)NULL, (FARPROC *)&pGetRegionData, (FARPROC)extGetRegionData}, - //{HOOK_HOT_CANDIDATE, "SetDIBits", (FARPROC)SetDIBits, (FARPROC *)&pSetDIBits, (FARPROC)extSetDIBits}, + {HOOK_IAT_CANDIDATE, "CreateCompatibleDC", (FARPROC)CreateCompatibleDC, (FARPROC *)&pGDICreateCompatibleDC, (FARPROC)extGDICreateCompatibleDC}, /* to check */ + //TODO {HOOK_IAT_CANDIDATE, "DrawEscape", (FARPROC)DrawEscape, (FARPROC *)&pDrawEscape, (FARPROC)extDrawEscape}, /* to check */ {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; -static HookEntry_Type ScaledHooks[]={ - {HOOK_IAT_CANDIDATE, "Rectangle", (FARPROC)Rectangle, (FARPROC *)&pGDIRectangle, (FARPROC)extRectangle}, - {HOOK_IAT_CANDIDATE, "TextOutA", (FARPROC)TextOutA, (FARPROC *)&pGDITextOutA, (FARPROC)extTextOutA}, - {HOOK_IAT_CANDIDATE, "GetClipBox", (FARPROC)NULL, (FARPROC *)&pGDIGetClipBox, (FARPROC)extGetClipBox}, - {HOOK_IAT_CANDIDATE, "IntersectClipRect", (FARPROC)IntersectClipRect, (FARPROC *)&pIntersectClipRect, (FARPROC)extIntersectClipRect}, // Riven !! - //{HOOK_IAT_CANDIDATE, "GetRgnBox", (FARPROC)NULL, (FARPROC *)&pGetRgnBox, (FARPROC)extGetRgnBox}, - {HOOK_IAT_CANDIDATE, "Polyline", (FARPROC)NULL, (FARPROC *)&pPolyline, (FARPROC)extPolyline}, - {HOOK_IAT_CANDIDATE, "PolyBezierTo", (FARPROC)NULL, (FARPROC *)&pPolyBezierTo, (FARPROC)extPolyBezierTo}, - {HOOK_IAT_CANDIDATE, "PolylineTo", (FARPROC)NULL, (FARPROC *)&pPolylineTo, (FARPROC)extPolylineTo}, - {HOOK_IAT_CANDIDATE, "PolyDraw", (FARPROC)NULL, (FARPROC *)&pPolyDraw, (FARPROC)extPolyDraw}, - {HOOK_IAT_CANDIDATE, "MoveToEx", (FARPROC)NULL, (FARPROC *)&pMoveToEx, (FARPROC)extMoveToEx}, - {HOOK_IAT_CANDIDATE, "ArcTo", (FARPROC)NULL, (FARPROC *)&pArcTo, (FARPROC)extArcTo}, - {HOOK_IAT_CANDIDATE, "LineTo", (FARPROC)NULL, (FARPROC *)&pLineTo, (FARPROC)extLineTo}, - {HOOK_IAT_CANDIDATE, "SetPixel", (FARPROC)NULL, (FARPROC *)&pSetPixel, (FARPROC)extSetPixel}, - {HOOK_IAT_CANDIDATE, "Ellipse", (FARPROC)NULL, (FARPROC *)&pEllipse, (FARPROC)extEllipse}, - {HOOK_IAT_CANDIDATE, "Polygon", (FARPROC)NULL, (FARPROC *)&pPolygon, (FARPROC)extPolygon}, - {HOOK_IAT_CANDIDATE, "Arc", (FARPROC)NULL, (FARPROC *)&pArc, (FARPROC)extArc}, - // commented out since they alter text on screen...... (see Imperialism II difficulty level menu) - // v2.03.47 - restored: needed for "688(I) Hunter Killer" periscope .... - {HOOK_IAT_CANDIDATE, "CreateEllipticRgn", (FARPROC)NULL, (FARPROC *)&pCreateEllipticRgn, (FARPROC)extCreateEllipticRgn}, - {HOOK_IAT_CANDIDATE, "CreateEllipticRgnIndirect", (FARPROC)NULL, (FARPROC *)&pCreateEllipticRgnIndirect, (FARPROC)extCreateEllipticRgnIndirect}, - // CreateRectRgn must be hooked in scaled mode to let Avernum work correctly! - {HOOK_IAT_CANDIDATE, "CreateRectRgn", (FARPROC)NULL, (FARPROC *)&pCreateRectRgn, (FARPROC)extCreateRectRgn}, - {HOOK_IAT_CANDIDATE, "CreateRectRgnIndirect", (FARPROC)NULL, (FARPROC *)&pCreateRectRgnIndirect, (FARPROC)extCreateRectRgnIndirect}, - //{HOOK_IAT_CANDIDATE, "CreatePolygonRgn", (FARPROC)NULL, (FARPROC *)&pCreatePolygonRgn, (FARPROC)extCreatePolygonRgn}, - // same as emulated GDI ... - {HOOK_IAT_CANDIDATE, "CreateCompatibleDC", (FARPROC)CreateCompatibleDC, (FARPROC *)&pGDICreateCompatibleDC, (FARPROC)extGDICreateCompatibleDC}, - {HOOK_IAT_CANDIDATE, "DeleteDC", (FARPROC)DeleteDC, (FARPROC *)&pGDIDeleteDC, (FARPROC)extGDIDeleteDC}, - {HOOK_IAT_CANDIDATE, "CreateDCA", (FARPROC)CreateDCA, (FARPROC *)&pGDICreateDC, (FARPROC)extGDICreateDC}, - // CreateDCW ..... +static HookEntry_Type SyscallHooks[]={ + {HOOK_IAT_CANDIDATE, "StretchDIBits", (FARPROC)StretchDIBits, (FARPROC *)&pStretchDIBits, (FARPROC)extStretchDIBits}, + {HOOK_HOT_CANDIDATE, "SetDIBits", (FARPROC)SetDIBits, (FARPROC *)&pSetDIBits, (FARPROC)extSetDIBits}, + {HOOK_HOT_CANDIDATE, "GetDIBits", (FARPROC)GetDIBits, (FARPROC *)&pGetDIBits, (FARPROC)extGetDIBits}, + {HOOK_IAT_CANDIDATE, "CreateCompatibleBitmap", (FARPROC)CreateCompatibleBitmap, (FARPROC *)&pCreateCompatibleBitmap, (FARPROC)extCreateCompatibleBitmap}, + {HOOK_IAT_CANDIDATE, "CreateDIBitmap", (FARPROC)NULL, (FARPROC *)&pCreateDIBitmap, (FARPROC)extCreateDIBitmap}, + {HOOK_IAT_CANDIDATE, "CreateDIBSection", (FARPROC)NULL, (FARPROC *)&pCreateDIBSection, (FARPROC)extCreateDIBSection}, + {HOOK_IAT_CANDIDATE, "CreateDiscardableBitmap", (FARPROC)NULL, (FARPROC *)&pCreateDiscardableBitmap, (FARPROC)extCreateDiscardableBitmap}, + {HOOK_IAT_CANDIDATE, "ExtFloodFill", (FARPROC)NULL, (FARPROC *)&pExtFloodFill, (FARPROC)extExtFloodFill}, + {HOOK_IAT_CANDIDATE, "GdiAlphaBlend", (FARPROC)NULL, (FARPROC *)&pGdiAlphaBlend, (FARPROC)extGdiAlphaBlend}, + {HOOK_IAT_CANDIDATE, "GdiGradientFill", (FARPROC)NULL, (FARPROC *)&pGdiGradientFill, (FARPROC)extGdiGradientFill}, + {HOOK_IAT_CANDIDATE, "GdiTransparentBlt", (FARPROC)NULL, (FARPROC *)&pGdiTransparentBlt, (FARPROC)extGdiTransparentBlt}, + {HOOK_IAT_CANDIDATE, "Pie", (FARPROC)NULL, (FARPROC *)&pPie, (FARPROC)extPie}, + {HOOK_IAT_CANDIDATE, "AngleArc", (FARPROC)NULL, (FARPROC *)&pAngleArc, (FARPROC)extAngleArc}, + {HOOK_IAT_CANDIDATE, "PolyPolyline", (FARPROC)NULL, (FARPROC *)&pPolyPolyline, (FARPROC)extPolyPolyline}, + {HOOK_IAT_CANDIDATE, "FillRgn", (FARPROC)NULL, (FARPROC *)&pFillRgn, (FARPROC)extFillRgn}, + {HOOK_IAT_CANDIDATE, "FrameRgn", (FARPROC)NULL, (FARPROC *)&pFrameRgn, (FARPROC)extFrameRgn}, + {HOOK_IAT_CANDIDATE, "InvertRgn", (FARPROC)NULL, (FARPROC *)&pInvertRgn, (FARPROC)extInvertRgn}, + {HOOK_IAT_CANDIDATE, "PaintRgn", (FARPROC)NULL, (FARPROC *)&pPaintRgn, (FARPROC)extPaintRgn}, + //{HOOK_IAT_CANDIDATE, "SetMapMode", (FARPROC)NULL, (FARPROC *)NULL, (FARPROC)extSetMapMode}, // crashes ??? + {HOOK_IAT_CANDIDATE, "SetDIBitsToDevice", (FARPROC)SetDIBitsToDevice, (FARPROC *)&pSetDIBitsToDevice, (FARPROC)extSetDIBitsToDevice}, // does the stretching + {HOOK_IAT_CANDIDATE, "Polyline", (FARPROC)Polyline, (FARPROC *)&pPolyline, (FARPROC)extPolyline}, {HOOK_IAT_CANDIDATE, "BitBlt", (FARPROC)BitBlt, (FARPROC *)&pGDIBitBlt, (FARPROC)extGDIBitBlt}, {HOOK_IAT_CANDIDATE, "StretchBlt", (FARPROC)StretchBlt, (FARPROC *)&pGDIStretchBlt, (FARPROC)extGDIStretchBlt}, {HOOK_IAT_CANDIDATE, "PatBlt", (FARPROC)PatBlt, (FARPROC *)&pGDIPatBlt, (FARPROC)extGDIPatBlt}, - {HOOK_IAT_CANDIDATE, "MaskBlt", (FARPROC)NULL, (FARPROC *)&pMaskBlt, (FARPROC)extMaskBlt}, + {HOOK_IAT_CANDIDATE, "MaskBlt", (FARPROC)MaskBlt, (FARPROC *)&pMaskBlt, (FARPROC)extMaskBlt}, + {HOOK_IAT_CANDIDATE, "TextOutA", (FARPROC)TextOutA, (FARPROC *)&pGDITextOutA, (FARPROC)extTextOutA}, + {HOOK_IAT_CANDIDATE, "TextOutW", (FARPROC)TextOutW, (FARPROC *)&pGDITextOutW, (FARPROC)extTextOutW}, + {HOOK_IAT_CANDIDATE, "Rectangle", (FARPROC)Rectangle, (FARPROC *)&pGDIRectangle, (FARPROC)extRectangle}, + {HOOK_IAT_CANDIDATE, "RoundRect", (FARPROC)RoundRect, (FARPROC *)&pRoundRect, (FARPROC)extRoundRect}, + {HOOK_IAT_CANDIDATE, "Polygon", (FARPROC)Polygon, (FARPROC *)&pPolygon, (FARPROC)extPolygon}, + {HOOK_IAT_CANDIDATE, "PolyPolygon", (FARPROC)PolyPolygon, (FARPROC *)&pPolyPolygon, (FARPROC)extPolyPolygon}, + {HOOK_IAT_CANDIDATE, "PolyBezier", (FARPROC)PolyBezier, (FARPROC *)&pPolyBezier, (FARPROC)extPolyBezier}, + {HOOK_IAT_CANDIDATE, "PolyBezierTo", (FARPROC)PolyBezierTo, (FARPROC *)&pPolyBezierTo, (FARPROC)extPolyBezierTo}, + {HOOK_IAT_CANDIDATE, "PolylineTo", (FARPROC)PolylineTo, (FARPROC *)&pPolylineTo, (FARPROC)extPolylineTo}, + {HOOK_IAT_CANDIDATE, "PolyDraw", (FARPROC)PolyDraw, (FARPROC *)&pPolyDraw, (FARPROC)extPolyDraw}, + {HOOK_IAT_CANDIDATE, "GetPixel", (FARPROC)GetPixel, (FARPROC *)&pGetPixel, (FARPROC)extGetPixel}, + {HOOK_IAT_CANDIDATE, "PlgBlt", (FARPROC)PlgBlt, (FARPROC *)&pPlgBlt, (FARPROC)extPlgBlt}, + {HOOK_IAT_CANDIDATE, "SetPixel", (FARPROC)SetPixel, (FARPROC *)&pSetPixel, (FARPROC)extSetPixel}, + {HOOK_IAT_CANDIDATE, "SetPixelV", (FARPROC)SetPixelV, (FARPROC *)&pSetPixelV, (FARPROC)extSetPixelV}, + {HOOK_IAT_CANDIDATE, "Chord", (FARPROC)Chord, (FARPROC *)&pChord, (FARPROC)extChord}, + {HOOK_IAT_CANDIDATE, "Ellipse", (FARPROC)Ellipse, (FARPROC *)&pEllipse, (FARPROC)extEllipse}, {HOOK_IAT_CANDIDATE, "ExtTextOutA", (FARPROC)ExtTextOutA, (FARPROC *)&pExtTextOutA, (FARPROC)extExtTextOutA}, {HOOK_IAT_CANDIDATE, "ExtTextOutW", (FARPROC)ExtTextOutW, (FARPROC *)&pExtTextOutW, (FARPROC)extExtTextOutW}, + {HOOK_IAT_CANDIDATE, "PolyTextOutA", (FARPROC)PolyTextOutA, (FARPROC *)&pPolyTextOutA, (FARPROC)extPolyTextOutA}, + {HOOK_IAT_CANDIDATE, "PolyTextOutW", (FARPROC)PolyTextOutA, (FARPROC *)&pPolyTextOutA, (FARPROC)extPolyTextOutA}, + {HOOK_IAT_CANDIDATE, "ArcTo", (FARPROC)ArcTo, (FARPROC *)&pArcTo, (FARPROC)extArcTo}, + {HOOK_IAT_CANDIDATE, "LineTo", (FARPROC)LineTo, (FARPROC *)&pLineTo, (FARPROC)extLineTo}, + {HOOK_IAT_CANDIDATE, "Arc", (FARPROC)Arc, (FARPROC *)&pArc, (FARPROC)extArc}, + {HOOK_IAT_CANDIDATE, "MoveToEx", (FARPROC)MoveToEx, (FARPROC *)&pMoveToEx, (FARPROC)extMoveToEx}, + {HOOK_IAT_CANDIDATE, "GetClipBox", (FARPROC)GetClipBox, (FARPROC *)&pGDIGetClipBox, (FARPROC)extGetClipBox}, + {HOOK_IAT_CANDIDATE, "IntersectClipRect", (FARPROC)IntersectClipRect, (FARPROC *)&pIntersectClipRect, (FARPROC)extIntersectClipRect}, // Riven !! + {HOOK_IAT_CANDIDATE, "DeleteDC", (FARPROC)DeleteDC, (FARPROC *)&pGDIDeleteDC, (FARPROC)extGDIDeleteDC}, // for tracing only! + {HOOK_IAT_CANDIDATE, "CreateDCA", (FARPROC)CreateDCA, (FARPROC *)&pGDICreateDCA, (FARPROC)extGDICreateDCA}, + {HOOK_IAT_CANDIDATE, "CreateDCW", (FARPROC)CreateDCW, (FARPROC *)&pGDICreateDCW, (FARPROC)extGDICreateDCW}, + // CreateDCW ..... {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type ScaledHooks[]={ + // commented out since they alter text on screen...... (see Imperialism II difficulty level menu) + // v2.03.47 - restored: needed for "688(I) Hunter Killer" periscope .... + {HOOK_IAT_CANDIDATE, "CreateEllipticRgn", (FARPROC)CreateEllipticRgn, (FARPROC *)&pCreateEllipticRgn, (FARPROC)extCreateEllipticRgn}, + {HOOK_IAT_CANDIDATE, "CreateEllipticRgnIndirect", (FARPROC)CreateEllipticRgnIndirect, (FARPROC *)&pCreateEllipticRgnIndirect, (FARPROC)extCreateEllipticRgnIndirect}, + // CreateRectRgn must be hooked in scaled mode to let Avernum work correctly! + {HOOK_IAT_CANDIDATE, "CreateRectRgn", (FARPROC)CreateRectRgn, (FARPROC *)&pCreateRectRgn, (FARPROC)extCreateRectRgn}, + {HOOK_IAT_CANDIDATE, "CreateRectRgnIndirect", (FARPROC)CreateRectRgnIndirect, (FARPROC *)&pCreateRectRgnIndirect, (FARPROC)extCreateRectRgnIndirect}, + {HOOK_IAT_CANDIDATE, "CreatePolygonRgn", (FARPROC)CreatePolygonRgn, (FARPROC *)&pCreatePolygonRgn, (FARPROC)extCreatePolygonRgn}, + // same as emulated GDI ... + {HOOK_IAT_CANDIDATE, "SetRectRgn", (FARPROC)SetRectRgn, (FARPROC *)&pSetRectRgn, (FARPROC)extSetRectRgn}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; static HookEntry_Type EmulateHooks[]={ - // useless CreateCompatibleDC: it maps VirtualHDC on top of VirtualHDC, then does nothing, unless when asked to operate on 0!.... - //{HOOK_IAT_CANDIDATE, "CreateCompatibleDC", (FARPROC)CreateCompatibleDC, (FARPROC *)&pGDICreateCompatibleDC, (FARPROC)extEMUCreateCompatibleDC}, - // useless DeleteDC: it's just a proxy - //{HOOK_IAT_CANDIDATE, "DeleteDC", (FARPROC)DeleteDC, (FARPROC *)&pGDIDeleteDC, (FARPROC)extGDIDeleteDC}, - {HOOK_IAT_CANDIDATE, "CreateDCA", (FARPROC)CreateDCA, (FARPROC *)&pGDICreateDC, (FARPROC)extGDICreateDC}, - // CreateDCW ..... - {HOOK_IAT_CANDIDATE, "GetObjectType", (FARPROC)GetObjectType, (FARPROC *)&pGetObjectType, (FARPROC)extGetObjectType}, - {HOOK_IAT_CANDIDATE, "GetClipBox", (FARPROC)NULL, (FARPROC *)&pGDIGetClipBox, (FARPROC)extGetClipBox}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; @@ -155,10 +257,10 @@ static HookEntry_Type GammaHooks[]={ }; static HookEntry_Type FontHooks[]={ - {HOOK_IAT_CANDIDATE, "CreateScalableFontResourceA", (FARPROC)NULL, (FARPROC *)&pCreateScalableFontResourceA, (FARPROC)extCreateScalableFontResourceA}, - {HOOK_IAT_CANDIDATE, "CreateScalableFontResourceW", (FARPROC)NULL, (FARPROC *)&pCreateScalableFontResourceW, (FARPROC)extCreateScalableFontResourceW}, - {HOOK_IAT_CANDIDATE, "AddFontResourceA", (FARPROC)NULL, (FARPROC *)&pAddFontResourceA, (FARPROC)extAddFontResourceA}, - {HOOK_IAT_CANDIDATE, "AddFontResourceW", (FARPROC)NULL, (FARPROC *)&pAddFontResourceW, (FARPROC)extAddFontResourceW}, + {HOOK_IAT_CANDIDATE, "CreateScalableFontResourceA", (FARPROC)CreateScalableFontResourceA, (FARPROC *)&pCreateScalableFontResourceA, (FARPROC)extCreateScalableFontResourceA}, + {HOOK_IAT_CANDIDATE, "CreateScalableFontResourceW", (FARPROC)CreateScalableFontResourceW, (FARPROC *)&pCreateScalableFontResourceW, (FARPROC)extCreateScalableFontResourceW}, + {HOOK_IAT_CANDIDATE, "AddFontResourceA", (FARPROC)AddFontResourceA, (FARPROC *)&pAddFontResourceA, (FARPROC)extAddFontResourceA}, + {HOOK_IAT_CANDIDATE, "AddFontResourceW", (FARPROC)AddFontResourceW, (FARPROC *)&pAddFontResourceW, (FARPROC)extAddFontResourceW}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; @@ -181,6 +283,7 @@ void HookGDI32Init() HookLibInit(Hooks); HookLibInit(RemapHooks); HookLibInit(ScaledHooks); + HookLibInit(SyscallHooks); HookLibInit(EmulateHooks); HookLibInit(TextHooks); HookLibInit(GammaHooks); @@ -191,6 +294,7 @@ void HookGDI32(HMODULE module) { HookLibrary(module, Hooks, libname); + if (dxw.GDIEmulationMode != GDIMODE_NONE) HookLibrary(module, SyscallHooks, libname); if (dxw.dwFlags1 & CLIENTREMAPPING) HookLibrary(module, RemapHooks, libname); if (dxw.dwFlags2 & GDISTRETCHED) HookLibrary(module, ScaledHooks, libname); if (dxw.dwFlags3 & GDIEMULATEDC) HookLibrary(module, EmulateHooks, libname); @@ -207,6 +311,7 @@ FARPROC Remap_GDI32_ProcAddress(LPCSTR proc, HMODULE hModule) if(addr=RemapLibrary(proc, hModule, Hooks)) return addr; + if (dxw.GDIEmulationMode != GDIMODE_NONE) if(addr=RemapLibrary(proc, hModule, SyscallHooks)) return addr; if (dxw.dwFlags1 & CLIENTREMAPPING) if(addr=RemapLibrary(proc, hModule, RemapHooks)) return addr; if (dxw.dwFlags2 & GDISTRETCHED) if (addr=RemapLibrary(proc, hModule, ScaledHooks)) return addr; if (dxw.dwFlags3 & GDIEMULATEDC) if (addr=RemapLibrary(proc, hModule, EmulateHooks)) return addr; @@ -232,84 +337,6 @@ extern HRESULT WINAPI sBlt(char *, LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURF extern GetDC_Type pGetDC; extern ReleaseDC_Type pReleaseDC; -#if 0 -static COLORREF GetMatchingColor(COLORREF crColor) -{ - int iDistance, iMinDistance; - int iColorIndex, iMinColorIndex; - COLORREF PalColor; - - iMinDistance=0xFFFFFF; - iMinColorIndex=0; - - for(iColorIndex=0; iColorIndex<256; iColorIndex++){ - int iDist; - iDistance=0; - - PalColor=PaletteEntries[iColorIndex]; - switch(dxw.ActualPixelFormat.dwRGBBitCount){ - case 32: - PalColor = ((PalColor & 0x00FF0000) >> 16) | (PalColor & 0x0000FF00) | ((PalColor & 0x000000FF) << 16); - break; - case 16: - if(dxw.ActualPixelFormat.dwGBitMask==0x03E0){ - // RGB555 screen settings - PalColor = ((PalColor & 0x7C00) >> 7) | ((PalColor & 0x03E0) << 6) | ((PalColor & 0x001F) << 19); - } - else { - // RGB565 screen settings - PalColor = ((PalColor & 0xF800) >> 8) | ((PalColor & 0x07E0) << 5) | ((PalColor & 0x001F) << 19); - } - break; - } - - iDist = (crColor & 0x00FF0000) - (PalColor & 0x00FF0000); - iDist >>= 16; - if (iDist<0) iDist=-iDist; - iDist *= iDist; - iDistance += iDist; - - iDist = (crColor & 0x0000FF00) - (PalColor & 0x0000FF00); - iDist >>= 8; - if (iDist<0) iDist=-iDist; - iDist *= iDist; - iDistance += iDist; - - iDist = (crColor & 0x000000FF) - (PalColor & 0x000000FF); - // iDist >>= 0; - if (iDist<0) iDist=-iDist; - iDist *= iDist; - iDistance += iDist; - - if (iDistance < iMinDistance) { - iMinDistance = iDistance; - iMinColorIndex = iColorIndex; - } - - if (iMinDistance==0) break; // got the perfect match! - } - OutTraceDW("GetMatchingColor: color=%x matched with palette[%d]=%x dist=%d\n", - crColor, iMinColorIndex, PaletteEntries[iMinColorIndex], iDistance); - PalColor=PaletteEntries[iMinColorIndex]; - switch(dxw.ActualPixelFormat.dwRGBBitCount){ - case 32: - crColor = ((PalColor & 0x00FF0000) >> 16) | (PalColor & 0x0000FF00) | ((PalColor & 0x000000FF) << 16); - break; - case 16: - if(dxw.ActualPixelFormat.dwGBitMask==0x03E0){ - // RGB555 screen settings - crColor = ((PalColor & 0x7C00) >> 7) | ((PalColor & 0x03E0) << 6) | ((PalColor & 0x001F) << 19); - } - else { - // RGB565 screen settings - crColor = ((PalColor & 0xF800) >> 8) | ((PalColor & 0x07E0) << 5) | ((PalColor & 0x001F) << 19); - } - break; - } - return crColor; -} -#endif - //-------------------------------------------------------------------------------------------- // // API hookers @@ -343,16 +370,53 @@ int WINAPI extGetDeviceCaps(HDC hdc, int nindex) switch(nindex){ case VERTRES: if(dxw.Windowize){ - res= dxw.GetScreenHeight(); + if(dxw.IsDesktop(WindowFromDC(hdc))) + res= dxw.GetScreenHeight(); + else { + if(OBJ_DC == (*pGetObjectType)(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + case GDIMODE_EMULATED: + default: + break; + case GDIMODE_STRETCHED: + int dummy = 0; + dxw.UnmapClient(&dummy, (int *)&res); + break; + } + } + } OutTraceDW("GetDeviceCaps: fix(2) VERTRES cap=%d\n", res); } break; case HORZRES: if(dxw.Windowize){ - res= dxw.GetScreenWidth(); + if(dxw.IsDesktop(WindowFromDC(hdc))) + res= dxw.GetScreenWidth(); + else { + if(OBJ_DC == (*pGetObjectType)(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + case GDIMODE_EMULATED: + default: + break; + case GDIMODE_STRETCHED: + int dummy = 0; + dxw.UnmapClient((int *)&res, &dummy); + break; + } + } + } OutTraceDW("GetDeviceCaps: fix(2) HORZRES cap=%d\n", res); } break; + + + + if(dxw.Windowize){ + res= dxw.GetScreenWidth(); + } + break; // WARNING: in no-emu mode, the INIT8BPP and INIT16BPP flags expose capabilities that // are NOT implemented and may cause later troubles! case RASTERCAPS: @@ -408,15 +472,55 @@ BOOL WINAPI extTextOutA(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int { BOOL ret; extern BOOL gFixed; - OutTraceDW("TextOut: hdc=%x xy=(%d,%d) str=(%d)\"%.*s\"\n", hdc, nXStart, nYStart, cchString, cchString, lpString); + OutTraceDW("TextOutA: hdc=%x xy=(%d,%d) str=(%d)\"%.*s\"\n", hdc, nXStart, nYStart, cchString, cchString, lpString); - if (!gFixed && dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&nXStart, &nYStart); - OutTraceDW("TextOut: fixed dest=(%d,%d)\n", nXStart, nYStart); + if (!gFixed && dxw.IsToRemap(hdc)){ + + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pGDITextOutA)(sdc.GetHdc(), nXStart, nYStart, lpString, cchString); + // update whole screen to avoid make calculations about text position & size + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&nXStart, &nYStart); + OutTraceDW("TextOut: fixed dest=(%d,%d)\n", nXStart, nYStart); + break; + } } ret=(*pGDITextOutA)(hdc, nXStart, nYStart, lpString, cchString); - if(!ret) OutTraceE("TextOut: ERROR ret=%x\n", ret); + if(!ret) OutTraceE("TextOutA: ERROR ret=%x\n", ret); + return ret; +} + +BOOL WINAPI extTextOutW(HDC hdc, int nXStart, int nYStart, LPCWSTR lpString, int cchString) +{ + BOOL ret; + extern BOOL gFixed; + OutTraceDW("TextOutW: hdc=%x xy=(%d,%d) str=(%d)\"%.*ls\"\n", hdc, nXStart, nYStart, cchString, cchString, lpString); + + if (!gFixed && dxw.IsToRemap(hdc)){ + + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pGDITextOutW)(sdc.GetHdc(), nXStart, nYStart, lpString, cchString); + // update whole screen to avoid make calculations about text position & size + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&nXStart, &nYStart); + OutTraceDW("TextOutW: fixed dest=(%d,%d)\n", nXStart, nYStart); + break; + } + } + + ret=(*pGDITextOutW)(hdc, nXStart, nYStart, lpString, cchString); + if(!ret) OutTraceE("TextOutW: ERROR ret=%x\n", ret); return ret; } @@ -436,9 +540,19 @@ BOOL WINAPI extRectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, i OutTraceDW("Rectangle: hdc=%x xy=(%d,%d)-(%d,%d)\n", hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&nLeftRect, &nTopRect, &nRightRect, &nBottomRect); - OutTraceDW("Rectangle: fixed dest=(%d,%d)-(%d,%d)\n", nLeftRect, nTopRect, nRightRect, nBottomRect); + if (dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pGDIRectangle)(sdc.GetHdc(), nLeftRect, nTopRect, nRightRect, nBottomRect); + sdc.PutPrimaryDC(hdc, TRUE, nLeftRect, nTopRect, nRightRect-nLeftRect, nBottomRect-nTopRect); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&nLeftRect, &nTopRect, &nRightRect, &nBottomRect); + OutTraceDW("Rectangle: fixed dest=(%d,%d)-(%d,%d)\n", nLeftRect, nTopRect, nRightRect, nBottomRect); + break; + } } ret=(*pGDIRectangle)(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); @@ -449,7 +563,6 @@ BOOL WINAPI extRectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, i int WINAPI extGDISaveDC(HDC hdc) { int ret; - ret=(*pGDISaveDC)(hdc); OutTraceDW("GDI.SaveDC: hdc=%x ret=%x\n", hdc, ret); return ret; @@ -458,7 +571,6 @@ int WINAPI extGDISaveDC(HDC hdc) BOOL WINAPI extGDIRestoreDC(HDC hdc, int nSavedDC) { BOOL ret; - ret=(*pGDIRestoreDC)(hdc, nSavedDC); OutTraceDW("GDI.RestoreDC: hdc=%x nSavedDC=%x ret=%x\n", hdc, nSavedDC, ret); return ret; @@ -593,7 +705,7 @@ HPALETTE WINAPI extSelectPalette(HDC hdc, HPALETTE hpal, BOOL bForceBackground) BOOL WINAPI extAnimatePalette(HPALETTE hpal, UINT iStartIndex, UINT cEntries, const PALETTEENTRY *ppe) { // Invoked by "Pharaoh's Ascent 1.4" - STOPPER("AnimatePalette"); + // STOPPER("AnimatePalette"); return TRUE; } @@ -675,31 +787,59 @@ UINT WINAPI extGetSystemPaletteUse(HDC hdc) return res; } -HDC WINAPI extGDICreateDC(LPSTR lpszDriver, LPSTR lpszDevice, LPSTR lpszOutput, CONST DEVMODE *lpdvmInit) +HDC WINAPI extGDICreateDCA(LPSTR lpszDriver, LPSTR lpszDevice, LPSTR lpszOutput, CONST DEVMODE *lpdvmInit) { HDC WinHDC, RetHDC; - OutTraceDW("GDI.CreateDC: Driver=%s Device=%s Output=%s InitData=%x\n", + OutTraceDW("GDI.CreateDCA: Driver=%s Device=%s Output=%s InitData=%x\n", lpszDriver?lpszDriver:"(NULL)", lpszDevice?lpszDevice:"(NULL)", lpszOutput?lpszOutput:"(NULL)", lpdvmInit); if (!lpszDriver || !strncmp(lpszDriver,"DISPLAY",7)) { - if(dxw.dwFlags3 & GDIEMULATEDC){ + if(dxw.GDIEmulationMode == GDIMODE_EMULATED){ RetHDC=dxw.AcquireEmulatedDC(dxw.GethWnd()); } else { - OutTraceDW("GDI.CreateDC: returning window surface DC\n"); - WinHDC=(*pGDIGetDC)(dxw.GethWnd()); - RetHDC=(*pGDICreateCompatibleDC)(WinHDC); - (*pGDIReleaseDC)(dxw.GethWnd(), WinHDC); + OutTraceDW("GDI.CreateDCA: returning window surface DC\n"); + WinHDC=(*pGDIGetDC)(dxw.GethWnd()); + RetHDC=(*pGDICreateCompatibleDC)(WinHDC); + (*pGDIReleaseDC)(dxw.GethWnd(), WinHDC); } } else{ - RetHDC=(*pGDICreateDC)(lpszDriver, lpszDevice, lpszOutput, lpdvmInit); + RetHDC=(*pGDICreateDCA)(lpszDriver, lpszDevice, lpszOutput, lpdvmInit); } if(RetHDC) - OutTraceDW("GDI.CreateDC: returning HDC=%x\n", RetHDC); + OutTraceDW("GDI.CreateDCA: returning HDC=%x\n", RetHDC); else - OutTraceE("GDI.CreateDC ERROR: err=%d at %d\n", GetLastError(), __LINE__); + OutTraceE("GDI.CreateDCA ERROR: err=%d at %d\n", GetLastError(), __LINE__); + return RetHDC; +} + +HDC WINAPI extGDICreateDCW(LPWSTR lpszDriver, LPWSTR lpszDevice, LPWSTR lpszOutput, CONST DEVMODE *lpdvmInit) +{ + HDC WinHDC, RetHDC; + OutTraceDW("GDI.CreateDCW: Driver=%ls Device=%ls Output=%ls InitData=%x\n", + lpszDriver?lpszDriver:L"(NULL)", lpszDevice?lpszDevice:L"(NULL)", lpszOutput?lpszOutput:L"(NULL)", lpdvmInit); + + if (!lpszDriver || !wcsncmp(lpszDriver,L"DISPLAY",7)) { + if(dxw.GDIEmulationMode == GDIMODE_EMULATED){ + RetHDC=dxw.AcquireEmulatedDC(dxw.GethWnd()); + } + else { + OutTraceDW("GDI.CreateDCW: returning window surface DC\n"); + WinHDC=(*pGDIGetDC)(dxw.GethWnd()); + RetHDC=(*pGDICreateCompatibleDC)(WinHDC); + (*pGDIReleaseDC)(dxw.GethWnd(), WinHDC); + } + + } + else{ + RetHDC=(*pGDICreateDCW)(lpszDriver, lpszDevice, lpszOutput, lpdvmInit); + } + if(RetHDC) + OutTraceDW("GDI.CreateDCW: returning HDC=%x\n", RetHDC); + else + OutTraceE("GDI.CreateDCW ERROR: err=%d at %d\n", GetLastError(), __LINE__); return RetHDC; } @@ -711,7 +851,7 @@ HDC WINAPI extCreateICA(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutp // EverQuest Tutorial.exe calls CreateICA passing "Tutorial" if(!lpszDriver || !_stricmp("DISPLAY", lpszDriver)){ - if(dxw.dwFlags3 & GDIEMULATEDC){ + if(dxw.GDIEmulationMode == GDIMODE_EMULATED){ RetHDC=dxw.AcquireEmulatedDC(dxw.GethWnd()); } else { @@ -758,46 +898,108 @@ HDC WINAPI extGDICreateCompatibleDC(HDC hdc) return RetHdc; } +/*----------------------------------------*/ +HBITMAP VirtualPic; + +static HDC FillVirtualDC(HDC hdc) +{ + HDC VirtualHDC; + HBITMAP VirtualPic; + + if(!(VirtualHDC=CreateCompatibleDC(hdc))) + OutTraceE("CreateCompatibleDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + + if(!(VirtualPic=CreateCompatibleBitmap(hdc, dxw.GetScreenWidth(), dxw.GetScreenHeight()))) + OutTraceE("dxwSDC::GetPrimaryDC: CreateCompatibleBitmap ERROR err=%d at=%d\n", GetLastError(), __LINE__); + + if(!SelectObject(VirtualHDC, VirtualPic)) + OutTraceE("dxwSDC::GetPrimaryDC: SelectObject ERROR err=%d at=%d\n", GetLastError(), __LINE__); + + if(!(*pGDIBitBlt)(VirtualHDC, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), hdc, 0, 0, SRCCOPY)) + OutTraceE("dxwSDC::GetPrimaryDC: StretchBlt ERROR err=%d at=%d\n", GetLastError(), __LINE__); + + return VirtualHDC; +} + +static void FlushVirtualDC(HDC VirtualHDC) +{ + DeleteObject(VirtualHDC); + DeleteObject(VirtualPic); +} + +/*-------------------------------------------*/ + BOOL WINAPI extGDIBitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop) { BOOL res; BOOL IsToScreen; + BOOL IsFromScreen; + BOOL IsDCLeakageSrc = FALSE; + BOOL IsDCLeakageDest = FALSE; + int Flux; - OutTraceDW("GDI.BitBlt: HDC=%x nXDest=%d nYDest=%d nWidth=%d nHeight=%d hdcSrc=%x nXSrc=%d nYSrc=%d dwRop=%x(%s)\n", - hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop, ExplainROP(dwRop)); + OutTraceDW("GDI.BitBlt: HDC=%x(type=%s) nXDest=%d nYDest=%d nWidth=%d nHeight=%d hdcSrc=%x(type=%s) nXSrc=%d nYSrc=%d dwRop=%x(%s)\n", + hdcDest, GetObjectTypeStr(hdcDest), nXDest, nYDest, nWidth, nHeight, + hdcSrc, GetObjectTypeStr(hdcSrc), nXSrc, nYSrc, dwRop, ExplainROP(dwRop)); OutTraceB("GDI.BitBlt: DEBUG FullScreen=%x target hdctype=%x(%s) hwnd=%x\n", - dxw.IsFullScreen(), GetObjectType(hdcDest), ExplainDCType(GetObjectType(hdcDest)), WindowFromDC(hdcDest)); + dxw.IsFullScreen(), (*pGetObjectType)(hdcDest), ExplainDCType((*pGetObjectType)(hdcDest)), WindowFromDC(hdcDest)); // beware: HDC could refer to screen DC that are written directly on screen, or memory DC that will be scaled to // the screen surface later on, on ReleaseDC or ddraw Blit / Flip operation. Scaling of rect coordinates is // needed only in the first case, and must be avoided on the second, otherwise the image would be scaled twice! - if(dxw.dwFlags3 & GDIEMULATEDC){ - if (hdcDest==dxw.RealHDC) hdcDest=dxw.VirtualHDC; - OutTraceB("GDI.BitBlt: DEBUG emulated hdc dest=%x->%x\n", dxw.RealHDC, hdcDest); - } - if(hdcDest == NULL){ // happens in Reah, hdc is NULL despite the fact that BeginPaint returns a valid DC. Too bad, we recover here ... hdcDest = (*pGDIGetDC)(dxw.GethWnd()); - OutTraceB("GDI.BitBlt: DEBUG hdc dest=NULL->%x\n", hdcDest); + OutTraceB("GDI.StretchBlt: DEBUG hdc dest=NULL->%x\n", hdcDest); + IsDCLeakageDest = TRUE; + } + if(hdcSrc == NULL){ + hdcSrc = (*pGDIGetDC)(dxw.GethWnd()); + OutTraceB("GDI.StretchBlt: DEBUG hdc src=NULL->%x\n", hdcSrc); + IsDCLeakageSrc = TRUE; } - IsToScreen=(OBJ_DC == GetObjectType(hdcDest)); + IsToScreen=(OBJ_DC == (*pGetObjectType)(hdcDest)); + IsFromScreen=(OBJ_DC == (*pGetObjectType)(hdcSrc)); + Flux = (IsToScreen ? 1 : 0) + (IsFromScreen ? 2 : 0); if (IsToScreen && (dxw.dwFlags3 & NOGDIBLT)) return TRUE; - if(dxw.IsFullScreen()) { + + if(dxw.IsFullScreen()){ + //int nWSrc, nHSrc, + int nWDest, nHDest; switch(dxw.GDIEmulationMode){ - case GDIMODE_STRETCHED: { - int nWDest, nHDest; - nWDest= nWidth; - nHDest= nHeight; - dxw.MapClient(&nXDest, &nYDest, &nWDest, &nHDest); - res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWDest, nHDest, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, dwRop); - OutTraceB("GDI.BitBlt: DEBUG DC dest=(%d,%d) size=(%d,%d)\n", nXDest, nYDest, nWDest, nHDest); + case GDIMODE_SHAREDDC: + switch(Flux){ + case 0: // memory to memory + res=(*pGDIBitBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); + break; + case 1: // memory to screen + case 3: // screen to screen + sdc.GetPrimaryDC(hdcDest); + res=(*pGDIBitBlt)(sdc.GetHdc(), nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); + sdc.PutPrimaryDC(hdcDest, TRUE, nXDest, nYDest, nWidth, nHeight); + break; + case 2: // screen to memory + sdc.GetPrimaryDC(hdcSrc); + res=(*pGDIBitBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, sdc.GetHdc(), nXSrc, nYSrc, dwRop); + sdc.PutPrimaryDC(hdcSrc, FALSE); + break; } break; + case GDIMODE_STRETCHED: + nWDest= nWidth; + nHDest= nHeight; + if (IsToScreen && !IsFromScreen) dxw.MapClient(&nXDest, &nYDest, &nWDest, &nHDest); + res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWDest, nHDest, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, dwRop); + OutTraceB("GDI.BitBlt: DEBUG DC dest=(%d,%d) size=(%d,%d)\n", nXDest, nYDest, nWDest, nHDest); + break; case GDIMODE_EMULATED: + if (hdcDest==dxw.RealHDC) hdcDest=dxw.VirtualHDC; + res=(*pGDIBitBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); + OutTraceB("GDI.BitBlt: DEBUG emulated hdc dest=%x->%x\n", dxw.RealHDC, hdcDest); + break; default: res=(*pGDIBitBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); break; @@ -807,23 +1009,110 @@ BOOL WINAPI extGDIBitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nH res=(*pGDIBitBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop); } + if(IsDCLeakageSrc) (*pGDIReleaseDC)(dxw.GethWnd(), hdcSrc); + if(IsDCLeakageDest) (*pGDIReleaseDC)(dxw.GethWnd(), hdcDest); if(res && IsToScreen) dxw.ShowOverlay(hdcDest); if(!res) OutTraceE("GDI.BitBlt: ERROR err=%d at %d\n", GetLastError(), __LINE__); return res; } +BOOL WINAPI extGDIStretchBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, + HDC hdcSrc, int nXSrc, int nYSrc, int nWSrc, int nHSrc, DWORD dwRop) +{ + BOOL res; + BOOL IsToScreen; + BOOL IsFromScreen; + BOOL IsDCLeakageSrc = FALSE; + BOOL IsDCLeakageDest = FALSE; + int Flux; + + OutTraceDW("GDI.StretchBlt: HDC=%x nXDest=%d nYDest=%d nWidth=%d nHeight=%d hdcSrc=%x nXSrc=%d nYSrc=%d nWSrc=%d nHSrc=%d dwRop=%x(%s)\n", + hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWSrc, nHSrc, dwRop, ExplainROP(dwRop)); + + OutTraceB("GDI.StretchBlt: DEBUG FullScreen=%x target hdctype=%x(%s) hwnd=%x\n", + dxw.IsFullScreen(), (*pGetObjectType)(hdcDest), ExplainDCType((*pGetObjectType)(hdcDest)), WindowFromDC(hdcDest)); + + if(dxw.GDIEmulationMode == GDIMODE_EMULATED){ + if (hdcDest==dxw.RealHDC) hdcDest=dxw.VirtualHDC; + OutTraceB("GDI.StretchBlt: DEBUG emulated hdc dest=%x->%x\n", dxw.RealHDC, hdcDest); + } + + if(hdcDest == NULL){ + // happens in Reah, hdc is NULL despite the fact that BeginPaint returns a valid DC. Too bad, we recover here ... + hdcDest = (*pGDIGetDC)(dxw.GethWnd()); + OutTraceB("GDI.StretchBlt: DEBUG hdc dest=NULL->%x\n", hdcDest); + IsDCLeakageDest = TRUE; + } + if(hdcSrc == NULL){ + hdcSrc = (*pGDIGetDC)(dxw.GethWnd()); + OutTraceB("GDI.StretchBlt: DEBUG hdc src=NULL->%x\n", hdcSrc); + IsDCLeakageSrc = TRUE; + } + + IsToScreen=(OBJ_DC == (*pGetObjectType)(hdcDest)); + IsFromScreen=(OBJ_DC == (*pGetObjectType)(hdcSrc)); + Flux = (IsToScreen ? 1 : 0) + (IsFromScreen ? 2 : 0); + if (IsToScreen && (dxw.dwFlags3 & NOGDIBLT)) return TRUE; + + if(dxw.IsToRemap(hdcDest) && (hdcDest != hdcSrc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + switch(Flux){ + case 0: // memory to memory + res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWSrc, nHSrc, dwRop); + break; + case 1: // memory to screen + case 3: // screen to screen + sdc.GetPrimaryDC(hdcDest); + res=(*pGDIStretchBlt)(sdc.GetHdc(), nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWSrc, nHSrc, dwRop); + sdc.PutPrimaryDC(hdcDest, TRUE, nXDest, nYDest, nWidth, nHeight); + break; + case 2: // screen to memory using virtual screen + sdc.GetPrimaryDC(hdcSrc); + res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, sdc.GetHdc(), nXSrc, nYSrc, nWSrc, nHSrc, dwRop); + sdc.PutPrimaryDC(hdcSrc, FALSE, nXSrc, nYSrc, nWSrc, nHSrc); + break; + } + break; + case GDIMODE_STRETCHED: { + int nWDest, nHDest; + nWDest= nWidth; + nHDest= nHeight; + dxw.MapClient(&nXDest, &nYDest, &nWDest, &nHDest); + res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWDest, nHDest, hdcSrc, nXSrc, nYSrc, nWSrc, nHSrc, dwRop); + OutTraceB("GDI.StretchBlt: DEBUG DC dest=(%d,%d) size=(%d,%d)\n", nXDest, nYDest, nWDest, nHDest); + } + break; + case GDIMODE_EMULATED: + default: + res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWSrc, nHSrc, dwRop); + break; + } + } + else { + res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWSrc, nHSrc, dwRop); + } + + if(IsDCLeakageSrc) (*pGDIReleaseDC)(dxw.GethWnd(), hdcSrc); + if(IsDCLeakageDest) (*pGDIReleaseDC)(dxw.GethWnd(), hdcDest); + if(res && IsToScreen) dxw.ShowOverlay(hdcDest); + if(!res) OutTraceE("GDI.StretchBlt: ERROR err=%d at %d\n", GetLastError(), __LINE__); + return res; +} + BOOL WINAPI extGDIPatBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, DWORD dwRop) { BOOL res; BOOL IsToScreen; + BOOL IsDCLeakageDest = FALSE; OutTraceDW("GDI.PatBlt: HDC=%x nXDest=%d nYDest=%d nWidth=%d nHeight=%d dwRop=%x(%s)\n", hdcDest, nXDest, nYDest, nWidth, nHeight, dwRop, ExplainROP(dwRop)); OutTraceB("GDI.PatBlt: DEBUG FullScreen=%x target hdctype=%x(%s) hwnd=%x\n", - dxw.IsFullScreen(), GetObjectType(hdcDest), ExplainDCType(GetObjectType(hdcDest)), WindowFromDC(hdcDest)); + dxw.IsFullScreen(), (*pGetObjectType)(hdcDest), ExplainDCType((*pGetObjectType)(hdcDest)), WindowFromDC(hdcDest)); - if(dxw.dwFlags3 & GDIEMULATEDC){ + if(dxw.GDIEmulationMode == GDIMODE_EMULATED){ if (hdcDest==dxw.RealHDC) hdcDest=dxw.VirtualHDC; OutTraceB("GDI.PatBlt: DEBUG emulated hdc dest=%x->%x\n", dxw.RealHDC, hdcDest); } @@ -832,12 +1121,22 @@ BOOL WINAPI extGDIPatBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nH // happens in Reah, hdc is NULL despite the fact that BeginPaint returns a valid DC. Too bad, we recover here ... hdcDest = (*pGDIGetDC)(dxw.GethWnd()); OutTraceB("GDI.PatBlt: DEBUG hdc dest=NULL->%x\n", hdcDest); + IsDCLeakageDest = TRUE; } - IsToScreen=(OBJ_DC == GetObjectType(hdcDest)); + IsToScreen=(OBJ_DC == (*pGetObjectType)(hdcDest)); + if (IsToScreen && (dxw.dwFlags3 & NOGDIBLT)) return TRUE; - if(dxw.IsFullScreen()) { + + if(dxw.IsToRemap(hdcDest)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdcDest); + res=(*pGDIPatBlt)(sdc.GetHdc(), nXDest, nYDest, nWidth, nHeight, dwRop); + sdc.PutPrimaryDC(hdcDest, TRUE, nXDest, nYDest, nWidth, nHeight); + return res; + break; case GDIMODE_STRETCHED: { int nWDest, nHDest; nWDest= nWidth; @@ -857,62 +1156,12 @@ BOOL WINAPI extGDIPatBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nH res=(*pGDIPatBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, dwRop); } + if(IsDCLeakageDest) (*pGDIReleaseDC)(dxw.GethWnd(), hdcDest); if(res && IsToScreen) dxw.ShowOverlay(hdcDest); if(!res) OutTraceE("GDI.PatBlt: ERROR err=%d at %d\n", GetLastError(), __LINE__); return res; } -BOOL WINAPI extGDIStretchBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, - HDC hdcSrc, int nXSrc, int nYSrc, int nWSrc, int nHSrc, DWORD dwRop) -{ - BOOL res; - BOOL IsToScreen; - - OutTraceDW("GDI.StretchBlt: HDC=%x nXDest=%d nYDest=%d nWidth=%d nHeight=%d hdcSrc=%x nXSrc=%d nYSrc=%d nWSrc=%d nHSrc=%d dwRop=%x(%s)\n", - hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWSrc, nHSrc, dwRop, ExplainROP(dwRop)); - - OutTraceB("GDI.StretchBlt: DEBUG FullScreen=%x target hdctype=%x(%s) hwnd=%x\n", - dxw.IsFullScreen(), GetObjectType(hdcDest), ExplainDCType(GetObjectType(hdcDest)), WindowFromDC(hdcDest)); - - if(dxw.dwFlags3 & GDIEMULATEDC){ - if (hdcDest==dxw.RealHDC) hdcDest=dxw.VirtualHDC; - OutTraceB("GDI.StretchBlt: DEBUG emulated hdc dest=%x->%x\n", dxw.RealHDC, hdcDest); - } - - if(hdcDest == NULL){ - // happens in Reah, hdc is NULL despite the fact that BeginPaint returns a valid DC. Too bad, we recover here ... - hdcDest = (*pGDIGetDC)(dxw.GethWnd()); - OutTraceB("GDI.StretchBlt: DEBUG hdc dest=NULL->%x\n", hdcDest); - } - - IsToScreen=(OBJ_DC == GetObjectType(hdcDest)); - if (IsToScreen && (dxw.dwFlags3 & NOGDIBLT)) return TRUE; - if(dxw.IsFullScreen()) { - switch(dxw.GDIEmulationMode){ - case GDIMODE_STRETCHED: { - int nWDest, nHDest; - nWDest= nWidth; - nHDest= nHeight; - dxw.MapClient(&nXDest, &nYDest, &nWDest, &nHDest); - res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWDest, nHDest, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, dwRop); - OutTraceB("GDI.StretchBlt: DEBUG DC dest=(%d,%d) size=(%d,%d)\n", nXDest, nYDest, nWDest, nHDest); - } - break; - case GDIMODE_EMULATED: - default: - res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, dwRop); - break; - } - } - else { - res=(*pGDIStretchBlt)(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, dwRop); - } - - if(res && IsToScreen) dxw.ShowOverlay(hdcDest); - if(!res) OutTraceE("GDI.StretchBlt: ERROR err=%d at %d\n", GetLastError(), __LINE__); - return res; -} - BOOL WINAPI extGDIDeleteDC(HDC hdc) { BOOL res; @@ -989,26 +1238,36 @@ BOOL WINAPI extGetDeviceGammaRamp(HDC hDC, LPVOID lpRamp) return ret; } -static char *sClipType(int t) -{ - static char *sRetCodes[4]={"ERROR", "NULLREGION", "SIMPLEREGION", "COMPLEXREGION"}; - if(t<0 || t>3) return "Unknown"; - return sRetCodes[t]; -} - int WINAPI extGetClipBox(HDC hdc, LPRECT lprc) { // v2.02.31: needed in "Imperialism II" to avoid blit clipping int ret; OutTraceDW("GetClipBox: hdc=%x\n", hdc); - ret=(*pGDIGetClipBox)(hdc, lprc); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc)) && (ret!=ERROR)){ - OutTraceDW("GetClipBox: scaling main win coordinates (%d,%d)-(%d,%d)\n", - lprc->left, lprc->top, lprc->right, lprc->bottom); - dxw.UnmapClient(lprc); + + if (dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pGDIGetClipBox)(sdc.GetHdc(), lprc); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + case GDIMODE_STRETCHED: + ret=(*pGDIGetClipBox)(hdc, lprc); + OutTraceDW("GetClipBox: scaling main win coordinates (%d,%d)-(%d,%d)\n", + lprc->left, lprc->top, lprc->right, lprc->bottom); + dxw.UnmapClient(lprc); + break; + default: + ret=(*pGDIGetClipBox)(hdc, lprc); + break; + } } + else + ret=(*pGDIGetClipBox)(hdc, lprc); + OutTraceDW("GetClipBox: ret=%x(%s) rect=(%d,%d)-(%d,%d)\n", - ret, sClipType(ret), lprc->left, lprc->top, lprc->right, lprc->bottom); + ret, ExplainRegionType(ret), lprc->left, lprc->top, lprc->right, lprc->bottom); return ret; } @@ -1017,13 +1276,23 @@ int WINAPI extIntersectClipRect(HDC hdc, int nLeftRect, int nTopRect, int nRight int ret; OutTraceDW("IntersectClipRect: hdc=%x rect=(%d,%d)-(%d,%d)\n", hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&nLeftRect, &nTopRect, &nRightRect, &nBottomRect); - OutTraceDW("IntersectClipRect: fixed rect=(%d,%d)-(%d,%d)\n", nLeftRect, nTopRect, nRightRect, nBottomRect); + if (dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pIntersectClipRect)(sdc.GetHdc(), nLeftRect, nTopRect, nRightRect, nBottomRect); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&nLeftRect, &nTopRect, &nRightRect, &nBottomRect); + OutTraceDW("IntersectClipRect: fixed rect=(%d,%d)-(%d,%d)\n", nLeftRect, nTopRect, nRightRect, nBottomRect); + break; + } } ret=(*pIntersectClipRect)(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); - OutTraceE("CreateRectRgnIndirect: ret=%x(%s)\n", ret, sClipType(ret)); + OutTraceE("IntersectClipRect: ret=%x(%s)\n", ret, ExplainRegionType(ret)); return ret; } @@ -1032,10 +1301,14 @@ int WINAPI extGetRgnBox(HRGN hrgn, LPRECT lprc) int ret; OutTraceDW("GetRgnBox: hrgn=%x\n", hrgn); ret=(*pGetRgnBox)(hrgn, lprc); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hrgn)) && (ret!=ERROR)){ - OutTraceDW("GetRgnBox: scaling main win coordinates (%d,%d)-(%d,%d)\n", - lprc->left, lprc->top, lprc->right, lprc->bottom); - dxw.UnmapClient(lprc); + if (dxw.IsFullScreen() && (ret!=ERROR)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + OutTraceDW("GetRgnBox: scaling main win coordinates (%d,%d)-(%d,%d)\n", + lprc->left, lprc->top, lprc->right, lprc->bottom); + dxw.UnmapClient(lprc); + break; + } } OutTraceDW("GetRgnBox: ret=%x(%s) rect=(%d,%d)-(%d,%d)\n", ret, ExplainRegionType(ret), lprc->left, lprc->top, lprc->right, lprc->bottom); @@ -1052,14 +1325,25 @@ BOOL WINAPI extPolyline(HDC hdc, const POINT *lppt, int cPoints) for(i=0; ibmiHeader); OutTraceDW("SetDIBits: BitmapInfo dim=(%dx%d) Planes=%d BPP=%d Compression=%x SizeImage=%x\n", bmi->biWidth, bmi->biHeight, bmi->biPlanes, bmi->biBitCount, bmi->biCompression, bmi->biSizeImage); - ret = (*pSetDIBits)(hdc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); - OutTraceDW("SetDIBits: ret=%d\n", ret); - return ret; - //return cScanLines; - //return (*pSetDIBits)(hdc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, DIB_PAL_COLORS); - //return (*pSetDIBits)(hdc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, DIB_RGB_COLORS); + if(dxw.IsToRemap(hdc) && !bGDIRecursionFlag){ + //HDC hTempDc; + //HBITMAP hbmPic; + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: // this will flicker !!!! + sdc.GetPrimaryDC(hdc); + ret=(*pSetDIBits)(sdc.GetHdc(), hbmp, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + sdc.PutPrimaryDC(hdc, TRUE, 0, 0, bmi->biWidth, bmi->biHeight); + return ret; + break; + case GDIMODE_STRETCHED: +#if 0 + // blitting to primary surface !!! + int OrigXDest, OrigYDest; + OrigWidth=dwWidth; + OrigHeight=dwHeight; + OrigXDest=XDest; + OrigYDest=YDest; + dxw.MapClient(&XDest, &YDest, (int *)&dwWidth, (int *)&dwHeight); + OutTraceDW("SetDIBitsToDevice: fixed dest=(%d,%d)-(%dx%d)\n", XDest, YDest, dwWidth, dwHeight); + if(!(hTempDc=CreateCompatibleDC(hdc))) + OutTraceE("CreateCompatibleDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + // tricky part: CreateCompatibleBitmap is needed to set the dc size, but it has to be performed + // against hdc to set for color depth, then selected (through SelectObject) against the temporary + // dc to assign the needed size and color space to the temporary dc. + if(!(hbmPic=CreateCompatibleBitmap(hdc, OrigWidth, OrigHeight))) + OutTraceE("CreateCompatibleBitmap: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!SelectObject(hTempDc, hbmPic)) + OutTraceE("SelectObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(*pSetDIBits)(hTempDc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse)) + OutTraceE("SetDIBitsToDevice: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + // v2.02.94: set HALFTONE stretching. Fixes "Celtic Kings Rage of War" + SetStretchBltMode(hdc,HALFTONE); + if(!(ret=(*pGDIStretchBlt)(hdc, XDest, YDest, dwWidth, dwHeight, hTempDc, 0, 0, OrigWidth, OrigHeight, SRCCOPY))) + OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(DeleteObject(hbmPic))) // v2.02.32 - avoid resource leakage + OutTraceE("DeleteObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(DeleteDC(hTempDc))) + OutTraceE("DeleteDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + return TRUE; +#endif + break; + case GDIMODE_EMULATED: +#if 0 + if (dxw.IsVirtual(hdc)){ + int X, Y; + X=XDest+dxw.VirtualOffsetX; + Y=YDest+dxw.VirtualOffsetY; + OutTraceDW("SetDIBitsToDevice: virtual pos=(%d,%d)+(%d+%d)=(%d,%d)\n", + XDest, YDest, dxw.VirtualOffsetX, dxw.VirtualOffsetY, X, Y); + ret=(*pSetDIBits)(sdc.GetHdc(), hbmp, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + if(!ret || (ret==GDI_ERROR)) OutTraceE("SetDIBitsToDevice: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; + } +#endif + break; + default: + break; + } + } + + return (*pSetDIBits)(hdc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + if(!ret || (ret==GDI_ERROR)) OutTraceE("SetDIBits: ERROR err=%d\n", GetLastError()); + return ret; } +int WINAPI extGetDIBits(HDC hdc, HBITMAP hbmp, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uUsage) +{ + int ret; + BITMAPINFOHEADER *bmi; + OutTraceDW("GetDIBits: hdc=%x hbmp=%x lines=(%d,%d) ColorUse=%x\n", hdc, hbmp, uStartScan, cScanLines, uUsage); + bmi=(BITMAPINFOHEADER *)&(lpbmi->bmiHeader); + OutTraceDW("GetDIBits: BitmapInfo dim=(%dx%d) Planes=%d BPP=%d Compression=%x SizeImage=%x\n", + bmi->biWidth, bmi->biHeight, bmi->biPlanes, bmi->biBitCount, bmi->biCompression, bmi->biSizeImage); + + if(dxw.IsToRemap(hdc) && !bGDIRecursionFlag){ + //HDC hTempDc; + //HBITMAP hbmPic; + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: // this will flicker !!!! + sdc.GetPrimaryDC(hdc); + ret=(*pGetDIBits)(sdc.GetHdc(), hbmp, uStartScan, cScanLines, lpvBits, lpbmi, uUsage); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + case GDIMODE_EMULATED: + default: + break; + } + } + + return (*pGetDIBits)(hdc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, uUsage); + if(!ret || (ret==GDI_ERROR)) OutTraceE("GetDIBits: ERROR err=%d\n", GetLastError()); + return ret; +} + +#if 0 int WINAPI extSetDIBitsToDevice(HDC hdc, int XDest, int YDest, DWORD dwWidth, DWORD dwHeight, int XSrc, int YSrc, UINT uStartScan, UINT cScanLines, const VOID *lpvBits, const BITMAPINFO *lpbmi, UINT fuColorUse) { @@ -1232,87 +1804,204 @@ int WINAPI extSetDIBitsToDevice(HDC hdc, int XDest, int YDest, DWORD dwWidth, DW OutTraceDW("SetDIBitsToDevice: BitmapInfo dim=(%dx%d) Planes=%d BPP=%d Compression=%x SizeImage=%x\n", bmi->biWidth, bmi->biHeight, bmi->biPlanes, bmi->biBitCount, bmi->biCompression, bmi->biSizeImage); - if (dxw.IsFullScreen() && dxw.IsVirtual(hdc)){ - int X, Y; - X=XDest+dxw.VirtualOffsetX; - Y=YDest+dxw.VirtualOffsetY; - OutTraceDW("SetDIBitsToDevice: virtual pos=(%d,%d)+(%d+%d)=(%d,%d)\n", - XDest, YDest, dxw.VirtualOffsetX, dxw.VirtualOffsetY, X, Y); - ret=(*pSetDIBitsToDevice)(hdc, X, Y, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); - if(!ret || (ret==GDI_ERROR)) OutTraceE("SetDIBitsToDevice: ERROR ret=%x err=%d\n", ret, GetLastError()); - return ret; - } - //else - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - // blitting to primary surface !!! + bGDIRecursionFlag = TRUE; // beware: it seems that SetDIBitsToDevice calls SetDIBits internally + if(dxw.IsFullScreen()){ + HDC hTempDc; + HBITMAP hbmPic; DWORD OrigWidth, OrigHeight; int OrigXDest, OrigYDest; OrigWidth=dwWidth; OrigHeight=dwHeight; OrigXDest=XDest; OrigYDest=YDest; - dxw.MapClient(&XDest, &YDest, (int *)&dwWidth, (int *)&dwHeight); - OutTraceDW("SetDIBitsToDevice: fixed dest=(%d,%d)-(%dx%d)\n", XDest, YDest, dwWidth, dwHeight); - HDC hTempDc; - HBITMAP hbmPic; - - if(dxw.HandleFPS()) return DD_OK; - if(dxw.dwFlags5 & NOBLT) return DD_OK; - - if(!(hTempDc=CreateCompatibleDC(hdc))) - OutTraceE("CreateCompatibleDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); - // tricky part: CreateCompatibleBitmap is needed to set the dc size, but it has to be performed - // against hdc to set for color depth, then selected (through SelectObject) against the temporary - // dc to assign the needed size and color space to the temporary dc. - if(!(hbmPic=CreateCompatibleBitmap(hdc, OrigWidth, OrigHeight))) - OutTraceE("CreateCompatibleBitmap: ERROR err=%d at=%d\n", GetLastError(), __LINE__); - if(!SelectObject(hTempDc, hbmPic)) - OutTraceE("SelectObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); - if(!(*pSetDIBitsToDevice)(hTempDc, 0, 0, OrigWidth, OrigHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse)) - OutTraceE("SetDIBitsToDevice: ERROR err=%d at=%d\n", GetLastError(), __LINE__); - // v2.02.94: set HALFTONE stretching. Fixes "Celtic Kings Rage of War" - SetStretchBltMode(hdc,HALFTONE); - if(!(ret=(*pGDIStretchBlt)(hdc, XDest, YDest, dwWidth, dwHeight, hTempDc, 0, 0, OrigWidth, OrigHeight, SRCCOPY))) - OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); - - dxw.ShowOverlay(hdc); - - if(!(DeleteObject(hbmPic))) // v2.02.32 - avoid resource leakage - OutTraceE("DeleteObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); - if(!(DeleteDC(hTempDc))) - OutTraceE("DeleteDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); - } - else{ - ret=(*pSetDIBitsToDevice)(hdc, XDest, YDest, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + if(dxw.IsToRemap(hdc)){ + sdc.GetPrimaryDC(hdc); + ret=(*pSetDIBitsToDevice)(sdc.GetHdc(), XDest, YDest, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + sdc.PutPrimaryDC(hdc, TRUE, XDest, YDest, dwWidth, dwHeight); + } + else{ + ret=(*pSetDIBitsToDevice)(hdc, XDest, YDest, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + } + bGDIRecursionFlag = FALSE; + return ret; + break; + case GDIMODE_STRETCHED: + if(dxw.IsToRemap(hdc)){ + // blitting to primary surface !!! + dxw.MapClient(&XDest, &YDest, (int *)&dwWidth, (int *)&dwHeight); + OutTraceDW("SetDIBitsToDevice: fixed dest=(%d,%d)-(%dx%d)\n", XDest, YDest, dwWidth, dwHeight); + if(!(hTempDc=CreateCompatibleDC(hdc))) + OutTraceE("CreateCompatibleDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + // tricky part: CreateCompatibleBitmap is needed to set the dc size, but it has to be performed + // against hdc to set for color depth, then selected (through SelectObject) against the temporary + // dc to assign the needed size and color space to the temporary dc. + if(!(hbmPic=CreateCompatibleBitmap(hdc, OrigWidth, OrigHeight))) + OutTraceE("CreateCompatibleBitmap: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!SelectObject(hTempDc, hbmPic)) + OutTraceE("SelectObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(ret=(*pSetDIBitsToDevice)(hTempDc, 0, 0, OrigWidth, OrigHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse))) + OutTraceE("SetDIBitsToDevice: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + bGDIRecursionFlag = FALSE; + // v2.02.94: set HALFTONE stretching. Fixes "Celtic Kings Rage of War" + SetStretchBltMode(hdc,HALFTONE); + if(!(ret=(*pGDIStretchBlt)(hdc, XDest, YDest, dwWidth, dwHeight, hTempDc, 0, 0, OrigWidth, OrigHeight, SRCCOPY))) + OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(DeleteObject(hbmPic))) // v2.02.32 - avoid resource leakage + OutTraceE("DeleteObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(DeleteDC(hTempDc))) + OutTraceE("DeleteDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + return ret; + } + break; + case GDIMODE_EMULATED: + if (dxw.IsVirtual(hdc)){ + int X, Y; + X=XDest+dxw.VirtualOffsetX; + Y=YDest+dxw.VirtualOffsetY; + OutTraceDW("SetDIBitsToDevice: virtual pos=(%d,%d)+(%d+%d)=(%d,%d)\n", + XDest, YDest, dxw.VirtualOffsetX, dxw.VirtualOffsetY, X, Y); + ret=(*pSetDIBitsToDevice)(hdc, X, Y, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + bGDIRecursionFlag = FALSE; + if(!ret || (ret==GDI_ERROR)) OutTraceE("SetDIBitsToDevice: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; + } + break; + default: + break; + } } + + ret=(*pSetDIBitsToDevice)(hdc, XDest, YDest, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + bGDIRecursionFlag = FALSE; if(!ret || (ret==GDI_ERROR)) OutTraceE("SetDIBitsToDevice: ERROR ret=%x err=%d\n", ret, GetLastError()); return ret; } +#else +int WINAPI extSetDIBitsToDevice(HDC hdc, int XDest, int YDest, DWORD dwWidth, DWORD dwHeight, int XSrc, int YSrc, UINT uStartScan, UINT cScanLines, + const VOID *lpvBits, const BITMAPINFO *lpbmi, UINT fuColorUse) +{ + int ret; + BITMAPINFOHEADER *bmi; + OutTraceDW("SetDIBitsToDevice: hdc=%x dest=(%d,%d)-(%dx%d) src=(%d,%d) lines=(%d,%d)\n", + hdc, XDest, YDest, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines); + bmi=(BITMAPINFOHEADER *)&(lpbmi->bmiHeader); + OutTraceDW("SetDIBitsToDevice: BitmapInfo dim=(%dx%d) Planes=%d BPP=%d Compression=%x SizeImage=%x\n", + bmi->biWidth, bmi->biHeight, bmi->biPlanes, bmi->biBitCount, bmi->biCompression, bmi->biSizeImage); -//HBITMAP WINAPI extCreateCompatibleBitmap(HDC hdc, int nWidth, int nHeight) -//{ -// HBITMAP ret; -// OutTraceDW("CreateCompatibleBitmap: hdc=%x size=(%d,%d)\n", -// hdc, nWidth, nHeight); -// -// if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ -// dxw.MapClient(&nWidth, &nHeight); -// OutTraceDW("CreateCompatibleBitmap: fixed size=(%d,%d)\n", nWidth, nHeight); -// } -// -// ret=(*pCreateCompatibleBitmap)(hdc, nWidth, nHeight); -// if(!ret) OutTraceE("CreateCompatibleBitmap: ERROR ret=%x err=%d\n", ret, GetLastError()); -// return ret; -//} + bGDIRecursionFlag = TRUE; // beware: it seems that SetDIBitsToDevice calls SetDIBits internally + if(dxw.IsToRemap(hdc)){ + HDC hTempDc; + HBITMAP hbmPic; + DWORD OrigWidth, OrigHeight; + int OrigXDest, OrigYDest; + OrigWidth=dwWidth; + OrigHeight=dwHeight; + OrigXDest=XDest; + OrigYDest=YDest; + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pSetDIBitsToDevice)(sdc.GetHdc(), XDest, YDest, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + sdc.PutPrimaryDC(hdc, TRUE, XDest, YDest, dwWidth, dwHeight); + bGDIRecursionFlag = FALSE; + return ret; + break; + case GDIMODE_STRETCHED: + // blitting to primary surface !!! + dxw.MapClient(&XDest, &YDest, (int *)&dwWidth, (int *)&dwHeight); + OutTraceDW("SetDIBitsToDevice: fixed dest=(%d,%d)-(%dx%d)\n", XDest, YDest, dwWidth, dwHeight); + if(!(hTempDc=CreateCompatibleDC(hdc))) + OutTraceE("CreateCompatibleDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + // tricky part: CreateCompatibleBitmap is needed to set the dc size, but it has to be performed + // against hdc to set for color depth, then selected (through SelectObject) against the temporary + // dc to assign the needed size and color space to the temporary dc. + if(!(hbmPic=CreateCompatibleBitmap(hdc, OrigWidth, OrigHeight))) + OutTraceE("CreateCompatibleBitmap: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!SelectObject(hTempDc, hbmPic)) + OutTraceE("SelectObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(ret=(*pSetDIBitsToDevice)(hTempDc, 0, 0, OrigWidth, OrigHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse))) + OutTraceE("SetDIBitsToDevice: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + bGDIRecursionFlag = FALSE; + // v2.02.94: set HALFTONE stretching. Fixes "Celtic Kings Rage of War" + SetStretchBltMode(hdc,HALFTONE); + if(!(ret=(*pGDIStretchBlt)(hdc, XDest, YDest, dwWidth, dwHeight, hTempDc, 0, 0, OrigWidth, OrigHeight, SRCCOPY))) + OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(DeleteObject(hbmPic))) // v2.02.32 - avoid resource leakage + OutTraceE("DeleteObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + if(!(DeleteDC(hTempDc))) + OutTraceE("DeleteDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + return ret; + break; + case GDIMODE_EMULATED: + int X, Y; + X=XDest+dxw.VirtualOffsetX; + Y=YDest+dxw.VirtualOffsetY; + OutTraceDW("SetDIBitsToDevice: virtual pos=(%d,%d)+(%d+%d)=(%d,%d)\n", + XDest, YDest, dxw.VirtualOffsetX, dxw.VirtualOffsetY, X, Y); + ret=(*pSetDIBitsToDevice)(hdc, X, Y, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + bGDIRecursionFlag = FALSE; + if(!ret || (ret==GDI_ERROR)) OutTraceE("SetDIBitsToDevice: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; + default: + break; + } + } + + ret=(*pSetDIBitsToDevice)(hdc, XDest, YDest, dwWidth, dwHeight, XSrc, YSrc, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + bGDIRecursionFlag = FALSE; + if(!ret || (ret==GDI_ERROR)) OutTraceE("SetDIBitsToDevice: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} +#endif + +HBITMAP WINAPI extCreateCompatibleBitmap(HDC hdc, int nWidth, int nHeight) +{ + HBITMAP ret; + OutTraceDW("CreateCompatibleBitmap: hdc=%x size=(%d,%d)\n", + hdc, nWidth, nHeight); + + if (dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pCreateCompatibleBitmap)(sdc.GetHdc(), nWidth, nHeight); + sdc.PutPrimaryDC(hdc, FALSE); + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&nWidth, &nHeight); + OutTraceDW("CreateCompatibleBitmap: fixed size=(%d,%d)\n", nWidth, nHeight); + break; + default: + break; + } + } + + ret=(*pCreateCompatibleBitmap)(hdc, nWidth, nHeight); + if(!ret) OutTraceE("CreateCompatibleBitmap: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} COLORREF WINAPI extSetPixel(HDC hdc, int X, int Y, COLORREF crColor) { COLORREF ret; OutTraceDW("SetPixel: hdc=%x color=%x point=(%d,%d)\n", hdc, crColor, X, Y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&X, &Y); - OutTraceDW("SetPixel: fixed pos=(%d,%d)\n", X, Y); + if(dxw.IsToRemap(hdc)){ + + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pSetPixel)(sdc.GetHdc(), X, Y, crColor); + sdc.PutPrimaryDC(hdc, TRUE, X, Y, 1, 1); // ???? + return ret; // this returns a COLORREF type + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + OutTraceDW("SetPixel: fixed pos=(%d,%d)\n", X, Y); + break; + } } ret=(*pSetPixel)(hdc, X, Y, crColor); @@ -1321,14 +2010,48 @@ COLORREF WINAPI extSetPixel(HDC hdc, int X, int Y, COLORREF crColor) return ret; } +BOOL WINAPI extSetPixelV(HDC hdc, int X, int Y, COLORREF crColor) +{ + BOOL ret; + OutTraceDW("SetPixelV: hdc=%x color=%x point=(%d,%d)\n", hdc, crColor, X, Y); + + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pSetPixelV)(sdc.GetHdc(), X, Y, crColor); + sdc.PutPrimaryDC(hdc, TRUE, X, Y, 1, 1); // ???? + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + OutTraceDW("SetPixelV: fixed pos=(%d,%d)\n", X, Y); + break; + } + } + + ret=(*pSetPixelV)(hdc, X, Y, crColor); + return ret; +} + BOOL WINAPI extEllipse(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) { int ret; OutTraceDW("Ellipse: hdc=%x rect=(%d,%d)-(%d,%d)\n", hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&nLeftRect, &nTopRect, &nRightRect, &nBottomRect); - OutTraceDW("Ellipse: fixed dest=(%d,%d)-(%d,%d)\n", nLeftRect, nTopRect, nRightRect, nBottomRect); + if (dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pEllipse)(sdc.GetHdc(),nLeftRect, nTopRect, nRightRect, nBottomRect); + sdc.PutPrimaryDC(hdc, TRUE, nLeftRect, nTopRect, nRightRect-nLeftRect, nBottomRect-nTopRect); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&nLeftRect, &nTopRect, &nRightRect, &nBottomRect); + OutTraceDW("Ellipse: fixed dest=(%d,%d)-(%d,%d)\n", nLeftRect, nTopRect, nRightRect, nBottomRect); + break; + } } ret=(*pEllipse)(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); @@ -1346,16 +2069,48 @@ BOOL WINAPI extPolygon(HDC hdc, const POINT *lpPoints, int cCount) for(i=0; ix = dxw.VirtualOffsetX; - lpPoint->y = dxw.VirtualOffsetY; - } - dxw.VirtualOffsetX = X; - dxw.VirtualOffsetY = Y; - return TRUE; - } - - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&X, &Y); - OutTraceDW("SetViewportOrgEx: fixed pos=(%d,%d)\n", X, Y); - } - - ret=(*pSetViewportOrgEx)(hdc, X, Y, lpPoint); - if(ret && lpPoint) { - OutTraceDW("SetViewportOrgEx: previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.UnmapClient(lpPoint); - OutTraceDW("SetViewportOrgEx: fixed previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_EMULATED: + if(dxw.IsVirtual(hdc)) { + OutTraceDW("SetViewportOrgEx: virtual hdc\n"); + if(lpPoint){ + lpPoint->x = dxw.VirtualOffsetX; + lpPoint->y = dxw.VirtualOffsetY; + } + dxw.VirtualOffsetX = X; + dxw.VirtualOffsetY = Y; + ret = TRUE; + } + else + ret=(*pSetViewportOrgEx)(hdc, X, Y, lpPoint); + break; + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pSetViewportOrgEx)(sdc.GetHdc(), X, Y, lpPoint); + sdc.PutPrimaryDC(hdc, FALSE); + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + OutTraceDW("SetViewportOrgEx: fixed pos=(%d,%d)\n", X, Y); + ret=(*pSetViewportOrgEx)(hdc, X, Y, lpPoint); + if(ret && lpPoint) { + OutTraceDW("SetViewportOrgEx: previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); + dxw.UnmapClient(lpPoint); + OutTraceDW("SetViewportOrgEx: fixed previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); + } + break; + default: + ret=(*pSetViewportOrgEx)(hdc, X, Y, lpPoint); + break; } } + else{ + ret=(*pSetViewportOrgEx)(hdc, X, Y, lpPoint); + } + + if(ret && lpPoint) OutTraceDW("SetViewportOrgEx: previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); if(!ret) OutTraceE("SetViewportOrgEx: ERROR ret=%x err=%d\n", ret, GetLastError()); return ret; } -BOOL WINAPI extSetViewportExtEx(HDC hdc, int nXExtent, int nYExtent, LPSIZE lpSize) +BOOL WINAPI extSetViewportExtEx(HDC hdc, int X, int Y, LPSIZE lpSize) { BOOL ret; - OutTraceDW("SetViewportExtEx: hdc=%x ext=(%d,%d)\n", hdc, nXExtent, nYExtent); + OutTraceDW("SetViewportExtEx: hdc=%x pos=(%d,%d)\n", hdc, X, Y); - if(dxw.IsVirtual(hdc)) { - OutTraceDW("SetViewportExtEx: virtual hdc\n"); - if(lpSize){ - lpSize->cx = dxw.VirtualExtentX; - lpSize->cy = dxw.VirtualExtentY; - } - dxw.VirtualExtentX = nXExtent; - dxw.VirtualExtentY = nYExtent; - return TRUE; - } - - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&nXExtent, &nYExtent); - OutTraceDW("SetViewportExtEx: fixed ext=(%d,%d)\n", nXExtent, nYExtent); - } - - ret=(*pSetViewportExtEx)(hdc, nXExtent, nYExtent, lpSize); - if(ret && lpSize) { - OutTraceDW("SetViewportExtEx: previous ext=(%d,%d)\n", lpSize->cx, lpSize->cy); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.UnmapClient((LPPOINT)lpSize); - OutTraceDW("SetViewportExtEx: fixed previous ext=(%d,%d)\n", lpSize->cx, lpSize->cy); + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_EMULATED: + if(dxw.IsVirtual(hdc)) { + OutTraceDW("SetViewportExtEx: virtual hdc\n"); + if(lpSize){ + lpSize->cx = dxw.VirtualExtentX; + lpSize->cy = dxw.VirtualExtentY; + } + dxw.VirtualExtentX = X; + dxw.VirtualExtentY = Y; + ret = TRUE; + } + else + ret=(*pSetViewportExtEx)(hdc, X, Y, lpSize); + break; + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pSetViewportExtEx)(sdc.GetHdc(), X, Y, lpSize); + sdc.PutPrimaryDC(hdc, FALSE); + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + OutTraceDW("SetViewportExtEx: fixed pos=(%d,%d)\n", X, Y); + ret=(*pSetViewportExtEx)(hdc, X, Y, lpSize); + if(ret && lpSize) { + OutTraceDW("SetViewportExtEx: previous ViewPort=(%d,%d)\n", lpSize->cx, lpSize->cy); + dxw.UnmapClient((LPPOINT)lpSize); + OutTraceDW("SetViewportExtEx: fixed previous ViewPort=(%d,%d)\n", lpSize->cx, lpSize->cy); + } + break; + default: + ret=(*pSetViewportExtEx)(hdc, X, Y, lpSize); + break; } } + else{ + ret=(*pSetViewportExtEx)(hdc, X, Y, lpSize); + } - if(!ret) OutTraceE("SetViewportExtEx: ERROR ret=%x err=%d\n", ret, GetLastError()); + if(ret && lpSize) OutTraceDW("SetViewportOrgEx: previous ViewPort=(%d,%d)\n", lpSize->cx, lpSize->cy); + if(!ret) OutTraceE("SetViewportOrgEx: ERROR ret=%x err=%d\n", ret, GetLastError()); return ret; } @@ -1575,7 +2378,7 @@ BOOL WINAPI extGetViewportOrgEx(HDC hdc, LPPOINT lpPoint) ret=(*pGetViewportOrgEx)(hdc, lpPoint); if(ret) { OutTraceDW("GetViewportOrgEx: ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + if (dxw.IsToRemap(hdc)){ dxw.UnmapClient(lpPoint); OutTraceDW("GetViewportOrgEx: fixed ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); } @@ -1599,7 +2402,7 @@ BOOL WINAPI extGetViewportExtEx(HDC hdc, LPPOINT lpPoint) ret=(*pGetViewportExtEx)(hdc, lpPoint); if(ret) { OutTraceDW("GetViewportExtEx: ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + if (dxw.IsToRemap(hdc)){ dxw.UnmapClient(lpPoint); OutTraceDW("GetViewportOrgEx: fixed ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); } @@ -1617,7 +2420,7 @@ BOOL WINAPI extGetWindowOrgEx(HDC hdc, LPPOINT lpPoint) ret=(*pGetWindowOrgEx)(hdc, lpPoint); if(ret) { OutTraceDW("GetWindowOrgEx: ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + if (dxw.IsToRemap(hdc)){ dxw.UnmapClient(lpPoint); OutTraceDW("GetWindowOrgEx: fixed ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); } @@ -1632,7 +2435,7 @@ BOOL WINAPI extSetWindowOrgEx(HDC hdc, int X, int Y, LPPOINT lpPoint) BOOL ret; OutTraceDW("SetWindowOrgEx: hdc=%x pos=(%d,%d)\n", hdc, X, Y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + if (dxw.IsToRemap(hdc)){ dxw.MapClient(&X, &Y); OutTraceDW("SetWindowOrgEx: fixed pos=(%d,%d)\n", X, Y); } @@ -1640,7 +2443,7 @@ BOOL WINAPI extSetWindowOrgEx(HDC hdc, int X, int Y, LPPOINT lpPoint) ret=(*pSetWindowOrgEx)(hdc, X, Y, lpPoint); if(ret && lpPoint) { OutTraceDW("SetWindowOrgEx: previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + if (dxw.IsToRemap(hdc)){ dxw.UnmapClient(lpPoint); OutTraceDW("SetWindowOrgEx: fixed previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); } @@ -1654,7 +2457,7 @@ BOOL WINAPI extSetWindowExtEx(HDC hdc, int X, int Y, LPPOINT lpPoint) BOOL ret; OutTraceDW("SetWindowExtEx: hdc=%x pos=(%d,%d)\n", hdc, X, Y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + if (dxw.IsToRemap(hdc)){ dxw.MapClient(&X, &Y); OutTraceDW("SetWindowExtEx: fixed pos=(%d,%d)\n", X, Y); } @@ -1662,7 +2465,7 @@ BOOL WINAPI extSetWindowExtEx(HDC hdc, int X, int Y, LPPOINT lpPoint) ret=(*pSetWindowExtEx)(hdc, X, Y, lpPoint); if(ret && lpPoint) { OutTraceDW("SetWindowExtEx: previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + if (dxw.IsToRemap(hdc)){ dxw.UnmapClient(lpPoint); OutTraceDW("SetWindowExtEx: fixed previous ViewPort=(%d,%d)\n", lpPoint->x, lpPoint->y); } @@ -1679,8 +2482,21 @@ BOOL WINAPI extGetCurrentPositionEx(HDC hdc, LPPOINT lpPoint) ret=(*pGetCurrentPositionEx)(hdc, lpPoint); if(ret) { OutTraceDW("GetCurrentPositionEx: pos=(%d,%d)\n", lpPoint->x, lpPoint->y); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.UnmapClient(lpPoint); + if (dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + dxw.UnmapClient(lpPoint); + break; + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pGetCurrentPositionEx)(sdc.GetHdc(), lpPoint); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + case GDIMODE_EMULATED: + default: + break; + } OutTraceDW("GetCurrentPositionEx: fixed pos=(%d,%d)\n", lpPoint->x, lpPoint->y); } } @@ -1834,6 +2650,7 @@ extern BOOL gFixed; BOOL WINAPI extExtTextOutA(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCSTR lpString, UINT cbCount, const INT *lpDx) { RECT rc; + BOOL ret; if(IsTraceDW){ char sRect[81]; if(lprc) sprintf(sRect, "(%d,%d)-(%d,%d)", lprc->left, lprc->top, lprc->right, lprc->bottom); @@ -1841,10 +2658,28 @@ BOOL WINAPI extExtTextOutA(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lp OutTrace("ExtTextOutA: hdc=%x pos=(%d,%d) String=\"%s\" rect=%s\n", hdc, X, Y, lpString, sRect); } - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc)) && !gFixed){ - dxw.MapClient(&X, &Y); - if(lprc) dxw.MapClient(&rc); - OutTraceDW("ExtTextOutA: fixed pos=(%d,%d)\n", X, Y); + if (dxw.IsToRemap(hdc) && !gFixed){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pExtTextOutA)(sdc.GetHdc(), X, Y, fuOptions, lprc, lpString, cbCount, lpDx); + if(lprc){ + rc = *lprc; + sdc.PutPrimaryDC(hdc, TRUE, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + } + else + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + if(lprc) { + rc = *lprc; + dxw.MapClient(&rc); + } + OutTraceDW("ExtTextOutA: fixed pos=(%d,%d)\n", X, Y); + break; + } } if(lprc) return (*pExtTextOutA)(hdc, X, Y, fuOptions, &rc, lpString, cbCount, lpDx); @@ -1855,6 +2690,7 @@ BOOL WINAPI extExtTextOutA(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lp BOOL WINAPI extExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cbCount, const INT *lpDx) { RECT rc; + BOOL ret; if(IsTraceDW){ char sRect[81]; if(lprc) sprintf(sRect, "(%d,%d)-(%d,%d)", lprc->left, lprc->top, lprc->right, lprc->bottom); @@ -1862,10 +2698,28 @@ BOOL WINAPI extExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lp OutTrace("ExtTextOutW: hdc=%x pos=(%d,%d) String=\"%ls\" rect=%s\n", hdc, X, Y, lpString, sRect); } - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc)) && !gFixed){ - dxw.MapClient(&X, &Y); - if(lprc) dxw.MapClient(&rc); - OutTraceDW("ExtTextOutW: fixed pos=(%d,%d)\n", X, Y); + if (dxw.IsToRemap(hdc) && !gFixed){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pExtTextOutW)(sdc.GetHdc(), X, Y, fuOptions, lprc, lpString, cbCount, lpDx); + if(lprc){ + rc = *lprc; + sdc.PutPrimaryDC(hdc, TRUE, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + } + else + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + if(lprc) { + rc = *lprc; + dxw.MapClient(&rc); + } + OutTraceDW("ExtTextOutW: fixed pos=(%d,%d)\n", X, Y); + break; + } } if(lprc) return (*pExtTextOutW)(hdc, X, Y, fuOptions, &rc, lpString, cbCount, lpDx); @@ -1949,3 +2803,411 @@ DWORD WINAPI extGetRegionData(HRGN hRgn, DWORD dwCount, LPRGNDATA lpRgnData) return ret; } #endif + +int WINAPI extOffsetRgn(HRGN hrgn, int nXOffset, int nYOffset) +{ + OutTraceDW("OffsetRgn(hrgn=%x nXOffset=%d nYOffset=%d\n", hrgn, nXOffset, nYOffset); + + if(dxw.IsFullScreen()){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + dxw.MapClient(&nXOffset, &nYOffset); + OutTraceDW("OffsetRgn: fixed STRETCHED offset=(%d,%d)\n", nXOffset, nYOffset); + break; + default: + break; + } + } + + return (*pOffsetRgn)(hrgn, nXOffset, nYOffset); +} + +COLORREF WINAPI extGetPixel(HDC hdc, int nXPos, int nYPos) +{ + COLORREF ret; + OutTraceDW("CreateDIBitmap: hdc=%x\n", hdc); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pGetPixel)(sdc.GetHdc(), nXPos, nYPos); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + default: + // to do ..... + break; + } + } + + ret=(*pGetPixel)(hdc, nXPos, nYPos); + if(!ret) OutTraceE("CreateDIBitmap ERROR: err=%d\n", GetLastError()); + return ret;} + +BOOL WINAPI extPlgBlt(HDC hdcDest, const POINT *lpPoint, HDC hdcSrc, int nXSrc, int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask, int xMask, int yMask) +{ + MessageBox(0, "PlgBlt", "DxWnd", MB_OK); + return (COLORREF)0; +} + +BOOL WINAPI extChord(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nXRadial1, int nYRadial1, int nXRadial2, int nYRadial2) +{ + MessageBox(0, "Chord", "DxWnd", MB_OK); + return (COLORREF)0; +} + +BOOL WINAPI extPolyTextOutA(HDC hdc, const POLYTEXTA *pptxt, int cStrings) +{ + MessageBox(0, "PolyTextOutA", "DxWnd", MB_OK); + return TRUE; +} + +BOOL WINAPI extPolyTextOutW(HDC hdc, const POLYTEXTW *pptxt, int cStrings) +{ + MessageBox(0, "PolyTextOutW", "DxWnd", MB_OK); + return TRUE; +} + +HBITMAP WINAPI extCreateDIBitmap(HDC hdc, BITMAPINFOHEADER *lpbmih, DWORD fdwInit, const VOID *lpbInit, const BITMAPINFO *lpbmi, UINT fuUsage) +{ + HBITMAP ret; + OutTraceDW("CreateDIBitmap: hdc=%x\n", hdc); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pCreateDIBitmap)(sdc.GetHdc(), lpbmih, fdwInit, lpbInit, lpbmi, fuUsage); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + default: + break; + } + } + + ret = (*pCreateDIBitmap)(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage); + if(!ret) OutTraceE("CreateDIBitmap ERROR: err=%d\n", GetLastError()); + return ret; +} + +HBITMAP WINAPI extCreateDIBSection(HDC hdc, const BITMAPINFO *pbmi, UINT iUsage, VOID **ppvBits, HANDLE hSection, DWORD dwOffset) +{ + HBITMAP ret; + OutTraceDW("CreateDIBitmap: hdc=%x\n", hdc); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pCreateDIBSection)(sdc.GetHdc(), pbmi, iUsage, ppvBits, hSection, dwOffset); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + default: + break; + } + } + + ret=(*pCreateDIBSection)(hdc, pbmi, iUsage, ppvBits, hSection, dwOffset); + if(!ret) OutTraceE("CreateDIBitmap ERROR: err=%d\n", GetLastError()); + return ret; +} + +HBITMAP WINAPI extCreateDiscardableBitmap(HDC hdc, int nWidth, int nHeight) +{ + HBITMAP ret; + OutTraceDW("CreateDiscardableBitmap: hdc=%x size=(%dx%d)\n", hdc, nWidth, nHeight); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pCreateDiscardableBitmap)(sdc.GetHdc(), nWidth, nHeight); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + default: + break; + } + } + + ret=(*pCreateDiscardableBitmap)(hdc, nWidth, nHeight); + if(!ret) OutTraceE("CreateDiscardableBitmap ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extExtFloodFill(HDC hdc, int nXStart, int nYStart, COLORREF crColor, UINT fuFillType) +{ + BOOL ret; + OutTraceDW("ExtFloodFill: hdc=%x pos=(%d,%d)\n", hdc, nXStart, nYStart); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pExtFloodFill)(sdc.GetHdc(), nXStart, nYStart, crColor, fuFillType); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pExtFloodFill)(hdc, nXStart, nYStart, crColor, fuFillType); + if(!ret) OutTraceE("ExtFloodFill ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extGdiAlphaBlend(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, BLENDFUNCTION ftn) +{ + // to be handled the 4 flux cases ..... + _Warn("GdiAlphaBlend"); + return TRUE; +} + +BOOL WINAPI extGdiGradientFill(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode) +{ + _Warn("GdiGradientFill"); + return TRUE; +} + +BOOL WINAPI extGdiTransparentBlt(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, + HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, UINT crTransparent) +{ + // to be handled the 4 flux cases ..... + _Warn("GdiTransparentBlt"); + return TRUE; +} + +BOOL WINAPI extPie(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nXRadial1, int nYRadial1, int nXRadial2, int nYRadial2) +{ + BOOL ret; + OutTraceDW("Pie: hdc=%x rect=(%d,%d)-(%d,%d)\n", hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pPie)(sdc.GetHdc(), nLeftRect, nTopRect, nRightRect, nBottomRect, nXRadial1, nYRadial1, nXRadial2, nYRadial2); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pPie)(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect, nXRadial1, nYRadial1, nXRadial2, nYRadial2); + if(!ret) OutTraceE("Pie ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extAngleArc(HDC hdc, int X, int Y, DWORD dwRadius, FLOAT eStartAngle, FLOAT eSweepAngle) +{ + BOOL ret; + OutTraceDW("AngleArc: hdc=%x pos=(%d,%d)\n", hdc, X, Y); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pAngleArc)(sdc.GetHdc(), X, Y, dwRadius, eStartAngle, eSweepAngle); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pAngleArc)(hdc, X, Y, dwRadius, eStartAngle, eSweepAngle); + if(!ret) OutTraceE("AngleArc ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extPolyPolyline(HDC hdc, const POINT *lppt, const DWORD *lpdwPolyPoints, DWORD cCount) +{ + BOOL ret; + OutTraceDW("PolyPolyline: hdc=%x\n", hdc); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pPolyPolyline)(sdc.GetHdc(), lppt, lpdwPolyPoints, cCount); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pPolyPolyline)(hdc, lppt, lpdwPolyPoints, cCount); + if(!ret) OutTraceE("PolyPolyline ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extFillRgn(HDC hdc, HRGN hrgn, HBRUSH hbr) +{ + BOOL ret; + OutTraceDW("FillRgn: hdc=%x\n", hdc); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pFillRgn)(sdc.GetHdc(), hrgn, hbr); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pFillRgn)(hdc, hrgn, hbr); + if(!ret) OutTraceE("FillRgn ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extFrameRgn(HDC hdc, HRGN hrgn, HBRUSH hbr, int nWidth, int nHeight) +{ + BOOL ret; + OutTraceDW("FrameRgn: hdc=%x\n", hdc); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pFrameRgn)(sdc.GetHdc(), hrgn, hbr, nWidth, nHeight); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pFrameRgn)(hdc, hrgn, hbr, nWidth, nHeight); + if(!ret) OutTraceE("FrameRgn ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extInvertRgn(HDC hdc, HRGN hrgn) +{ + BOOL ret; + OutTraceDW("InvertRgn: hdc=%x hrgn=%x\n", hdc, hrgn); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pInvertRgn)(sdc.GetHdc(), hrgn); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pInvertRgn)(hdc, hrgn); + if(!ret) OutTraceE("InvertRgn ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extPaintRgn(HDC hdc, HRGN hrgn) +{ + BOOL ret; + OutTraceDW("PaintRgn: hdc=%x hrgn=%x\n", hdc, hrgn); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pPaintRgn)(sdc.GetHdc(), hrgn); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pPaintRgn)(hdc, hrgn); + if(!ret) OutTraceE("PaintRgn ERROR: err=%d\n", GetLastError()); + return ret; +} + +int WINAPI extSetMapMode(HDC hdc, int fnMapMode) +{ + int ret; + OutTraceDW("SetMapMode: hdc=%x fnMapMode=%x\n", hdc, fnMapMode); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pSetMapMode)(sdc.GetHdc(), fnMapMode); + sdc.PutPrimaryDC(hdc, FALSE); + return ret; + break; + default: + break; + } + } + + ret=(*pSetMapMode)(hdc, fnMapMode); + if(!ret) OutTraceE("SetMapMode ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extRoundRect(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidth, int nHeight) +{ + int ret; + OutTraceDW("RoundRect: hdc=%x rect=(%d,%d)-(%d,%d) ellipse=(%dx%d)\n", hdc, nLeftRect, nTopRect, nRightRect, nBottomRect, nWidth, nHeight); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pRoundRect)(sdc.GetHdc(), nLeftRect, nTopRect, nRightRect, nBottomRect, nWidth, nHeight); + sdc.PutPrimaryDC(hdc, TRUE, nLeftRect, nTopRect, nRightRect, nBottomRect); + return ret; + break; + default: + break; + } + } + + ret=(*pRoundRect)(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect, nWidth, nHeight); + if(!ret) OutTraceE("RoundRect ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extPolyPolygon(HDC hdc, const POINT *lpPoints, const INT *lpPolyCounts, int nCount) +{ + BOOL ret; + OutTraceDW("PolyPolygon: hdc=%x\n", hdc); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pPolyPolygon)(sdc.GetHdc(), lpPoints, lpPolyCounts, nCount); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret=(*pPolyPolygon)(hdc, lpPoints, lpPolyCounts, nCount); + if(!ret) OutTraceE("PolyPolygon ERROR: err=%d\n", GetLastError()); + return ret; +} diff --git a/dll/hd3d.cpp b/dll/hd3d.cpp index 308259a..740c81d 100644 --- a/dll/hd3d.cpp +++ b/dll/hd3d.cpp @@ -20,6 +20,8 @@ extern void D3D9TextureHandling(void *, int); extern void D3D8TextureHandling(void *, int); +void *lpD3DActiveDevice = NULL; + typedef HRESULT (WINAPI *QueryInterface_Type)(void *, REFIID riid, void** ppvObj); // D3D8/9 API @@ -212,6 +214,7 @@ typedef HRESULT (WINAPI *SetTexture9_Type)(void *, DWORD, void *); //typedef ULONG (WINAPI *CreateRenderTarget8_Type)(void *, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, BOOL, IDirect3DSurface8**); typedef ULONG (WINAPI *CreateRenderTarget8_Type)(void *, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, BOOL, void**); +typedef ULONG (WINAPI *CreateRenderTarget9_Type)(void *, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, BOOL, void**); typedef ULONG (WINAPI *BeginScene_Type)(void *); typedef ULONG (WINAPI *EndScene_Type)(void *); @@ -250,6 +253,7 @@ BOOL WINAPI voidDisableD3DSpy(void); //ULONG WINAPI extCreateRenderTarget8(void *, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, BOOL, IDirect3DSurface8**); ULONG WINAPI extCreateRenderTarget8(void *, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, BOOL, void**); +ULONG WINAPI extCreateRenderTarget9(void *, UINT, UINT, D3DFORMAT, D3DMULTISAMPLE_TYPE, BOOL, void**); ULONG WINAPI extBeginScene8(void *); ULONG WINAPI extEndScene8(void *); ULONG WINAPI extBeginScene9(void *); @@ -291,6 +295,7 @@ SetGammaRamp_Type pSetGammaRamp = 0; GetGammaRamp_Type pGetGammaRamp = 0; CreateRenderTarget8_Type pCreateRenderTarget8 = 0; +CreateRenderTarget9_Type pCreateRenderTarget9 = 0; BeginScene_Type pBeginScene8 = 0; EndScene_Type pEndScene8 = 0; BeginScene_Type pBeginScene9 = 0; @@ -540,6 +545,7 @@ void HookD3DDevice9(void** ppD3Ddev9) SetHook((void *)(**(DWORD **)ppD3Ddev9 + 124), extUpdateTexture, (void **)&pUpdateTexture, "UpdateTexture(D9)"); #endif + //SetHook((void *)(**(DWORD **)ppD3Ddev9 + 112), extCreateRenderTarget9, (void **)&pCreateRenderTarget9, "CreateRenderTarget(D9)"); SetHook((void *)(**(DWORD **)ppD3Ddev9 + 164), extBeginScene9, (void **)&pBeginScene9, "BeginScene(D9)"); SetHook((void *)(**(DWORD **)ppD3Ddev9 + 168), extEndScene9, (void **)&pEndScene9, "EndScene(D9)"); //SetHook((void *)(**(DWORD **)ppD3Ddev9 +188), extSetViewport, (void **)&pSetViewport, "SetViewport(D9)"); @@ -1153,6 +1159,7 @@ HRESULT WINAPI extCreateDevice(void *lpd3d, UINT adapter, D3DDEVTYPE devicetype, return res; } OutTraceD3D("SUCCESS! device=%x\n", *ppd3dd); + lpD3DActiveDevice = *ppd3dd; if(dwD3DVersion == 8){ HookD3DDevice8(ppd3dd); @@ -1259,6 +1266,7 @@ HRESULT WINAPI extCreateDeviceEx(void *lpd3d, UINT adapter, D3DDEVTYPE devicetyp return res; } OutTraceD3D("SUCCESS!\n"); + lpD3DActiveDevice = *ppd3dd; HookD3DDevice9(ppd3dd); diff --git a/dll/hddraw.h b/dll/hddraw.h index d5fc7aa..2958706 100644 --- a/dll/hddraw.h +++ b/dll/hddraw.h @@ -5,6 +5,7 @@ typedef HRESULT (WINAPI *DirectDrawCreateEx_Type)(GUID *, LPDIRECTDRAW *, REFIID typedef HRESULT (WINAPI *DirectDrawEnumerate_Type)(LPDDENUMCALLBACK, LPVOID); typedef HRESULT (WINAPI *DirectDrawEnumerateEx_Type)(LPDDENUMCALLBACKEX, LPVOID, DWORD); typedef HRESULT (WINAPI *DirectDrawCreateClipper_Type)(DWORD, LPDIRECTDRAWCLIPPER *, IUnknown *); +typedef void (WINAPI *HandleDDThreadLock_Type)(void); typedef HDC (WINAPI *GDIGetDC_Type)(HWND); typedef int (WINAPI *GDIReleaseDC_Type)(HWND, HDC); diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index 65d1af9..3e4fae3 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -9,6 +9,7 @@ //#undef IsTraceDW //#define IsTraceDW TRUE #define LOCKINJECTIONTHREADS +#define TRYFATNAMES TRUE BOOL WINAPI extCheckRemoteDebuggerPresent(HANDLE, PBOOL); LPVOID WINAPI extVirtualAlloc(LPVOID, SIZE_T, DWORD, DWORD); @@ -792,6 +793,7 @@ HANDLE WINAPI extCreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwS DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { HANDLE ret; + int err=0; OutTraceDW("CreateFile: FileName=%s DesiredAccess=%x SharedMode=%x Disposition=%x Flags=%x\n", lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes); @@ -809,8 +811,29 @@ HANDLE WINAPI extCreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwS if(ret && (ret != (HANDLE)INVALID_SET_FILE_POINTER)) OutTrace("CreateFile: ret=%x\n", ret); else - OutTrace("CreateFile ERROR: err=%d\n", GetLastError()); + OutTrace("CreateFile ERROR: err=%d\n", err=GetLastError()); } + +#if 0 + if(TRYFATNAMES && (!ret) && (err==ERROR_FILE_NOT_FOUND)){ + char ShortPath[MAX_PATH+1]; + int iLastBackSlash, iFnameLength; + char *sFileName; + strncpy(ShortPath, lpFileName, MAX_PATH); + iLastBackSlash = -1; + for(size_t i=0; i 8){ + sFileName[6] = '~'; + sFileName[7] = '1'; + strcpy(&sFileName[8], &sFileName[iFnameLength]); + } + OutTrace("CreateFile: try FAT path=\"%s\"\n", ShortPath); + ret=(*pCreateFile)(ShortPath, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + } +#endif + return ret; } diff --git a/dll/msims32.cpp b/dll/msims32.cpp new file mode 100644 index 0000000..5aabbca --- /dev/null +++ b/dll/msims32.cpp @@ -0,0 +1,74 @@ +#define _CRT_SECURE_NO_WARNINGS + +#include "dxwnd.h" +#include "dxwcore.hpp" +#include "syslibs.h" +#include "hddraw.h" +#include "dxhook.h" +#include "dxhelper.h" +#include "shareddc.hpp" + +#include "stdio.h" + +static BOOL bGDIRecursionFlag = FALSE; + +#define _Warn(s) MessageBox(0, s, "to do", MB_ICONEXCLAMATION) + +typedef BOOL (WINAPI *AlphaBlend_Type)(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, BLENDFUNCTION ftn); +AlphaBlend_Type pAlphaBlend = NULL; +BOOL WINAPI extAlphaBlend(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, BLENDFUNCTION ftn); + +typedef BOOL (WINAPI *GradientFill_Type)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG); +GradientFill_Type pGradientFill = NULL; +BOOL WINAPI extGradientFill(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG); + +typedef BOOL (WINAPI *TransparentBlt_Type)(HDC, int, int, int, int, HDC, int, int, int, int, UINT); +TransparentBlt_Type pTransparentBlt = NULL; +BOOL WINAPI extTransparentBlt(HDC, int, int, int, int, HDC, int, int, int, int, UINT); + +static HookEntry_Type Hooks[]={ + + {HOOK_IAT_CANDIDATE, "AlphaBlend", (FARPROC)NULL, (FARPROC *)&pAlphaBlend, (FARPROC)extAlphaBlend}, + {HOOK_IAT_CANDIDATE, "GradientFill", (FARPROC)NULL, (FARPROC *)&pGradientFill, (FARPROC)extGradientFill}, + {HOOK_IAT_CANDIDATE, "TransparentBlt", (FARPROC)NULL, (FARPROC *)&pTransparentBlt, (FARPROC)extTransparentBlt}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static char *libname = "msimg32.dll"; + +void HookMSIMG32Init() +{ + HookLibInit(Hooks); +} + +void HookMSIMG32(HMODULE module) +{ + HookLibrary(module, Hooks, libname); +} + +FARPROC Remap_MSIMG32_ProcAddress(LPCSTR proc, HMODULE hModule) +{ + FARPROC addr; + + if(addr=RemapLibrary(proc, hModule, Hooks)) return addr; + return NULL; +} + +BOOL WINAPI extAlphaBlend(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, BLENDFUNCTION ftn) +{ + _Warn("AlphaBlend"); + return TRUE; +} + +BOOL WINAPI extGradientFill(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode) +{ + _Warn("GradientFill"); + return TRUE; +} + +BOOL WINAPI extTransparentBlt(HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, + HDC hdcSrc, int xoriginSrc, int yoriginSrc, int wSrc, int hSrc, UINT crTransparent) +{ + _Warn("TransparentBlt"); + return TRUE; +} diff --git a/dll/shareddc.cpp b/dll/shareddc.cpp new file mode 100644 index 0000000..eb40911 --- /dev/null +++ b/dll/shareddc.cpp @@ -0,0 +1,461 @@ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include "dxwnd.h" +#include "dxwcore.hpp" +#include "syslibs.h" +#include "dxhelper.h" +#include "resource.h" +#include "hddraw.h" +#include "shareddc.hpp" + +//#define D3D9TRY +#define SHAREDDCDEBUG FALSE +#if SHAREDDCDEBUG +#define _Warn(s) {char cap[80]; sprintf(cap, "Warn at %d", __LINE__); MessageBox(NULL, (s), cap, MB_OK);} +#else +#define _Warn(s) +#endif + + +extern ReleaseDC_Type pReleaseDC; +extern HandleDDThreadLock_Type pReleaseDDThreadLock; +extern GetDC_Type pGetDC; + +/*---------------------------------------------------------------------------------+ +| | +| Constructor, Desctructor | +| | ++---------------------------------------------------------------------------------*/ + +dxwSDC::dxwSDC() +{ + OutTraceB("dxwSDC::dxwSDC: Initialize\n"); + PrimaryDC = NULL; + lpDDSPrimary = NULL; + LastScreenWidth = LastScreenHeight = 0; + LastHDC = NULL; + CurrenthWnd = NULL; +} + +dxwSDC::~dxwSDC() +{ + OutTraceB("dxwSDC::~dxwSDC: Destroy\n"); +} + +/*---------------------------------------------------------------------------------+ +| | +| GetPrimaryDC: builds a suitable DC to write to, according to the input DC | +| | ++---------------------------------------------------------------------------------*/ + +static IDirect3DSurface9 *pDestSurface = NULL; + +HDC dxwSDC::GetPrimaryDC(HDC hdc) +{ + HRESULT res; + extern HandleDDThreadLock_Type pReleaseDDThreadLock; + extern GetDC_Type pGetDC; + extern ReleaseDC_Type pReleaseDC; + extern void *lpD3DActiveDevice; + + OutTraceB("dxwSDC::GetPrimaryDC: hdc=%x\n", hdc); +#ifdef D3D9TRY + if(lpD3DActiveDevice){ + // search for D3D first + //RECT client; + //(*pGetClientRect)(dxw.GethWnd(), &client); + //if(pDestSurface == NULL){ + // //res=((IDirect3DDevice9 *)lpD3DActiveDevice)->CreateOffscreenPlainSurface(ScreenWidth, ScreenHeight, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, &pDestSurface, NULL); + // //res=((IDirect3DDevice9 *)lpD3DActiveDevice)->CreateOffscreenPlainSurface(dxw.GetScreenWidth(), dxw.GetScreenHeight(), D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, &pDestSurface, NULL); + // res=((IDirect3DDevice9 *)lpD3DActiveDevice)->CreateOffscreenPlainSurface(client.right, client.bottom, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, &pDestSurface, NULL); + // if(res){ + // OutTraceE("dxwSDC::CreateOffscreenPlainSurface: ERROR err=%x(%s) at=%d\n", res, ExplainDDError(res), __LINE__); + // return NULL; + // _Warn("CreateOffscreenPlainSurface ERROR"); + // } + //} + //res=((IDirect3DDevice9 *)lpD3DActiveDevice)->GetFrontBufferData(1, pDestSurface); + //if(res){ + // OutTraceE("GetFrontBufferData: ERROR err=%x(%s) at=%d\n", res, ExplainDDError(res), __LINE__); + // _Warn("GetFrontBufferData ERROR"); + //} + IDirect3DSurface9 *pRenderSurface; + res=((IDirect3DDevice9 *)lpD3DActiveDevice)->GetRenderTarget(0, &pRenderSurface); + if(res){ + OutTraceE("d3d9::GetRenderTarget: ERROR err=%x(%s) at=%d\n", res, ExplainDDError(res), __LINE__); + _Warn("d3d9::GetRenderTarget ERROR"); + } + //res=((IDirect3DDevice9 *)lpD3DActiveDevice)->GetRenderTargetData(pRenderSurface, pDestSurface); + //if(res){ + // OutTraceE("d3d9::GetRenderTargetData: ERROR err=%x(%s) at=%d\n", res, ExplainDDError(res), __LINE__); + // _Warn("d3d9::GetRenderTargetData ERROR"); + //} + //res=pDestSurface->GetDC(&PrimaryDC); + res=pRenderSurface->GetDC(&PrimaryDC); + if(res){ + OutTraceE("d3d9::GetDC: ERROR err=%x(%s) at=%d\n", res, ExplainDDError(res), __LINE__); + //_Warn("d3d9::GetDC ERROR"); + VirtualSurfaceType = VIRTUAL_ON_D3D; + return NULL; + } + VirtualSurfaceType = VIRTUAL_ON_D3D; + } + else { +#else + { +#endif + // else look for ddraw + //if(pReleaseDDThreadLock)(*pReleaseDDThreadLock)(); + lpDDSPrimary = dxwss.GetPrimarySurface(); + if (lpDDSPrimary) { + if(pReleaseDDThreadLock)(*pReleaseDDThreadLock)(); + res=((*pGetDC)(lpDDSPrimary, &PrimaryDC)); + while((PrimaryDC == NULL) && lpDDSPrimary) { + OutTraceB("dxwSDC::GetPrimaryDC: found primary surface with no DC, unref lpdds=%x\n", lpDDSPrimary); + dxwss.UnrefSurface(lpDDSPrimary); + lpDDSPrimary = dxwss.GetPrimarySurface(); + if (lpDDSPrimary) (*pGetDC)(lpDDSPrimary, &PrimaryDC); + } + if (!PrimaryDC) { + _Warn("No primary DC"); + OutTraceB("dxwSDC::GetPrimaryDC: no ddraw primary DC\n"); + return NULL; + } + // avoid double Getdc on same hdc and lock + // if(PrimaryDC == hdc) (*pReleaseDC)(lpDDSPrimary, PrimaryDC); + OutTraceB("dxwSDC::GetPrimaryDC: ddraw PrimaryDC=%x\n", PrimaryDC); + VirtualSurfaceType = VIRTUAL_ON_DDRAW; + } + else { + // finally, search GDI DC + PrimaryDC = (*pGDIGetDC)(dxw.GethWnd()); + if (!PrimaryDC) { + _Warn("No window DC"); + OutTraceB("dxwSDC::GetPrimaryDC: no windows DC\n"); + return NULL; + } + OutTraceB("dxwSDC::GetPrimaryDC: gdi PrimaryDC=%x\n", PrimaryDC); + VirtualSurfaceType = VIRTUAL_ON_WINDOW; + } + } + + // whenever the hdc changes, rebuild the virtual DC + if(hdc != LastHDC) do { + LastHDC = hdc; + RECT client; + if(VirtualHDC){ + //(*pGDIReleaseDC)(dxw.GethWnd(), VirtualHDC); + DeleteObject(VirtualHDC); + } + + if(!(VirtualHDC=(*pGDICreateCompatibleDC)(PrimaryDC))){ + OutTraceE("CreateCompatibleDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + _Warn("CreateCompatibleDC ERROR"); + break; + } + + if(!(CurrenthWnd = WindowFromDC(hdc))){ + OutTraceE("dxwSDC::GetPrimaryDC: WindowFromDC ERROR err=%d at=%d\n", GetLastError(), __LINE__); + _Warn("WindowFromDC ERROR"); + break; + } + + if(!(*pGetClientRect)(CurrenthWnd, &client)){ + OutTraceE("dxwSDC::GetPrimaryDC: GetClietError ERROR err=%d at=%d\n", GetLastError(), __LINE__); + _Warn("GetClietError ERROR"); + break; + } + + dxw.UnmapClient(&client); + ScreenWidth = client.right; + ScreenHeight = client.bottom; + + OutTraceB("dxwSDC::GetPrimaryDC: VirtualHDC INITIALIZE size=(%dx%d)\n", LastScreenWidth, LastScreenHeight); + + if(!(VirtualPic=(*pCreateCompatibleBitmap)(PrimaryDC, ScreenWidth, ScreenHeight))){ + OutTraceE("dxwSDC::GetPrimaryDC: CreateCompatibleBitmap ERROR err=%d at=%d\n", GetLastError(), __LINE__); + _Warn("CreateCompatibleBitmap ERROR"); + } + + if(!SelectObject(VirtualHDC, VirtualPic)){ + OutTraceE("dxwSDC::GetPrimaryDC: SelectObject ERROR err=%d at=%d\n", GetLastError(), __LINE__); + _Warn("SelectObject ERROR"); + } + + DeleteObject(VirtualPic); + VirtualPic = 0; + } while(0); + + if(CurrenthWnd && CurrenthWnd!=dxw.GethWnd()){ + POINT zero1 = {0, 0}; + POINT zero2 = {0, 0}; + (*pClientToScreen)(CurrenthWnd, &zero1); + (*pClientToScreen)(dxw.GethWnd(), &zero2); + WinOffset.x = zero1.x - zero2.x; + WinOffset.y = zero1.y - zero2.y; + VirtualOffset = WinOffset; + dxw.UnmapClient(&VirtualOffset); + OutTraceB("dxwSDC::GetPrimaryDC: WinOffset=(%d,%d)->(%d,%d)\n", WinOffset.x, WinOffset.y, VirtualOffset.x, VirtualOffset.y); + } + else { + WinOffset.x = 0; + WinOffset.y = 0; + VirtualOffset.x = 0; + VirtualOffset.y = 0; + OutTraceB("dxwSDC::GetPrimaryDC: same window\n"); + } + + if(PrimaryDC){ + if(!(*pGDIBitBlt)(VirtualHDC, 0, 0, ScreenWidth, ScreenHeight, PrimaryDC, VirtualOffset.x, VirtualOffset.y, SRCCOPY)){ + OutTraceE("dxwSDC::GetPrimaryDC: StretchBlt ERROR err=%d at=%d\n", GetLastError(), __LINE__); + _Warn("StretchBlt ERROR"); + } + OutTraceB("dxwSDC::GetPrimaryDC: fill=(0,0)-(%d,%d) from=(%d,%d)\n", ScreenWidth, ScreenHeight, VirtualOffset.x, VirtualOffset.y); + } + + POINT origin = {}; + POINT mainwin = {}; + GetDCOrgEx(hdc, &origin); + GetDCOrgEx((*pGDIGetDC)(dxw.GethWnd()), &mainwin); + origin.x -= mainwin.x; + origin.y -= mainwin.y; + OutTraceB("dxwSDC::GetPrimaryDC: origin=(%d,%d)\n", origin.x, origin.y); + + copyDcAttributes(VirtualHDC, hdc, origin); + setClippingRegion(VirtualHDC, hdc, origin); + + return VirtualHDC; +} + +/*---------------------------------------------------------------------------------+ +| | +| GetHdc: returns the DC to write for the GDI call | +| | ++---------------------------------------------------------------------------------*/ + +HDC dxwSDC::GetHdc(void) +{ + return VirtualHDC; +} + +/*---------------------------------------------------------------------------------+ +| | +| PutPrimaryDC: transfers the DC content to the primary surface and the screen | +| | ++---------------------------------------------------------------------------------*/ + +BOOL dxwSDC::PutPrimaryDC(HDC hdc, BOOL UpdateScreen, int XDest, int YDest, int nDestWidth, int nDestHeight) +{ + extern ReleaseDC_Type pReleaseDC; + extern Unlock1_Type pUnlock1; + BOOL ret; + HRESULT res; + + ret = TRUE; + if (nDestWidth == 0) nDestWidth=ScreenWidth-XDest; + if (nDestHeight == 0) nDestHeight=ScreenHeight-YDest; + + if (IsDebug){ + char sRect[81]; + if(UpdateScreen) sprintf(sRect, "pos=(%d,%d) size=(%dx%d) winoffset=(%d,%d) virtoffset=(%d,%d)", + XDest, YDest, nDestWidth, nDestHeight, WinOffset.x, WinOffset.y, VirtualOffset.x, VirtualOffset.y); + else strcpy(sRect, ""); + char *sType; + switch(VirtualSurfaceType){ + case VIRTUAL_ON_D3D: sType="D3D"; break; + case VIRTUAL_ON_DDRAW: sType="DDRAW"; break; + case VIRTUAL_ON_WINDOW: sType="WINDOW"; break; + default: sType="???"; break; + } + OutTrace("dxwSDC::PutPrimaryDC: hdc=%x type=%s update=%x %s\n", hdc, sType, UpdateScreen, sRect); + } + + if(UpdateScreen){ + switch(VirtualSurfaceType){ +#ifdef D3D9TRY + case VIRTUAL_ON_D3D: + RECT client; + SetStretchBltMode(PrimaryDC, HALFTONE); + (*pGetClientRect)(dxw.GethWnd(), &client); + if(PrimaryDC) ret=(*pGDIStretchBlt)(PrimaryDC, 0, 0, client.right, client.bottom, VirtualHDC, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), SRCCOPY); + ret=(*pGDIReleaseDC)(dxw.GethWnd(), PrimaryDC); + //ret=(*pGDIReleaseDC)(dxw.GethWnd(), PrimaryDC); + if(!ret) OutTrace("dxwSDC::PutPrimaryDC: ReleaseDC ERROR err=%d\n", GetLastError()); + //pDestSurface->Release(); + break; +#endif + case VIRTUAL_ON_DDRAW: + ret=(*pGDIBitBlt)(PrimaryDC, XDest+VirtualOffset.x, YDest+VirtualOffset.y, nDestWidth, nDestHeight, VirtualHDC, XDest, YDest, SRCCOPY); + if(!ret || (ret==GDI_ERROR)) { + OutTraceE("dxwSDC::PutPrimaryDC: BitBlt ERROR ret=%x err=%d\n", ret, GetLastError()); + } + res=(*pReleaseDC)(lpDDSPrimary, PrimaryDC); + if(res){ + OutTraceE("dxwSDC::PutPrimaryDC: ReleaseDC ERROR res=%x\n", res); + } + dxw.ScreenRefresh(); + break; + case VIRTUAL_ON_WINDOW: + SetStretchBltMode(PrimaryDC, HALFTONE); + RECT RealArea, VirtualArea; + // some fullscreen games ("Imperialism II") blitted from negative coordinates -2,-2 !! + if(XDest < 0) { + nDestWidth += XDest; + XDest=0; + } + if(YDest < 0) { + nDestHeight += YDest; + YDest=0; + } + VirtualArea.left = XDest; + VirtualArea.top = YDest; + VirtualArea.right = nDestWidth; + VirtualArea.bottom = nDestHeight; + RealArea = VirtualArea; + dxw.MapClient(&RealArea); + OffsetRect(&RealArea, WinOffset.x, WinOffset.y); + ret=TRUE; + if(PrimaryDC)ret=(*pGDIStretchBlt)(PrimaryDC, RealArea.left, RealArea.top, RealArea.right, RealArea.bottom, VirtualHDC, VirtualArea.left, VirtualArea.top, VirtualArea.right, VirtualArea.bottom, SRCCOPY); + ret=(*pGDIReleaseDC)(dxw.GethWnd(), PrimaryDC); + break; + } + } + else { + switch(VirtualSurfaceType){ + case VIRTUAL_ON_DDRAW: + res=(*pReleaseDC)(lpDDSPrimary, PrimaryDC); + if(res){ + OutTraceE("dxwSDC::PutPrimaryDC: ReleaseDC ERROR res=%x\n", res); + } + break; + case VIRTUAL_ON_WINDOW: + ret=(*pGDIReleaseDC)(dxw.GethWnd(), PrimaryDC); + if(!ret){ + OutTraceE("dxwSDC::PutPrimaryDC: ReleaseDC ERROR err=%d\n", GetLastError()); + } + break; + } + } + + OutTraceB("dxwSDC::PutPrimaryDC: hdc=%x PrimaryDC=%x ret=%x\n", hdc, PrimaryDC, ret); + return ret; +} + +BOOL dxwSDC::PutPrimaryDC(HDC hdc, BOOL UpdateScreen) +{ + return PutPrimaryDC(hdc, UpdateScreen, 0, 0, LastScreenWidth, LastScreenHeight); +} + +/*---------------------------------------------------------------------------------+ +| | +| Service routines | +| | ++---------------------------------------------------------------------------------*/ + +void dxwSDC::copyDcAttributes(HDC destDC, HDC origDc, POINT origin) +{ + origFont = SelectObject(destDC, GetCurrentObject(origDc, OBJ_FONT)); + origBrush = SelectObject(destDC, GetCurrentObject(origDc, OBJ_BRUSH)); + origPen = SelectObject(destDC, GetCurrentObject(origDc, OBJ_PEN)); + SetArcDirection(destDC, GetArcDirection(origDc)); + SetBkColor(destDC, GetBkColor(origDc)); + SetBkMode(destDC, GetBkMode(origDc)); + SetDCBrushColor(destDC, GetDCBrushColor(origDc)); + SetDCPenColor(destDC, GetDCPenColor(origDc)); + SetPolyFillMode(destDC, GetPolyFillMode(origDc)); + SetROP2(destDC, GetROP2(origDc)); + SetStretchBltMode(destDC, GetStretchBltMode(origDc)); + SetTextAlign(destDC, GetTextAlign(origDc)); + SetTextCharacterExtra(destDC, GetTextCharacterExtra(origDc)); + SetTextColor(destDC, GetTextColor(origDc)); + + OutTrace("copyDcAttributes: orig=(%d,%d)\n", origin.x, origin.y); + if(!(*pSetWindowOrgEx)(destDC, -origin.x, -origin.y, NULL)) + OutTraceE("copyDcAttributes: SetWindowOrgEx ERROR orig=(%d,%d) err=%d\n", origin.x, origin.y, GetLastError()); + + POINT brushOrg = {}; + GetBrushOrgEx(origDc, &brushOrg); + SetBrushOrgEx(destDC, brushOrg.x, brushOrg.y, NULL); + + POINT currentPos = {}; + (*pMoveToEx)(origDc, 0, 0, ¤tPos); + (*pMoveToEx)(origDc, currentPos.x, currentPos.y, NULL); + dxw.MapClient(¤tPos); + (*pMoveToEx)(destDC, currentPos.x, currentPos.y, NULL); +} + +typedef struct +{ + HDC compatDc; + POINT origin; + HWND rootWnd; +} ExcludeClipRectsData_Type; + +static BOOL CALLBACK excludeClipRectsForOverlappingWindows(HWND hwnd, LPARAM lParam) +{ + ExcludeClipRectsData_Type *excludeClipRectsData = (ExcludeClipRectsData_Type *)lParam; + if (hwnd == dxw.GethWnd()) return FALSE; // stop + if (!IsWindowVisible(hwnd)) return TRUE; // go ahead + + RECT rect = {}; + (*pGetWindowRect)(hwnd, &rect); + OffsetRect(&rect, -excludeClipRectsData->origin.x, -excludeClipRectsData->origin.y); + ExcludeClipRect(excludeClipRectsData->compatDc, rect.left, rect.top, rect.right, rect.bottom); + OutTrace("dxwSDC::excludeClipRects: hwnd=%x rect=(%d,%d)-(%d,%d)\n", hwnd, rect.left, rect.top, rect.right, rect.bottom); + return TRUE; +} + +void dxwSDC::setClippingRegion(HDC compatDc, HDC origDc, POINT& origin) +{ + OutTrace("dxwSDC::setClippingRegion: compdc=%x origdc=%x origin=(%d,%d)\n", compatDc, origDc, origin.x, origin.y); + HRGN clipRgn = CreateRectRgn(0, 0, 0, 0); + const bool isEmptyClipRgn = (1 != GetRandomRgn(origDc, clipRgn, SYSRGN)); + OutTrace("dxwSDC::setClippingRegion: isEmptyClipRgn=%x\n", isEmptyClipRgn); + // scale clip region + POINT upleft={0, 0}; + //(*pClientToScreen)(dxw.GethWnd(), &upleft); + (*pClientToScreen)(CurrenthWnd, &upleft); + if(IsDebug){ + OutTrace("dxwSDC::setClippingRegion: upleft=(%d,%d)\n", upleft.x, upleft.y); + } + OffsetRgn(clipRgn, -upleft.x, -upleft.y); + if(IsDebug){ + RECT RgnBox; + GetRgnBox(clipRgn, &RgnBox); + OutTrace("dxwSDC::setClippingRegion: RgnBox=(%d,%d)-(%d,%d) size=(%dx%d)\n", + RgnBox.left, RgnBox.top, RgnBox.right, RgnBox.bottom, RgnBox.right-RgnBox.left, RgnBox.bottom-RgnBox.top); + } + // end of scaling + SelectClipRgn(compatDc, isEmptyClipRgn ? NULL : clipRgn); + DeleteObject(clipRgn); + + HRGN origClipRgn = (*pCreateRectRgn)(0, 0, 0, 0); + if (1 == GetClipRgn(origDc, origClipRgn)) + { + OutTrace("dxwSDC::setClippingRegion: GetClipRgn==1\n"); + OffsetRgn(origClipRgn, origin.x, origin.y); + ExtSelectClipRgn(compatDc, origClipRgn, RGN_AND); + if(IsDebug){ + RECT RgnBox; + GetRgnBox(origClipRgn, &RgnBox); // for logging only + OutTrace("dxwSDC::setClippingRegion: OrigRgnBox=(%d,%d)-(%d,%d)\n", RgnBox.left, RgnBox.top, RgnBox.right, RgnBox.bottom); + } + } + DeleteObject(origClipRgn); + + return; + // to finish ..... + // on Win10 this part seems unnecessary and giving troubles ..... + //dxw.MapClient(&origin); + if (!isEmptyClipRgn) + { + HWND hwnd = WindowFromDC(origDc); + if (hwnd) + { + ExcludeClipRectsData_Type excludeClipRectsData = { compatDc, origin, GetAncestor(hwnd, GA_ROOT) }; + EnumWindows(&excludeClipRectsForOverlappingWindows,(LPARAM)(&excludeClipRectsData)); + } + } +} diff --git a/dll/shareddc.hpp b/dll/shareddc.hpp new file mode 100644 index 0000000..303ca48 --- /dev/null +++ b/dll/shareddc.hpp @@ -0,0 +1,55 @@ +#include +#include "syslibs.h" + +typedef enum { + VIRTUAL_UNDEFINED = 0, + VIRTUAL_ON_WINDOW, + VIRTUAL_ON_DDRAW, + VIRTUAL_ON_D3D, + VIRTUAL_ON_OPENGL, + VIRTUAL_ERROR +} Virtual_type; + +class dxwSDC +{ +// Construction/destruction +public: + dxwSDC(); + virtual ~dxwSDC(); + +// Operations +public: // methods + HDC GetPrimaryDC(HDC); + HDC GetHdc(void); + BOOL PutPrimaryDC(HDC, BOOL, int, int, int, int); + BOOL PutPrimaryDC(HDC, BOOL); + +private: + void copyDcAttributes(HDC, HDC, POINT); + void setClippingRegion(HDC, HDC, POINT&); + + HDC PrimaryDC; + HDC VirtualHDC; + HDC CurrentHDC; + HWND CurrenthWnd; + LPDIRECTDRAWSURFACE lpDDSPrimary; + HBITMAP VirtualPic; + HGDIOBJ origFont; + HGDIOBJ origBrush; + HGDIOBJ origPen; + POINT WinOffset; + POINT VirtualOffset; + int ScreenWidth, ScreenHeight; + int LastScreenWidth, LastScreenHeight; + HDC LastHDC; + Virtual_type VirtualSurfaceType; + struct ExcludeClipRectsData + { + HDC compatDc; + POINT origin; + HWND rootWnd; + }; + +}; + +extern dxwSDC sdc; \ No newline at end of file diff --git a/dll/syslibs.h b/dll/syslibs.h index efd5d5b..3051c58 100644 --- a/dll/syslibs.h +++ b/dll/syslibs.h @@ -38,7 +38,8 @@ typedef BOOL (WINAPI *ImmGetOpenStatus_Type)(HIMC); // GDI32.dll: typedef BOOL (WINAPI *BitBlt_Type)(HDC, int, int, int, int, HDC, int, int, DWORD); typedef HDC (WINAPI *CreateCompatibleDC_Type)(HDC); -typedef HDC (WINAPI *CreateDC_Type)(LPCSTR, LPCSTR, LPCSTR, const DEVMODE *); +typedef HDC (WINAPI *CreateDCA_Type)(LPCSTR, LPCSTR, LPCSTR, const DEVMODE *); +typedef HDC (WINAPI *CreateDCW_Type)(LPWSTR, LPWSTR, LPWSTR, const DEVMODE *); typedef HFONT (WINAPI *CreateFont_Type)(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCTSTR); typedef HFONT (WINAPI *CreateFontIndirect_Type)(const LOGFONT*); typedef HDC (WINAPI *CreateICA_Type)(LPCTSTR, LPCTSTR, LPCTSTR, const DEVMODE *); @@ -69,7 +70,9 @@ typedef BOOL (WINAPI *SetDeviceGammaRamp_Type)(HDC, LPVOID); typedef COLORREF(WINAPI *SetTextColor_Type)(HDC, COLORREF); typedef BOOL (WINAPI *StretchBlt_Type)(HDC, int, int, int, int, HDC, int, int, int, int, DWORD); typedef int (WINAPI *StretchDIBits_Type)(HDC, int, int, int, int, int, int, int, int, const VOID *, const BITMAPINFO *, UINT, DWORD); -typedef BOOL (WINAPI *TextOut_Type)(HDC, int, int, LPCTSTR, int); +typedef BOOL (WINAPI *TextOutA_Type)(HDC, int, int, LPCTSTR, int); +typedef BOOL (WINAPI *TextOutW_Type)(HDC, int, int, LPCWSTR, int); +typedef BOOL (WINAPI *PolyBezier_Type)(HDC, const POINT *, DWORD); typedef BOOL (WINAPI *PolyBezierTo_Type)(HDC, const POINT *, DWORD); typedef BOOL (WINAPI *PolylineTo_Type)(HDC, const POINT *, DWORD); typedef BOOL (WINAPI *PolyDraw_Type)(HDC, const POINT *, const BYTE *, int); @@ -161,8 +164,10 @@ typedef HWND (WINAPI *CreateDialogParam_Type)(HINSTANCE, LPCTSTR, HWND, DLGPROC, typedef HWND (WINAPI *CreateWindowExA_Type)(DWORD, LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); typedef HWND (WINAPI *CreateWindowExW_Type)(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); typedef LRESULT (WINAPI *DefWindowProc_Type)(HWND, UINT, WPARAM, LPARAM); -typedef int (WINAPI *DrawText_Type)(HDC, LPCTSTR, int, LPRECT, UINT); -typedef int (WINAPI *DrawTextEx_Type)(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); +typedef int (WINAPI *DrawTextA_Type)(HDC, LPCTSTR, int, LPRECT, UINT); +typedef int (WINAPI *DrawTextW_Type)(HDC, LPCWSTR, int, LPRECT, UINT); +typedef int (WINAPI *DrawTextExA_Type)(HDC, LPCTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); +typedef int (WINAPI *DrawTextExW_Type)(HDC, LPCWSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); typedef BOOL (WINAPI *EndPaint_Type)(HWND, const PAINTSTRUCT *); typedef LONG (WINAPI *EnumDisplaySettings_Type)(LPCTSTR, DWORD, LPDEVMODEA); typedef int (WINAPI *FillRect_Type)(HDC, const RECT *, HBRUSH); @@ -184,8 +189,10 @@ typedef int (WINAPI *MapWindowPoints_Type)(HWND, HWND, LPPOINT, UINT); typedef BOOL (WINAPI *MoveWindow_Type)(HWND, int, int, int, int, BOOL); typedef BOOL (WINAPI *PeekMessage_Type)(LPMSG, HWND, UINT, UINT, UINT); typedef BOOL (WINAPI *RedrawWindow_Type)(HWND, const RECT *, HRGN, UINT); -typedef ATOM (WINAPI *RegisterClassExA_Type)(WNDCLASSEX *); -typedef ATOM (WINAPI *RegisterClassA_Type)(WNDCLASS *); +typedef ATOM (WINAPI *RegisterClassExA_Type)(WNDCLASSEXA *); +typedef ATOM (WINAPI *RegisterClassA_Type)(WNDCLASSA *); +typedef ATOM (WINAPI *RegisterClassExW_Type)(WNDCLASSEXW *); +typedef ATOM (WINAPI *RegisterClassW_Type)(WNDCLASSW *); typedef int (WINAPI *GDIReleaseDC_Type)(HWND, HDC); typedef BOOL (WINAPI *ScreenToClient_Type)(HWND, LPPOINT); typedef LRESULT (WINAPI *SendMessage_Type)(HWND, UINT, WPARAM, LPARAM); @@ -197,6 +204,7 @@ typedef BOOL (WINAPI *SetWindowPos_Type)(HWND, HWND, int, int, int, int, UINT); typedef int (WINAPI *ShowCursor_Type)(BOOL); typedef BOOL (WINAPI *ShowWindow_Type)(HWND, int); typedef LONG (WINAPI *TabbedTextOutA_Type)(HDC, int, int, LPCTSTR, int, int, const LPINT, int); +typedef LONG (WINAPI *TabbedTextOutW_Type)(HDC, int, int, LPCWSTR, int, int, const LPINT, int); typedef BOOL (WINAPI *DestroyWindow_Type)(HWND); typedef BOOL (WINAPI *CloseWindow_Type)(HWND); typedef BOOL (WINAPI *SetSysColors_Type)(int, const INT *, const COLORREF *); @@ -264,7 +272,8 @@ DXWEXTERN ImmGetOpenStatus_Type pImmGetOpenStatus DXWINITIALIZED; // GDI32.dll: DXWEXTERN BitBlt_Type pGDIBitBlt DXWINITIALIZED; DXWEXTERN CreateCompatibleDC_Type pGDICreateCompatibleDC DXWINITIALIZED; -DXWEXTERN CreateDC_Type pGDICreateDC DXWINITIALIZED; +DXWEXTERN CreateDCA_Type pGDICreateDCA DXWINITIALIZED; +DXWEXTERN CreateDCW_Type pGDICreateDCW DXWINITIALIZED; DXWEXTERN CreateFont_Type pGDICreateFont DXWINITIALIZED; DXWEXTERN CreateFontIndirect_Type pGDICreateFontIndirect DXWINITIALIZED; DXWEXTERN CreateICA_Type pCreateICA DXWINITIALIZED; @@ -295,12 +304,14 @@ DXWEXTERN SetDeviceGammaRamp_Type pGDISetDeviceGammaRamp DXWINITIALIZED; DXWEXTERN SetTextColor_Type pGDISetTextColor DXWINITIALIZED; DXWEXTERN StretchBlt_Type pGDIStretchBlt DXWINITIALIZED; DXWEXTERN StretchDIBits_Type pStretchDIBits DXWINITIALIZED; -DXWEXTERN TextOut_Type pGDITextOutA DXWINITIALIZED; +DXWEXTERN TextOutA_Type pGDITextOutA DXWINITIALIZED; +DXWEXTERN TextOutW_Type pGDITextOutW DXWINITIALIZED; DXWEXTERN LineTo_Type pLineTo DXWINITIALIZED; DXWEXTERN ArcTo_Type pArcTo DXWINITIALIZED; DXWEXTERN MoveToEx_Type pMoveToEx DXWINITIALIZED; DXWEXTERN PolyDraw_Type pPolyDraw DXWINITIALIZED; DXWEXTERN PolylineTo_Type pPolylineTo DXWINITIALIZED; +DXWEXTERN PolyBezier_Type pPolyBezier DXWINITIALIZED; DXWEXTERN PolyBezierTo_Type pPolyBezierTo DXWINITIALIZED; DXWEXTERN SetDIBitsToDevice_Type pSetDIBitsToDevice DXWINITIALIZED; DXWEXTERN CreateCompatibleBitmap_Type pCreateCompatibleBitmap DXWINITIALIZED; @@ -387,8 +398,10 @@ DXWEXTERN CreateWindowExA_Type pCreateWindowExA DXWINITIALIZED; DXWEXTERN CreateWindowExW_Type pCreateWindowExW DXWINITIALIZED; DXWEXTERN DefWindowProc_Type pDefWindowProcA DXWINITIALIZED; DXWEXTERN DefWindowProc_Type pDefWindowProcW DXWINITIALIZED; -DXWEXTERN DrawText_Type pDrawText DXWINITIALIZED; -DXWEXTERN DrawTextEx_Type pDrawTextEx DXWINITIALIZED; +DXWEXTERN DrawTextA_Type pDrawTextA DXWINITIALIZED; +DXWEXTERN DrawTextW_Type pDrawTextW DXWINITIALIZED; +DXWEXTERN DrawTextExA_Type pDrawTextExA DXWINITIALIZED; +DXWEXTERN DrawTextExW_Type pDrawTextExW DXWINITIALIZED; DXWEXTERN EndPaint_Type pEndPaint DXWINITIALIZED; DXWEXTERN EnumDisplaySettings_Type pEnumDisplaySettings DXWINITIALIZED; DXWEXTERN FillRect_Type pFillRect DXWINITIALIZED; @@ -414,6 +427,8 @@ DXWEXTERN PeekMessage_Type pPeekMessage DXWINITIALIZED; DXWEXTERN RedrawWindow_Type pRedrawWindow DXWINITIALIZED; DXWEXTERN RegisterClassExA_Type pRegisterClassExA DXWINITIALIZED; DXWEXTERN RegisterClassA_Type pRegisterClassA DXWINITIALIZED; +DXWEXTERN RegisterClassExW_Type pRegisterClassExW DXWINITIALIZED; +DXWEXTERN RegisterClassW_Type pRegisterClassW DXWINITIALIZED; DXWEXTERN GDIReleaseDC_Type pGDIReleaseDC DXWINITIALIZED; DXWEXTERN ScreenToClient_Type pScreenToClient DXWINITIALIZED; DXWEXTERN SendMessage_Type pSendMessageA DXWINITIALIZED; @@ -427,6 +442,7 @@ DXWEXTERN SetWindowPos_Type pSetWindowPos DXWINITIALIZED; DXWEXTERN ShowCursor_Type pShowCursor DXWINITIALIZED; DXWEXTERN ShowWindow_Type pShowWindow DXWINITIALIZED; DXWEXTERN TabbedTextOutA_Type pTabbedTextOutA DXWINITIALIZED; +DXWEXTERN TabbedTextOutW_Type pTabbedTextOutW DXWINITIALIZED; DXWEXTERN DestroyWindow_Type pDestroyWindow DXWINITIALIZED; DXWEXTERN CloseWindow_Type pCloseWindow DXWINITIALIZED; DXWEXTERN SetSysColors_Type pSetSysColors DXWINITIALIZED; @@ -485,7 +501,8 @@ extern BOOL WINAPI extImmGetOpenStatus(HIMC); extern BOOL WINAPI extGDIBitBlt(HDC, int, int, int, int, HDC, int, int, DWORD); extern HDC WINAPI extGDICreateCompatibleDC(HDC); extern HDC WINAPI extEMUCreateCompatibleDC(HDC); -extern HDC WINAPI extGDICreateDC(LPSTR, LPSTR, LPSTR, CONST DEVMODE *); +extern HDC WINAPI extGDICreateDCA(LPSTR, LPSTR, LPSTR, CONST DEVMODE *); +extern HDC WINAPI extGDICreateDCW(LPWSTR, LPWSTR, LPWSTR, CONST DEVMODE *); extern HFONT WINAPI extCreateFont(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCTSTR); extern HFONT WINAPI extCreateFontIndirect(const LOGFONT*); extern HDC WINAPI extCreateICA(LPCTSTR, LPCTSTR, LPCTSTR, const DEVMODE *); @@ -515,6 +532,8 @@ extern BOOL WINAPI extSetDeviceGammaRamp(HDC, LPVOID); extern BOOL WINAPI extGDIStretchBlt(HDC, int, int, int, int, HDC, int, int, int, int, DWORD); extern int WINAPI extStretchDIBits(HDC, int, int, int, int, int, int, int, int, const VOID *, const BITMAPINFO *, UINT, DWORD); extern BOOL WINAPI extTextOutA(HDC, int, int, LPCTSTR, int); +extern BOOL WINAPI extTextOutW(HDC, int, int, LPCWSTR, int); +extern BOOL WINAPI extPolyBezier(HDC, const POINT *, DWORD); extern BOOL WINAPI extPolyBezierTo(HDC, const POINT *, DWORD); extern BOOL WINAPI extPolylineTo(HDC, const POINT *, DWORD); extern BOOL WINAPI extPolyDraw(HDC, const POINT *, const BYTE *, int); @@ -610,6 +629,8 @@ extern LRESULT WINAPI extDefWindowProcA(HWND, UINT, WPARAM, LPARAM); extern LRESULT WINAPI extDefWindowProcW(HWND, UINT, WPARAM, LPARAM); extern int WINAPI extDrawTextA(HDC, LPCTSTR, int, LPRECT, UINT); extern int WINAPI extDrawTextExA(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); +extern int WINAPI extDrawTextW(HDC, LPCWSTR, int, LPRECT, UINT); +extern int WINAPI extDrawTextExW(HDC, LPCWSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); extern BOOL WINAPI extEndPaint(HWND, const PAINTSTRUCT *); extern LONG WINAPI extEnumDisplaySettings(LPCTSTR, DWORD, DEVMODE *); extern int WINAPI extFillRect(HDC, const RECT *, HBRUSH); @@ -618,7 +639,6 @@ extern BOOL WINAPI extGetClientRect(HWND, LPRECT); extern BOOL WINAPI extGetClipCursor(LPRECT); extern BOOL WINAPI extGetCursorPos(LPPOINT); extern HDC WINAPI extGDIGetDC(HWND); -extern HDC WINAPI extEMUGetDC(HWND); extern HWND WINAPI extGetDesktopWindow(void); extern BOOL WINAPI extGetMonitorInfoA(HMONITOR, LPMONITORINFO); extern BOOL WINAPI extGetMonitorInfoW(HMONITOR, LPMONITORINFO); @@ -636,6 +656,8 @@ extern BOOL WINAPI extPeekMessage(LPMSG, HWND, UINT, UINT, UINT); extern BOOL WINAPI extRedrawWindow(HWND, const RECT *, HRGN, UINT); extern ATOM WINAPI extRegisterClassExA(WNDCLASSEXA *); extern ATOM WINAPI extRegisterClassA(WNDCLASSA *); +extern ATOM WINAPI extRegisterClassExW(WNDCLASSEXW *); +extern ATOM WINAPI extRegisterClassW(WNDCLASSW *); extern int WINAPI extGDIReleaseDC(HWND, HDC); extern BOOL WINAPI extScreenToClient(HWND, LPPOINT); extern LRESULT WINAPI extSendMessageA(HWND, UINT, WPARAM, LPARAM); @@ -649,6 +671,7 @@ extern BOOL WINAPI extSetWindowPos(HWND, HWND, int, int, int, int, UINT); extern int WINAPI extShowCursor(BOOL); extern BOOL WINAPI extShowWindow(HWND, int); extern LONG WINAPI extTabbedTextOutA(HDC, int, int, LPCTSTR, int, int, const LPINT, int); +extern LONG WINAPI extTabbedTextOutW(HDC, int, int, LPCWSTR, int, int, const LPINT, int); extern BOOL WINAPI extDestroyWindow(HWND); extern BOOL WINAPI extCloseWindow(HWND); extern BOOL WINAPI extSetSysColors(int, const INT *, const COLORREF *); @@ -687,3 +710,4 @@ extern void HookGDI32Init(); extern void HookImagehlpInit(); /* eof */ + diff --git a/dll/user32.09.cpp b/dll/user32.09.cpp new file mode 100644 index 0000000..61dc1fe --- /dev/null +++ b/dll/user32.09.cpp @@ -0,0 +1,3302 @@ +#define _WIN32_WINNT 0x0600 +#define WIN32_LEAN_AND_MEAN +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NON_CONFORMING_SWPRINTFS + +#include +#include +#include "dxwnd.h" +#include "dxwcore.hpp" +#include "syslibs.h" +#include "dxhook.h" +#include "hddraw.h" +#include "dxhelper.h" +#include "shareddc.hpp" + +#define FIXCHILDSIZE FALSE + +BOOL IsChangeDisplaySettingsHotPatched = FALSE; +extern BOOL bFlippedDC; +extern HDC hFlippedDC; + +//typedef BOOL (WINAPI *EnumDisplayMonitors_Type)(HDC, LPCRECT, MONITORENUMPROC, LPARAM); +//EnumDisplayMonitors_Type pEnumDisplayMonitors = NULL; +//BOOL WINAPI extEnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM); + +typedef BOOL (WINAPI *BringWindowToTop_Type)(HWND); +BringWindowToTop_Type pBringWindowToTop = NULL; +BOOL WINAPI extBringWindowToTop(HWND); +typedef BOOL (WINAPI *SetForegroundWindow_Type)(HWND); +SetForegroundWindow_Type pSetForegroundWindow = NULL; +BOOL WINAPI extSetForegroundWindow(HWND); +typedef HHOOK (WINAPI *SetWindowsHookEx_Type)(int, HOOKPROC, HINSTANCE, DWORD); +SetWindowsHookEx_Type pSetWindowsHookEx = NULL; +HHOOK WINAPI extSetWindowsHookEx(int, HOOKPROC, HINSTANCE, DWORD); +typedef BOOL (WINAPI *PostMessageA_Type)(HWND, UINT, WPARAM, LPARAM); +PostMessageA_Type pPostMessageA = NULL; +BOOL WINAPI extPostMessageA(HWND, UINT, WPARAM, LPARAM); +typedef HRESULT (WINAPI *MessageBoxTimeoutA_Type)(HWND, LPCSTR, LPCSTR, UINT, WORD, DWORD); +MessageBoxTimeoutA_Type pMessageBoxTimeoutA = NULL; +HRESULT WINAPI extMessageBoxTimeoutA(HWND, LPCSTR, LPCSTR, UINT, WORD, DWORD); +typedef HRESULT (WINAPI *MessageBoxTimeoutW_Type)(HWND, LPCWSTR, LPCWSTR, UINT, WORD, DWORD); +MessageBoxTimeoutW_Type pMessageBoxTimeoutW = NULL; +HRESULT WINAPI extMessageBoxTimeoutW(HWND, LPCWSTR, LPCWSTR, UINT, WORD, DWORD); +typedef BOOL (WINAPI *IsIconic_Type)(HWND); +IsIconic_Type pIsIconic = NULL; +BOOL WINAPI extIsIconic(HWND); +typedef BOOL (WINAPI *IsZoomed_Type)(HWND); +IsZoomed_Type pIsZoomed = NULL; +BOOL WINAPI extIsZoomed(HWND); +typedef HDESK (WINAPI *CreateDesktop_Type)(LPCTSTR, LPCTSTR, DEVMODE *, DWORD, ACCESS_MASK, LPSECURITY_ATTRIBUTES); +CreateDesktop_Type pCreateDesktop = NULL; +HDESK WINAPI extCreateDesktop(LPCTSTR, LPCTSTR, DEVMODE *, DWORD, ACCESS_MASK, LPSECURITY_ATTRIBUTES); +typedef BOOL (WINAPI *SwitchDesktop_Type)(HDESK); +SwitchDesktop_Type pSwitchDesktop = NULL; +BOOL WINAPI extSwitchDesktop(HDESK); +typedef HDESK (WINAPI *OpenDesktop_Type)(LPTSTR, DWORD, BOOL, ACCESS_MASK); +OpenDesktop_Type pOpenDesktop = NULL; +HDESK WINAPI extOpenDesktop(LPTSTR, DWORD, BOOL, ACCESS_MASK); +typedef BOOL (WINAPI *CloseDesktop_Type)(HDESK); +CloseDesktop_Type pCloseDesktop = NULL; +BOOL WINAPI extCloseDesktop(HDESK); +typedef int (WINAPI *ValidateRect_Type)(HWND, const RECT *); +ValidateRect_Type pValidateRect = NULL; +int WINAPI extValidateRect(HWND, const RECT *); +typedef BOOL (WINAPI *ScrollWindow_Type)(HWND, int, int, const RECT *, const RECT *); +ScrollWindow_Type pScrollWindow = NULL; +BOOL extScrollWindow(HWND, int, int, const RECT *, const RECT *); +typedef INT_PTR (WINAPI *DialogBoxParamA_Type)(HINSTANCE, LPCTSTR, HWND, DLGPROC, LPARAM); +DialogBoxParamA_Type pDialogBoxParamA = NULL; +INT_PTR WINAPI extDialogBoxParamA(HINSTANCE, LPCTSTR, HWND, DLGPROC, LPARAM); +typedef HWND (WINAPI *GetParent_Type)(HWND); +GetParent_Type pGetParent = NULL; +HWND WINAPI extGetParent(HWND); +typedef BOOL (WINAPI *InvalidateRgn_Type)(HWND, HRGN, BOOL); +InvalidateRgn_Type pInvalidateRgn = NULL; +BOOL WINAPI extInvalidateRgn(HWND, HRGN, BOOL); +typedef BOOL (WINAPI *InvertRect_Type)(HDC, const RECT *); +InvertRect_Type pInvertRect = NULL; +BOOL WINAPI extInvertRect(HDC, const RECT *); +typedef BOOL (WINAPI *ScrollDC_Type)(HDC, int, int, const RECT *, const RECT *, HRGN, LPRECT); +ScrollDC_Type pScrollDC = NULL; +BOOL WINAPI extScrollDC(HDC, int, int, const RECT *, const RECT *, HRGN, LPRECT); + +#ifdef TRACEPALETTE +typedef UINT (WINAPI *GetDIBColorTable_Type)(HDC, UINT, UINT, RGBQUAD *); +GetDIBColorTable_Type pGetDIBColorTable = NULL; +UINT WINAPI extGetDIBColorTable(HDC, UINT, UINT, RGBQUAD *); +typedef UINT (WINAPI *SetDIBColorTable_Type)(HDC, UINT, UINT, const RGBQUAD *); +SetDIBColorTable_Type pSetDIBColorTable = NULL; +UINT WINAPI extSetDIBColorTable(HDC, UINT, UINT, const RGBQUAD *); +#endif + +static HookEntry_Type Hooks[]={ + {HOOK_IAT_CANDIDATE, "UpdateWindow", (FARPROC)NULL, (FARPROC *)&pUpdateWindow, (FARPROC)extUpdateWindow}, + //{HOOK_IAT_CANDIDATE, "GetWindowPlacement", (FARPROC)NULL, (FARPROC *)&pGetWindowPlacement, (FARPROC)extGetWindowPlacement}, + //{HOOK_IAT_CANDIDATE, "SetWindowPlacement", (FARPROC)NULL, (FARPROC *)&pSetWindowPlacement, (FARPROC)extSetWindowPlacement}, + {HOOK_HOT_CANDIDATE, "ChangeDisplaySettingsA", (FARPROC)ChangeDisplaySettingsA, (FARPROC *)&pChangeDisplaySettingsA, (FARPROC)extChangeDisplaySettingsA}, + {HOOK_HOT_CANDIDATE, "ChangeDisplaySettingsExA", (FARPROC)ChangeDisplaySettingsExA, (FARPROC *)&pChangeDisplaySettingsExA, (FARPROC)extChangeDisplaySettingsExA}, + {HOOK_HOT_CANDIDATE, "ChangeDisplaySettingsW", (FARPROC)NULL, (FARPROC *)&pChangeDisplaySettingsW, (FARPROC)extChangeDisplaySettingsW}, // ref. by Knights of Honor + {HOOK_HOT_CANDIDATE, "ChangeDisplaySettingsExW", (FARPROC)NULL, (FARPROC *)&pChangeDisplaySettingsExW, (FARPROC)extChangeDisplaySettingsExW}, + {HOOK_HOT_CANDIDATE, "GetMonitorInfoA", (FARPROC)GetMonitorInfoA, (FARPROC *)&pGetMonitorInfoA, (FARPROC)extGetMonitorInfoA}, + {HOOK_HOT_CANDIDATE, "GetMonitorInfoW", (FARPROC)GetMonitorInfoW, (FARPROC *)&pGetMonitorInfoW, (FARPROC)extGetMonitorInfoW}, + {HOOK_HOT_CANDIDATE, "ShowCursor", (FARPROC)ShowCursor, (FARPROC *)&pShowCursor, (FARPROC)extShowCursor}, + {HOOK_IAT_CANDIDATE, "CreateDialogIndirectParamA", (FARPROC)CreateDialogIndirectParamA, (FARPROC *)&pCreateDialogIndirectParam, (FARPROC)extCreateDialogIndirectParam}, + {HOOK_IAT_CANDIDATE, "CreateDialogParamA", (FARPROC)CreateDialogParamA, (FARPROC *)&pCreateDialogParam, (FARPROC)extCreateDialogParam}, + {HOOK_IAT_CANDIDATE, "MoveWindow", (FARPROC)MoveWindow, (FARPROC *)&pMoveWindow, (FARPROC)extMoveWindow}, + {HOOK_HOT_CANDIDATE, "EnumDisplaySettingsA", (FARPROC)EnumDisplaySettingsA, (FARPROC *)&pEnumDisplaySettings, (FARPROC)extEnumDisplaySettings}, + {HOOK_IAT_CANDIDATE, "GetClipCursor", (FARPROC)GetClipCursor, (FARPROC*)&pGetClipCursor, (FARPROC)extGetClipCursor}, + {HOOK_IAT_CANDIDATE, "ClipCursor", (FARPROC)ClipCursor, (FARPROC *)&pClipCursor, (FARPROC)extClipCursor}, + {HOOK_IAT_CANDIDATE, "DefWindowProcA", (FARPROC)DefWindowProcA, (FARPROC *)&pDefWindowProcA, (FARPROC)extDefWindowProcA}, + {HOOK_IAT_CANDIDATE, "DefWindowProcW", (FARPROC)DefWindowProcW, (FARPROC *)&pDefWindowProcW, (FARPROC)extDefWindowProcW}, + {HOOK_HOT_CANDIDATE, "CreateWindowExA", (FARPROC)CreateWindowExA, (FARPROC *)&pCreateWindowExA, (FARPROC)extCreateWindowExA}, + {HOOK_HOT_CANDIDATE, "CreateWindowExW", (FARPROC)CreateWindowExW, (FARPROC *)&pCreateWindowExW, (FARPROC)extCreateWindowExW}, + {HOOK_IAT_CANDIDATE, "RegisterClassExA", (FARPROC)RegisterClassExA, (FARPROC *)&pRegisterClassExA, (FARPROC)extRegisterClassExA}, + {HOOK_IAT_CANDIDATE, "RegisterClassA", (FARPROC)RegisterClassA, (FARPROC *)&pRegisterClassA, (FARPROC)extRegisterClassA}, + {HOOK_HOT_CANDIDATE, "GetSystemMetrics", (FARPROC)GetSystemMetrics, (FARPROC *)&pGetSystemMetrics, (FARPROC)extGetSystemMetrics}, + {HOOK_HOT_CANDIDATE, "GetDesktopWindow", (FARPROC)GetDesktopWindow, (FARPROC *)&pGetDesktopWindow, (FARPROC)extGetDesktopWindow}, + {HOOK_IAT_CANDIDATE, "CloseWindow", (FARPROC)NULL, (FARPROC *)&pCloseWindow, (FARPROC)extCloseWindow}, + {HOOK_IAT_CANDIDATE, "DestroyWindow", (FARPROC)NULL, (FARPROC *)&pDestroyWindow, (FARPROC)extDestroyWindow}, + {HOOK_IAT_CANDIDATE, "SetSysColors", (FARPROC)NULL, (FARPROC *)&pSetSysColors, (FARPROC)extSetSysColors}, + {HOOK_IAT_CANDIDATE, "SetCapture", (FARPROC)NULL, (FARPROC *)&pSetCapture, (FARPROC)extSetCapture}, + {HOOK_HOT_CANDIDATE, "SetWindowLongA", (FARPROC)SetWindowLongA, (FARPROC *)&pSetWindowLongA, (FARPROC)extSetWindowLongA}, + {HOOK_HOT_CANDIDATE, "GetWindowLongA", (FARPROC)GetWindowLongA, (FARPROC *)&pGetWindowLongA, (FARPROC)extGetWindowLongA}, + {HOOK_HOT_CANDIDATE, "SetWindowLongW", (FARPROC)SetWindowLongW, (FARPROC *)&pSetWindowLongW, (FARPROC)extSetWindowLongW}, + {HOOK_HOT_CANDIDATE, "GetWindowLongW", (FARPROC)GetWindowLongW, (FARPROC *)&pGetWindowLongW, (FARPROC)extGetWindowLongW}, + {HOOK_IAT_CANDIDATE, "IsWindowVisible", (FARPROC)NULL, (FARPROC *)&pIsWindowVisible, (FARPROC)extIsWindowVisible}, + // hot by MinHook since v2.03.07 + {HOOK_HOT_CANDIDATE, "SystemParametersInfoA", (FARPROC)SystemParametersInfoA, (FARPROC *)&pSystemParametersInfoA, (FARPROC)extSystemParametersInfoA}, + {HOOK_HOT_CANDIDATE, "SystemParametersInfoW", (FARPROC)SystemParametersInfoW, (FARPROC *)&pSystemParametersInfoW, (FARPROC)extSystemParametersInfoW}, + //{HOOK_HOT_CANDIDATE, "GetActiveWindow", (FARPROC)NULL, (FARPROC *)&pGetActiveWindow, (FARPROC)extGetActiveWindow}, + //{HOOK_HOT_CANDIDATE, "GetForegroundWindow", (FARPROC)GetForegroundWindow, (FARPROC *)&pGetForegroundWindow, (FARPROC)extGetForegroundWindow}, + //{HOOK_IAT_CANDIDATE, "GetWindowTextA", (FARPROC)GetWindowTextA, (FARPROC *)&pGetWindowTextA, (FARPROC)extGetWindowTextA}, + //{HOOK_HOT_CANDIDATE, "EnumDisplayMonitors", (FARPROC)EnumDisplayMonitors, (FARPROC *)&pEnumDisplayMonitors, (FARPROC)extEnumDisplayMonitors}, +#ifdef TRACEPALETTE + {HOOK_HOT_CANDIDATE, "GetDIBColorTable", (FARPROC)GetDIBColorTable, (FARPROC *)&pGetDIBColorTable, (FARPROC)extGetDIBColorTable}, + {HOOK_HOT_CANDIDATE, "SetDIBColorTable", (FARPROC)SetDIBColorTable, (FARPROC *)&pSetDIBColorTable, (FARPROC)extSetDIBColorTable}, +#endif + + {HOOK_HOT_CANDIDATE, "BringWindowToTop", (FARPROC)BringWindowToTop, (FARPROC *)&pBringWindowToTop, (FARPROC)extBringWindowToTop}, + {HOOK_HOT_CANDIDATE, "SetForegroundWindow", (FARPROC)SetForegroundWindow, (FARPROC *)&pSetForegroundWindow, (FARPROC)extSetForegroundWindow}, + {HOOK_HOT_CANDIDATE, "ChildWindowFromPoint", (FARPROC)ChildWindowFromPoint, (FARPROC *)&pChildWindowFromPoint, (FARPROC)extChildWindowFromPoint}, + {HOOK_HOT_CANDIDATE, "ChildWindowFromPointEx", (FARPROC)ChildWindowFromPointEx, (FARPROC *)&pChildWindowFromPointEx, (FARPROC)extChildWindowFromPointEx}, + {HOOK_HOT_CANDIDATE, "WindowFromPoint", (FARPROC)WindowFromPoint, (FARPROC *)&pWindowFromPoint, (FARPROC)extWindowFromPoint}, + {HOOK_HOT_CANDIDATE, "SetWindowsHookExA", (FARPROC)SetWindowsHookExA, (FARPROC *)&pSetWindowsHookEx, (FARPROC)extSetWindowsHookEx}, + + //{HOOK_HOT_CANDIDATE, "MessageBoxTimeoutA", (FARPROC)NULL, (FARPROC *)&pMessageBoxTimeoutA, (FARPROC)extMessageBoxTimeoutA}, + //{HOOK_HOT_CANDIDATE, "MessageBoxTimeoutW", (FARPROC)NULL, (FARPROC *)&pMessageBoxTimeoutW, (FARPROC)extMessageBoxTimeoutW}, + + {HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extGDIGetDC}, + {HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)GetDCEx, (FARPROC *)&pGDIGetDCEx, (FARPROC)extGDIGetDCEx}, + {HOOK_IAT_CANDIDATE, "GetWindowDC", (FARPROC)GetWindowDC, (FARPROC *)&pGDIGetWindowDC, (FARPROC)extGDIGetWindowDC}, + {HOOK_IAT_CANDIDATE, "ReleaseDC", (FARPROC)ReleaseDC, (FARPROC *)&pGDIReleaseDC, (FARPROC)extGDIReleaseDC}, + + {HOOK_HOT_CANDIDATE, "BeginPaint", (FARPROC)BeginPaint, (FARPROC *)&pBeginPaint, (FARPROC)extBeginPaint}, + {HOOK_HOT_CANDIDATE, "EndPaint", (FARPROC)EndPaint, (FARPROC *)&pEndPaint, (FARPROC)extEndPaint}, + + {HOOK_IAT_CANDIDATE, "DialogBoxParamA", (FARPROC)NULL, (FARPROC *)&pDialogBoxParamA, (FARPROC)extDialogBoxParamA}, + + //{HOOK_IAT_CANDIDATE, "IsZoomed", (FARPROC)NULL, (FARPROC *)&pIsZoomed, (FARPROC)extIsZoomed}, + //{HOOK_HOT_CANDIDATE, "IsIconic", (FARPROC)IsIconic, (FARPROC *)&pIsIconic, (FARPROC)extIsIconic}, + + {HOOK_HOT_CANDIDATE, "FillRect", (FARPROC)FillRect, (FARPROC *)&pFillRect, (FARPROC)extFillRect}, + {HOOK_IAT_CANDIDATE, "FrameRect", (FARPROC)FrameRect, (FARPROC *)&pFrameRect, (FARPROC)extFrameRect}, + {HOOK_IAT_CANDIDATE, "RedrawWindow", (FARPROC)RedrawWindow, (FARPROC *)&pRedrawWindow, (FARPROC)extRedrawWindow}, + {HOOK_HOT_CANDIDATE, "GetParent", (FARPROC)GetParent, (FARPROC *)&pGetParent, (FARPROC)extGetParent}, + {HOOK_HOT_CANDIDATE, "InvalidateRgn", (FARPROC)InvalidateRgn, (FARPROC *)&pInvalidateRgn, (FARPROC)extInvalidateRgn}, + {HOOK_IAT_CANDIDATE, "TabbedTextOutA", (FARPROC)TabbedTextOutA, (FARPROC *)&pTabbedTextOutA, (FARPROC)extTabbedTextOutA}, + {HOOK_IAT_CANDIDATE, "ScrollDC", (FARPROC)ScrollDC, (FARPROC *)&pScrollDC, (FARPROC)extScrollDC}, + {HOOK_IAT_CANDIDATE, "InvalidateRect", (FARPROC)InvalidateRect, (FARPROC *)&pInvalidateRect, (FARPROC)extInvalidateRect}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type NoGDIHooks[]={ + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type EmulateHooks[]={ + //{HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extGDIGetDC}, + //{HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)GetDCEx, (FARPROC *)&pGDIGetDCEx, (FARPROC)extGDIGetDCEx}, + //{HOOK_IAT_CANDIDATE, "GetWindowDC", (FARPROC)GetWindowDC, (FARPROC *)&pGDIGetWindowDC, (FARPROC)extGDIGetWindowDC}, + //{HOOK_IAT_CANDIDATE, "ReleaseDC", (FARPROC)ReleaseDC, (FARPROC *)&pGDIReleaseDC, (FARPROC)extGDIReleaseDC}, + //{HOOK_IAT_CANDIDATE, "InvalidateRect", (FARPROC)InvalidateRect, (FARPROC *)&pInvalidateRect, (FARPROC)extInvalidateRect}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type ScaledHooks[]={ + {HOOK_IAT_CANDIDATE, "DrawTextA", (FARPROC)DrawTextA, (FARPROC *)&pDrawText, (FARPROC)extDrawTextA}, + {HOOK_IAT_CANDIDATE, "DrawTextExA", (FARPROC)DrawTextExA, (FARPROC *)&pDrawTextEx, (FARPROC)extDrawTextExA}, + {HOOK_HOT_CANDIDATE, "FillRect", (FARPROC)NULL, (FARPROC *)&pFillRect, (FARPROC)extFillRect}, + {HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extGDIGetDC}, + {HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)NULL, (FARPROC *)&pGDIGetDCEx, (FARPROC)extGDIGetDCEx}, + {HOOK_IAT_CANDIDATE, "GetWindowDC", (FARPROC)GetWindowDC, (FARPROC *)&pGDIGetWindowDC, (FARPROC)extGDIGetWindowDC}, + {HOOK_IAT_CANDIDATE, "ReleaseDC", (FARPROC)ReleaseDC, (FARPROC *)&pGDIReleaseDC, (FARPROC)extGDIReleaseDC}, + {HOOK_IAT_CANDIDATE, "ValidateRect", (FARPROC)ValidateRect, (FARPROC *)&pValidateRect, (FARPROC)extValidateRect}, + {HOOK_IAT_CANDIDATE, "ScrollWindow", (FARPROC)ScrollWindow, (FARPROC *)&pScrollWindow, (FARPROC)extScrollWindow}, + + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type RemapHooks[]={ + {HOOK_HOT_CANDIDATE, "ScreenToClient", (FARPROC)ScreenToClient, (FARPROC *)&pScreenToClient, (FARPROC)extScreenToClient}, + {HOOK_HOT_CANDIDATE, "ClientToScreen", (FARPROC)ClientToScreen, (FARPROC *)&pClientToScreen, (FARPROC)extClientToScreen}, + {HOOK_HOT_CANDIDATE, "GetClientRect", (FARPROC)GetClientRect, (FARPROC *)&pGetClientRect, (FARPROC)extGetClientRect}, + {HOOK_HOT_CANDIDATE, "GetWindowRect", (FARPROC)GetWindowRect, (FARPROC *)&pGetWindowRect, (FARPROC)extGetWindowRect}, + {HOOK_HOT_CANDIDATE, "MapWindowPoints", (FARPROC)MapWindowPoints, (FARPROC *)&pMapWindowPoints, (FARPROC)extMapWindowPoints}, + {HOOK_HOT_CANDIDATE, "GetUpdateRgn", (FARPROC)GetUpdateRgn, (FARPROC *)&pGetUpdateRgn, (FARPROC)extGetUpdateRgn}, + //{HOOK_IAT_CANDIDATE, "GetUpdateRect", (FARPROC)GetUpdateRect, (FARPROC *)&pGetUpdateRect, (FARPROC)extGetUpdateRect}, + //{HOOK_IAT_CANDIDATE, "RedrawWindow", (FARPROC)RedrawWindow, (FARPROC *)&pRedrawWindow, (FARPROC)extRedrawWindow}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type PeekAllHooks[]={ + {HOOK_IAT_CANDIDATE, "PeekMessageA", (FARPROC)NULL, (FARPROC *)&pPeekMessage, (FARPROC)extPeekMessage}, + {HOOK_IAT_CANDIDATE, "PeekMessageW", (FARPROC)NULL, (FARPROC *)&pPeekMessage, (FARPROC)extPeekMessage}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type MouseHooks[]={ + {HOOK_HOT_CANDIDATE, "GetCursorPos", (FARPROC)GetCursorPos, (FARPROC *)&pGetCursorPos, (FARPROC)extGetCursorPos}, + {HOOK_HOT_CANDIDATE, "SetCursorPos", (FARPROC)SetCursorPos, (FARPROC *)&pSetCursorPos, (FARPROC)extSetCursorPos}, + {HOOK_IAT_CANDIDATE, "GetCursorInfo", (FARPROC)GetCursorInfo, (FARPROC *)&pGetCursorInfo, (FARPROC)extGetCursorInfo}, + {HOOK_IAT_CANDIDATE, "SetCursor", (FARPROC)SetCursor, (FARPROC *)&pSetCursor, (FARPROC)extSetCursor}, + {HOOK_IAT_CANDIDATE, "SendMessageA", (FARPROC)SendMessageA, (FARPROC *)&pSendMessageA, (FARPROC)extSendMessageA}, + {HOOK_IAT_CANDIDATE, "SendMessageW", (FARPROC)SendMessageW, (FARPROC *)&pSendMessageW, (FARPROC)extSendMessageW}, + //{HOOK_IAT_CANDIDATE, "SetPhysicalCursorPos", NULL, (FARPROC *)&pSetCursor, (FARPROC)extSetCursor}, // ??? + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type WinHooks[]={ + {HOOK_HOT_CANDIDATE, "ShowWindow", (FARPROC)ShowWindow, (FARPROC *)&pShowWindow, (FARPROC)extShowWindow}, + {HOOK_HOT_CANDIDATE, "SetWindowPos", (FARPROC)SetWindowPos, (FARPROC *)&pSetWindowPos, (FARPROC)extSetWindowPos}, + {HOOK_HOT_CANDIDATE, "DeferWindowPos", (FARPROC)DeferWindowPos, (FARPROC *)&pGDIDeferWindowPos, (FARPROC)extDeferWindowPos}, + {HOOK_HOT_CANDIDATE, "CallWindowProcA", (FARPROC)CallWindowProcA, (FARPROC *)&pCallWindowProcA, (FARPROC)extCallWindowProcA}, + {HOOK_HOT_CANDIDATE, "CallWindowProcW", (FARPROC)CallWindowProcW, (FARPROC *)&pCallWindowProcW, (FARPROC)extCallWindowProcW}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type TimeHooks[]={ + {HOOK_IAT_CANDIDATE, "SetTimer", (FARPROC)SetTimer, (FARPROC *)&pSetTimer, (FARPROC)extSetTimer}, + {HOOK_IAT_CANDIDATE, "KillTimer", (FARPROC)KillTimer, (FARPROC *)&pKillTimer, (FARPROC)extKillTimer}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type DesktopHooks[]={ // currently unused, needed for X-Files + {HOOK_IAT_CANDIDATE, "CreateDesktopA", (FARPROC)CreateDesktopA, (FARPROC *)&pCreateDesktop, (FARPROC)extCreateDesktop}, + {HOOK_IAT_CANDIDATE, "SwitchDesktop", (FARPROC)SwitchDesktop, (FARPROC *)&pSwitchDesktop, (FARPROC)extSwitchDesktop}, + {HOOK_IAT_CANDIDATE, "OpenDesktopA", (FARPROC)OpenDesktopA, (FARPROC *)&pOpenDesktop, (FARPROC)extOpenDesktop}, + {HOOK_IAT_CANDIDATE, "CloseDesktop", (FARPROC)CloseDesktop, (FARPROC *)&pCloseDesktop, (FARPROC)extCloseDesktop}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +FARPROC Remap_user32_ProcAddress(LPCSTR proc, HMODULE hModule) +{ + FARPROC addr; + if (addr=RemapLibrary(proc, hModule, Hooks)) return addr; + if (dxw.dwFlags1 & CLIENTREMAPPING) if (addr=RemapLibrary(proc, hModule, RemapHooks)) return addr; + + if (dxw.dwFlags2 & GDISTRETCHED) + if (addr=RemapLibrary(proc, hModule, ScaledHooks)) return addr; + if (dxw.dwFlags3 & GDIEMULATEDC) + if (addr=RemapLibrary(proc, hModule, EmulateHooks)) return addr; + if (!(dxw.dwFlags2 & GDISTRETCHED) && !(dxw.dwFlags3 & GDIEMULATEDC)) + if (addr=RemapLibrary(proc, hModule, NoGDIHooks)) return addr; + if (dxw.dwFlags1 & (PREVENTMAXIMIZE|FIXWINFRAME|LOCKWINPOS|LOCKWINSTYLE)) + if (addr=RemapLibrary(proc, hModule, WinHooks)) return addr; + if ((dxw.dwFlags1 & (MODIFYMOUSE|SLOWDOWN|KEEPCURSORWITHIN)) || (dxw.dwFlags2 & KEEPCURSORFIXED)) + if (addr=RemapLibrary(proc, hModule, MouseHooks)) return addr; + if (dxw.dwFlags3 & PEEKALLMESSAGES) + if (addr=RemapLibrary(proc, hModule, PeekAllHooks)) return addr; + if((dxw.dwFlags2 & TIMESTRETCH) && (dxw.dwFlags4 & STRETCHTIMERS)) + if (addr=RemapLibrary(proc, hModule, TimeHooks)) return addr; + + return NULL; +} + +static char *libname = "user32.dll"; + +void HookUser32(HMODULE hModule) +{ + + HookLibrary(hModule, Hooks, libname); + if (!(dxw.dwFlags2 & GDISTRETCHED) && !(dxw.dwFlags3 & GDIEMULATEDC)) + HookLibrary(hModule, NoGDIHooks, libname); + if (dxw.dwFlags3 & GDIEMULATEDC) HookLibrary(hModule, EmulateHooks, libname); + if (dxw.dwFlags2 & GDISTRETCHED) HookLibrary(hModule, ScaledHooks, libname); + + if (dxw.dwFlags1 & CLIENTREMAPPING) HookLibrary(hModule, RemapHooks, libname); + if (dxw.dwFlags1 & (PREVENTMAXIMIZE|FIXWINFRAME|LOCKWINPOS|LOCKWINSTYLE)) HookLibrary(hModule, WinHooks, libname); + if ((dxw.dwFlags1 & (MODIFYMOUSE|SLOWDOWN|KEEPCURSORWITHIN)) || (dxw.dwFlags2 & KEEPCURSORFIXED)) HookLibrary(hModule, MouseHooks, libname); + if (dxw.dwFlags3 & PEEKALLMESSAGES) HookLibrary(hModule, PeekAllHooks, libname); + if (dxw.dwFlags2 & TIMESTRETCH) HookLibrary(hModule, TimeHooks, libname); + + IsChangeDisplaySettingsHotPatched = IsHotPatched(Hooks, "ChangeDisplaySettingsExA") || IsHotPatched(Hooks, "ChangeDisplaySettingsExW"); + return; +} + +void HookUser32Init() +{ + HookLibInit(Hooks); + HookLibInit(ScaledHooks); + HookLibInit(EmulateHooks); + HookLibInit(RemapHooks); + HookLibInit(MouseHooks); + HookLibInit(WinHooks); +} + +/* ------------------------------------------------------------------------------ */ +// auxiliary (static) functions +/* ------------------------------------------------------------------------------ */ + +static void Stopper(char *s, int line) +{ + char sMsg[81]; + sprintf(sMsg,"break: \"%s\"", s); + MessageBox(0, sMsg, "break", MB_OK | MB_ICONEXCLAMATION); +} + +//#define STOPPER_TEST // comment out to eliminate +#ifdef STOPPER_TEST +#define STOPPER(s) Stopper(s, __LINE__) +#else +#define STOPPER(s) +#endif + +static LPCSTR sTemplateName(LPCSTR tn) +{ + static char sBuf[20+1]; + if((DWORD)tn >> 16) + return tn; + else { + sprintf(sBuf, "ID:(%x)", ((DWORD)tn & 0x0000FFFF)); + return sBuf; + } +} + +// -------------------------------------------------------------------------- +// +// globals, externs, static functions... +// +// -------------------------------------------------------------------------- + +// PrimHDC: DC handle of the selected DirectDraw primary surface. NULL when invalid. +HDC PrimHDC=NULL; + +LPRECT lpClipRegion=NULL; +RECT ClipRegion; +int LastCurPosX, LastCurPosY; + +extern GetDC_Type pGetDC; +extern ReleaseDC_Type pReleaseDC; +//extern void FixWindowFrame(HWND); +extern HRESULT WINAPI sBlt(char *, LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX, BOOL); + +LONG WINAPI MyChangeDisplaySettings(char *fname, BOOL WideChar, void *lpDevMode, DWORD dwflags) +{ + HRESULT res; + DWORD dmFields, dmBitsPerPel, dmPelsWidth, dmPelsHeight; + + if(dwflags & CDS_TEST) { + OutTraceDW("%s: TEST res=DISP_CHANGE_SUCCESSFUL\n", fname); + return DISP_CHANGE_SUCCESSFUL; + } + + // v2.02.32: reset the emulated DC used in GDIEMULATEDC mode + dxw.ResetEmulatedDC(); + + if(lpDevMode){ + if(WideChar){ + dmFields=((DEVMODEW *)lpDevMode)->dmFields; + dmPelsWidth=((DEVMODEW *)lpDevMode)->dmPelsWidth; + dmPelsHeight=((DEVMODEW *)lpDevMode)->dmPelsHeight; + dmBitsPerPel=((DEVMODEW *)lpDevMode)->dmBitsPerPel; + } + else{ + dmFields=((DEVMODEA *)lpDevMode)->dmFields; + dmPelsWidth=((DEVMODEA *)lpDevMode)->dmPelsWidth; + dmPelsHeight=((DEVMODEA *)lpDevMode)->dmPelsHeight; + dmBitsPerPel=((DEVMODEA *)lpDevMode)->dmBitsPerPel; + } + } + + // save desired settings first v.2.1.89 + // v2.1.95 protect when lpDevMode is null (closing game... Jedi Outcast) + // v2.2.23 consider new width/height only when dmFields flags are set. + if(lpDevMode && (dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT))){ + RECT client; + dxw.SetScreenSize(dmPelsWidth, dmPelsHeight); + + // v2.02.31: when main win is bigger that expected resolution, you're in windowed fullscreen mode + //(*pGetClientRect)((dxw.dwFlags1 & FIXPARENTWIN) ? dxw.hParentWnd : dxw.GethWnd(), &client); + (*pGetClientRect)(dxw.GethWnd(), &client); + OutTraceDW("%s: current hWnd=%x size=(%d,%d)\n", fname, dxw.GethWnd(), client.right, client.bottom); + if((client.right>=(LONG)dmPelsWidth) && (client.bottom>=(LONG)dmPelsHeight)) { + OutTraceDW("%s: entering FULLSCREEN mode\n", fname); + dxw.SetFullScreen(TRUE); + } + } + + if ((dwflags==0 || dwflags==CDS_FULLSCREEN) && lpDevMode){ + if (dxw.dwFlags1 & EMULATESURFACE || !(dmFields & DM_BITSPERPEL)){ + OutTraceDW("%s: BYPASS res=DISP_CHANGE_SUCCESSFUL\n", fname); + return DISP_CHANGE_SUCCESSFUL; + } + else{ + DEVMODEA NewMode; + if(dwflags==CDS_FULLSCREEN) dwflags=0; // no FULLSCREEN + (*pEnumDisplaySettings)(NULL, ENUM_CURRENT_SETTINGS, &NewMode); + OutTraceDW("ChangeDisplaySettings: CURRENT wxh=(%dx%d) BitsPerPel=%d -> %d\n", + NewMode.dmPelsWidth, NewMode.dmPelsHeight, NewMode.dmBitsPerPel, dmBitsPerPel); + NewMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + NewMode.dmBitsPerPel = dmBitsPerPel; + res=(*pChangeDisplaySettingsExA)(NULL, &NewMode, NULL, 0, NULL); + if(res) OutTraceE("ChangeDisplaySettings: ERROR err=%d at %d\n", GetLastError(), __LINE__); + return res; + } + } + else{ + if(WideChar) + return (*pChangeDisplaySettingsExW)(NULL, (LPDEVMODEW)lpDevMode, NULL, dwflags, NULL); + else + return (*pChangeDisplaySettingsExA)(NULL, (LPDEVMODEA)lpDevMode, NULL, dwflags, NULL); + } +} + +void dxwFixWindowPos(char *ApiName, HWND hwnd, LPARAM lParam) +{ + LPWINDOWPOS wp; + int MaxX, MaxY; + wp = (LPWINDOWPOS)lParam; + MaxX = dxw.iSizX; + MaxY = dxw.iSizY; + if (!MaxX) MaxX = dxw.GetScreenWidth(); + if (!MaxY) MaxY = dxw.GetScreenHeight(); + static int iLastCX, iLastCY; + static int BorderX=-1; + static int BorderY=-1; + int cx, cy; + extern void CalculateWindowPos(HWND, DWORD, DWORD, LPWINDOWPOS); + + OutTraceDW("%s: GOT hwnd=%x pos=(%d,%d) dim=(%d,%d) Flags=%x(%s)\n", + ApiName, hwnd, wp->x, wp->y, wp->cx, wp->cy, wp->flags, ExplainWPFlags(wp->flags)); + + if (dxw.dwFlags1 & PREVENTMAXIMIZE){ + int UpdFlag = 0; + WINDOWPOS MaxPos; + CalculateWindowPos(hwnd, MaxX, MaxY, &MaxPos); + + if(wp->cx>MaxPos.cx) { wp->cx=MaxPos.cx; UpdFlag=1; } + if(wp->cy>MaxPos.cy) { wp->cy=MaxPos.cy; UpdFlag=1; } + if (UpdFlag) + OutTraceDW("%s: SET max dim=(%d,%d)\n", ApiName, wp->cx, wp->cy); + } + + if ((wp->flags & (SWP_NOMOVE|SWP_NOSIZE))==(SWP_NOMOVE|SWP_NOSIZE)) return; //v2.02.13 + + if ((dxw.dwFlags1 & LOCKWINPOS) && dxw.IsFullScreen() && (hwnd==dxw.GethWnd())){ + CalculateWindowPos(hwnd, MaxX, MaxY, wp); + OutTraceDW("%s: LOCK pos=(%d,%d) dim=(%d,%d)\n", ApiName, wp->x, wp->y, wp->cx, wp->cy); + } + + if ((dxw.dwFlags2 & KEEPASPECTRATIO) && dxw.IsFullScreen() && (hwnd==dxw.GethWnd())){ + // note: while keeping aspect ration, resizing from one corner doesn't tell + // which coordinate is prevalent to the other. We made an arbitrary choice. + // note: v2.1.93: compensation must refer to the client area, not the wp + // window dimensions that include the window borders. + if(BorderX==-1){ + // v2.02.92: Fixed for AERO mode, where GetWindowRect substantially LIES! + RECT client, full; + LONG dwStyle, dwExStyle; + HMENU hMenu; + extern GetWindowLong_Type pGetWindowLongA; + (*pGetClientRect)(hwnd, &client); + full=client; + dwStyle=(*pGetWindowLongA)(hwnd, GWL_STYLE); + dwExStyle=(*pGetWindowLongA)(hwnd, GWL_EXSTYLE); + hMenu = (dwStyle & WS_CHILD) ? NULL : GetMenu(hwnd); + AdjustWindowRectEx(&full, dwStyle, (hMenu!=NULL), dwExStyle); + if (hMenu && (hMenu != (HMENU)-1)) __try {CloseHandle(hMenu);} __except(EXCEPTION_EXECUTE_HANDLER){}; + BorderX= full.right - full.left - client.right; + BorderY= full.bottom - full.top - client.bottom; + OutTraceDW("%s: KEEPASPECTRATIO window borders=(%d,%d)\n", ApiName, BorderX, BorderY); + } + extern LRESULT LastCursorPos; + switch (LastCursorPos){ + case HTBOTTOM: + case HTTOP: + case HTBOTTOMLEFT: + case HTBOTTOMRIGHT: + case HTTOPLEFT: + case HTTOPRIGHT: + cx = BorderX + ((wp->cy - BorderY) * dxw.iRatioX) / dxw.iRatioY; + if(cx!=wp->cx){ + OutTraceDW("%s: KEEPASPECTRATIO adjusted cx=%d->%d\n", ApiName, wp->cx, cx); + wp->cx = cx; + } + break; + case HTLEFT: + case HTRIGHT: + cy = BorderY + ((wp->cx - BorderX) * dxw.iRatioY) / dxw.iRatioX; + if(cy!=wp->cy){ + OutTraceDW("%s: KEEPASPECTRATIO adjusted cy=%d->%d\n", ApiName, wp->cy, cy); + wp->cy = cy; + } + break; + } + } + + if ((dxw.dwFlags5 & CENTERTOWIN) && dxw.IsFullScreen() && (hwnd==dxw.GethWnd())){ + RECT wrect; + LONG dwStyle, dwExStyle; + HMENU hMenu; + int minx, miny; + wrect = dxw.GetScreenRect(); + dwStyle=(*pGetWindowLongA)(hwnd, GWL_STYLE); + dwExStyle=(*pGetWindowLongA)(hwnd, GWL_EXSTYLE); + hMenu = (dwStyle & WS_CHILD) ? NULL : GetMenu(hwnd); + AdjustWindowRectEx(&wrect, dwStyle, (hMenu!=NULL), dwExStyle); + minx = wrect.right - wrect.left; + miny = wrect.bottom - wrect.top; + if(wp->cx < minx) wp->cx = minx; + if(wp->cy < miny) wp->cy = miny; + } + + iLastCX= wp->cx; + iLastCY= wp->cy; +} + +void dxwFixMinMaxInfo(char *ApiName, HWND hwnd, LPARAM lParam) +{ + if (dxw.dwFlags1 & PREVENTMAXIMIZE){ + LPMINMAXINFO lpmmi; + lpmmi=(LPMINMAXINFO)lParam; + OutTraceDW("%s: GOT MaxPosition=(%d,%d) MaxSize=(%d,%d)\n", ApiName, + lpmmi->ptMaxPosition.x, lpmmi->ptMaxPosition.y, lpmmi->ptMaxSize.x, lpmmi->ptMaxSize.y); + lpmmi->ptMaxPosition.x=0; + lpmmi->ptMaxPosition.y=0; + lpmmi->ptMaxSize.x = dxw.GetScreenWidth(); + lpmmi->ptMaxSize.y = dxw.GetScreenHeight(); + + OutTraceDW("%s: SET PREVENTMAXIMIZE MaxPosition=(%d,%d) MaxSize=(%d,%d)\n", ApiName, + lpmmi->ptMaxPosition.x, lpmmi->ptMaxPosition.y, lpmmi->ptMaxSize.x, lpmmi->ptMaxSize.y); + } + + // v2.1.75: added logic to fix win coordinates to selected ones. + // fixes the problem with "Achtung Spitfire", that can't be managed through PREVENTMAXIMIZE flag. + if (dxw.dwFlags1 & LOCKWINPOS){ + LPMINMAXINFO lpmmi; + lpmmi=(LPMINMAXINFO)lParam; + OutTraceDW("%s: GOT MaxPosition=(%d,%d) MaxSize=(%d,%d)\n", ApiName, + lpmmi->ptMaxPosition.x, lpmmi->ptMaxPosition.y, lpmmi->ptMaxSize.x, lpmmi->ptMaxSize.y); + lpmmi->ptMaxPosition.x=dxw.iPosX; + lpmmi->ptMaxPosition.y=dxw.iPosY; + lpmmi->ptMaxSize.x = dxw.iSizX ? dxw.iSizX : dxw.GetScreenWidth(); + lpmmi->ptMaxSize.y = dxw.iSizY ? dxw.iSizY : dxw.GetScreenHeight(); + OutTraceDW("%s: SET LOCKWINPOS MaxPosition=(%d,%d) MaxSize=(%d,%d)\n", ApiName, + lpmmi->ptMaxPosition.x, lpmmi->ptMaxPosition.y, lpmmi->ptMaxSize.x, lpmmi->ptMaxSize.y); + } +} + +static LRESULT WINAPI FixWindowProc(char *ApiName, HWND hwnd, UINT Msg, WPARAM wParam, LPARAM *lpParam) +{ + LPARAM lParam; + + lParam=*lpParam; + OutTraceW("%s: hwnd=%x msg=[0x%x]%s(%x,%x)\n", + ApiName, hwnd, Msg, ExplainWinMessage(Msg), wParam, lParam); + + switch(Msg){ + case WM_NCHITTEST: + // v2.02.71 fix: when processing WM_NCHITTEST messages whith fixed coordinates avoid calling + // the *pDefWindowProc call + // fixes "Microsoft Motocross Madness" mouse handling + if((dxw.dwFlags2 & FIXNCHITTEST) && (dxw.dwFlags1 & MODIFYMOUSE)){ // mouse processing + OutTraceDW("%s: suppress WM_NCHITTEST\n", ApiName); + return TRUE; + } + break; + case WM_ERASEBKGND: + OutTraceDW("%s: prevent erase background\n", ApiName); + return TRUE; // 1=erased + break; // useless + case WM_GETMINMAXINFO: + dxwFixMinMaxInfo(ApiName, hwnd, lParam); + break; + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + dxwFixWindowPos(ApiName, hwnd, lParam); + break; + case WM_STYLECHANGING: + case WM_STYLECHANGED: + dxw.FixStyle(ApiName, hwnd, wParam, lParam); + break; + case WM_SIZE: + if ((dxw.dwFlags1 & LOCKWINPOS) && dxw.IsFullScreen()) return 0; + if (dxw.dwFlags1 & PREVENTMAXIMIZE){ + if ((wParam == SIZE_MAXIMIZED)||(wParam == SIZE_MAXSHOW)){ + OutTraceDW("%s: prevent screen SIZE to fullscreen wparam=%d(%s) size=(%d,%d)\n", ApiName, + wParam, ExplainResizing(wParam), HIWORD(lParam), LOWORD(lParam)); + return 0; // checked + //lParam = MAKELPARAM(dxw.GetScreenWidth(), dxw.GetScreenHeight()); + //OutTraceDW("%s: updated SIZE wparam=%d(%s) size=(%d,%d)\n", ApiName, + // wParam, ExplainResizing(wParam), HIWORD(lParam), LOWORD(lParam)); + } + } + break; + default: + break; + } + + // marker to run hooked function + return(-1); +} + +// -------------------------------------------------------------------------- +// +// user32 API hookers +// +// -------------------------------------------------------------------------- + + +BOOL WINAPI extInvalidateRect(HWND hwnd, RECT *lpRect, BOOL bErase) +{ + if(IsTraceDW){ + char sRect[81]; + if(lpRect) sprintf(sRect, "(%d,%d)-(%d,%d)", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + else strcpy(sRect, "NULL"); + OutTrace("InvalidateRect: hwnd=%x rect=%s erase=%x\n", hwnd, sRect, bErase); + } + + if(dxw.IsFullScreen()) { + if(dxw.dwFlags6 & SHAREDDC){ // Deadlock 2 + if(lpRect) dxw.MapClient(lpRect); + return (*pInvalidateRect)(hwnd, lpRect, bErase); + } + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + case GDIMODE_SHAREDDC: + if(lpRect) dxw.MapClient(lpRect); + break; + case GDIMODE_EMULATED: + default: + break; + } + } + + return (*pInvalidateRect)(hwnd, lpRect, bErase); +} + +BOOL WINAPI extShowWindow(HWND hwnd, int nCmdShow) +{ + BOOL res; + + OutTraceDW("ShowWindow: hwnd=%x, CmdShow=%x(%s)\n", hwnd, nCmdShow, ExplainShowCmd(nCmdShow)); + if (dxw.dwFlags1 & PREVENTMAXIMIZE){ + if(nCmdShow==SW_MAXIMIZE){ + OutTraceDW("ShowWindow: suppress SW_MAXIMIZE maximize\n"); + nCmdShow=SW_SHOWNORMAL; + } + if(nCmdShow==SW_SHOWDEFAULT){ + STARTUPINFO StartupInfo; + GetStartupInfo(&StartupInfo); + OutTraceDW("DEBUG: StartupInfo dwFlags=%x ShowWindow=%x\n", StartupInfo.dwFlags, StartupInfo.wShowWindow); + if((StartupInfo.dwFlags & STARTF_USESHOWWINDOW) && (StartupInfo.wShowWindow == SW_MAXIMIZE)){ + OutTraceDW("ShowWindow: suppress SW_SHOWDEFAULT maximize\n"); + nCmdShow=SW_SHOWNORMAL; + } + } + } + + res=(*pShowWindow)(hwnd, nCmdShow); + OutTraceDW("ShowWindow: res=%x\n", res); + + return res; +} + +LONG WINAPI extGetWindowLong(GetWindowLong_Type pGetWindowLong, char *ApiName, HWND hwnd, int nIndex) +{ + LONG res; + + res=(*pGetWindowLong)(hwnd, nIndex); + + OutTraceB("%s: hwnd=%x, Index=%x(%s) res=%x\n", ApiName, hwnd, nIndex, ExplainSetWindowIndex(nIndex), res); + + if((nIndex==GWL_WNDPROC)||(nIndex==DWL_DLGPROC)){ + WNDPROC wp; + wp=dxwws.GetProc(hwnd); + OutTraceDW("%s: remapping WindowProc res=%x -> %x\n", ApiName, res, (LONG)wp); + if(wp) res=(LONG)wp; // if not found, don't alter the value. + } + + return res; +} + +LONG WINAPI extGetWindowLongA(HWND hwnd, int nIndex) +{ + return extGetWindowLong(pGetWindowLongA, "GetWindowLongA", hwnd, nIndex); +} + +LONG WINAPI extGetWindowLongW(HWND hwnd, int nIndex) +{ + return extGetWindowLong(pGetWindowLongW, "GetWindowLongW", hwnd, nIndex); +} + +LONG WINAPI extSetWindowLong(HWND hwnd, int nIndex, LONG dwNewLong, SetWindowLong_Type pSetWindowLong) +{ + LONG res; + + OutTraceDW("SetWindowLong: hwnd=%x, Index=%x(%s) Val=%x\n", + hwnd, nIndex, ExplainSetWindowIndex(nIndex), dwNewLong); + + if (dxw.Windowize){ + if(dxw.dwFlags1 & LOCKWINSTYLE){ + if(nIndex==GWL_STYLE){ + OutTraceDW("SetWindowLong: Lock GWL_STYLE=%x\n", dwNewLong); + return (*pGetWindowLongA)(hwnd, nIndex); + } + if(nIndex==GWL_EXSTYLE){ + OutTraceDW("SetWindowLong: Lock GWL_EXSTYLE=%x\n", dwNewLong); + return (*pGetWindowLongA)(hwnd, nIndex); + } + } + + if (dxw.dwFlags1 & PREVENTMAXIMIZE){ + if(nIndex==GWL_STYLE){ + dwNewLong &= ~WS_MAXIMIZE; + if(dxw.IsDesktop(hwnd)){ + OutTraceDW("SetWindowLong: GWL_STYLE %x suppress MAXIMIZE\n", dwNewLong); + dwNewLong |= WS_OVERLAPPEDWINDOW; + dwNewLong &= ~(WS_DLGFRAME|WS_MAXIMIZE|WS_VSCROLL|WS_HSCROLL|WS_CLIPSIBLINGS); + } + } + // v2.02.32: disable topmost for main window only + if(dxw.IsDesktop(hwnd) && (nIndex==GWL_EXSTYLE)){ + OutTraceDW("SetWindowLong: GWL_EXSTYLE %x suppress TOPMOST\n", dwNewLong); + dwNewLong = dwNewLong & ~(WS_EX_TOPMOST); + } + } + + if (dxw.dwFlags1 & FIXWINFRAME){ + //if((nIndex==GWL_STYLE) && !(dwNewLong & WS_CHILD)){ + if((nIndex==GWL_STYLE) && !(dwNewLong & WS_CHILD) && dxw.IsDesktop(hwnd)){ + OutTraceDW("SetWindowLong: GWL_STYLE %x force OVERLAPPEDWINDOW\n", dwNewLong); + dwNewLong |= WS_OVERLAPPEDWINDOW; + dwNewLong &= ~WS_CLIPSIBLINGS; + } + } + } + + if (((nIndex==GWL_WNDPROC)||(nIndex==DWL_DLGPROC)) && + dxw.IsFullScreen() && // v2.02.51 - see A10 Cuba.... + !(dxw.dwFlags6 & NOWINDOWHOOKS)){ // v2.03.41 - debug flag + WNDPROC lres; + WNDPROC OldProc; + // GPL fix + if(dxw.IsRealDesktop(hwnd) && dxw.Windowize) { + hwnd=dxw.GethWnd(); + OutTraceDW("SetWindowLong: DESKTOP hwnd, FIXING hwnd=%x\n",hwnd); + } + // end of GPL fix + + OldProc = (WNDPROC)(*pGetWindowLongA)(hwnd, nIndex); + // v2.02.70 fix + if((OldProc==extWindowProc) || + (OldProc==extChildWindowProc)|| + (OldProc==extDialogWindowProc)) + OldProc=dxwws.GetProc(hwnd); + dxwws.PutProc(hwnd, (WNDPROC)dwNewLong); + res=(LONG)OldProc; + SetLastError(0); + lres=(WNDPROC)(*pSetWindowLongA)(hwnd, nIndex, (LONG)extWindowProc); + if(!lres && GetLastError())OutTraceE("SetWindowLong: ERROR err=%d at %d\n", GetLastError(), __LINE__); + } + else { + res=(*pSetWindowLongA)(hwnd, nIndex, dwNewLong); + } + + OutTraceDW("SetWindowLong: hwnd=%x, nIndex=%x, Val=%x, res=%x\n", hwnd, nIndex, dwNewLong, res); + return res; +} + +LONG WINAPI extSetWindowLongA(HWND hwnd, int nIndex, LONG dwNewLong) +{ + return extSetWindowLong(hwnd, nIndex, dwNewLong, pSetWindowLongA); +} + +LONG WINAPI extSetWindowLongW(HWND hwnd, int nIndex, LONG dwNewLong) +{ + return extSetWindowLong(hwnd, nIndex, dwNewLong, pSetWindowLongW); +} + +BOOL WINAPI extSetWindowPos(HWND hwnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags) +{ + BOOL res; + + OutTraceDW("SetWindowPos: hwnd=%x%s pos=(%d,%d) dim=(%d,%d) Flags=%x\n", + hwnd, dxw.IsFullScreen()?"(FULLSCREEN)":"", X, Y, cx, cy, uFlags); + + // when not in fullscreen mode, just proxy the call + if (!dxw.IsFullScreen()){ + res=(*pSetWindowPos)(hwnd, hWndInsertAfter, X, Y, cx, cy, uFlags); + if(!res)OutTraceE("SetWindowPos: ERROR err=%d at %d\n", GetLastError(), __LINE__); + return res; + } + + // in fullscreen, but a child window inside ..... + if (!dxw.IsDesktop(hwnd)){ + RECT r; + r.left = X; + r.right = X + cx; + r.top = Y; + r.bottom = Y + cy; + if ((*pGetWindowLongA)(hwnd, GWL_STYLE) & WS_CHILD){ + r = dxw.MapClientRect(&r); + } + else { + //r = dxw.MapWindowRect(&r); + } + X = r.left; + Y = r.top; + cx = r.right - r.left; + cy = r.bottom - r.top; + + res=(*pSetWindowPos)(hwnd, hWndInsertAfter, X, Y, cx, cy, uFlags); + if(!res)OutTraceE("SetWindowPos: ERROR err=%d at %d\n", GetLastError(), __LINE__); + + //HFONT hFont; + //hFont=CreateFont ( + // 30, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, + // FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + // DEFAULT_PITCH | FF_SWISS, NULL); // "Arial"); + //SendMessage (hwnd, WM_SETFONT, WPARAM (hFont), TRUE); + + return res; + } + + if (dxw.dwFlags1 & LOCKWINPOS){ + // Note: any attempt to change the window position, no matter where and how, through the + // SetWindowPos API is causing resizing to the default 1:1 pixed size in Commandos. + // in such cases, there is incompatibility between LOCKWINPOS and LOCKWINSTYLE. + OutTraceDW("SetWindowPos: locked position\n"); + return 1; + } + + if (dxw.dwFlags1 & PREVENTMAXIMIZE){ + int UpdFlag =0; + int MaxX, MaxY; + MaxX = dxw.iSizX; + MaxY = dxw.iSizY; + if (!MaxX) MaxX = dxw.GetScreenWidth(); + if (!MaxY) MaxY = dxw.GetScreenHeight(); + if(cx>MaxX) { cx=MaxX; UpdFlag=1; } + if(cy>MaxY) { cy=MaxY; UpdFlag=1; } + if (UpdFlag) + OutTraceDW("SetWindowPos: using max dim=(%d,%d)\n", cx, cy); + } + + // useful??? to be demonstrated.... + // when altering main window in fullscreen mode, fix the coordinates for borders + DWORD dwCurStyle, dwExStyle; + HMENU hMenu; + RECT rect; + rect.top=rect.left=0; + rect.right=cx; rect.bottom=cy; + dwCurStyle=(*pGetWindowLongA)(hwnd, GWL_STYLE); + dwExStyle=(*pGetWindowLongA)(hwnd, GWL_EXSTYLE); + // BEWARE: from MSDN - If the window is a child window, the return value is undefined. + hMenu = (dwCurStyle & WS_CHILD) ? NULL : GetMenu(hwnd); + AdjustWindowRectEx(&rect, dwCurStyle, (hMenu!=NULL), dwExStyle); + if (hMenu && (hMenu != (HMENU)-1)) __try {CloseHandle(hMenu);} __except(EXCEPTION_EXECUTE_HANDLER){}; + cx=rect.right; cy=rect.bottom; + OutTraceDW("SetWindowPos: main form hwnd=%x fixed size=(%d,%d)\n", hwnd, cx, cy); + + res=(*pSetWindowPos)(hwnd, hWndInsertAfter, X, Y, cx, cy, uFlags); + if(!res)OutTraceE("SetWindowPos: ERROR err=%d at %d\n", GetLastError(), __LINE__); + return res; +} + +HDWP WINAPI extDeferWindowPos(HDWP hWinPosInfo, HWND hwnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags) +{ + // v2.02.31: heavily used by "Imperialism II" !!! + HDWP res; + + OutTraceDW("DeferWindowPos: hwnd=%x%s pos=(%d,%d) dim=(%d,%d) Flags=%x\n", + hwnd, dxw.IsFullScreen()?"(FULLSCREEN)":"", X, Y, cx, cy, uFlags); + + if(dxw.IsFullScreen()){ + dxw.MapClient(&X, &Y, &cx, &cy); + OutTraceDW("DeferWindowPos: remapped pos=(%d,%d) dim=(%d,%d)\n", X, Y, cx, cy); + } + + res=(*pGDIDeferWindowPos)(hWinPosInfo, hwnd, hWndInsertAfter, X, Y, cx, cy, uFlags); + if(!res)OutTraceE("DeferWindowPos: ERROR err=%d at %d\n", GetLastError(), __LINE__); + return res; +} + +LRESULT WINAPI extSendMessage(char *apiname, SendMessage_Type pSendMessage, HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT ret; + OutTraceW("%s: hwnd=%x WinMsg=[0x%x]%s(%x,%x)\n", + apiname, hwnd, Msg, ExplainWinMessage(Msg), wParam, lParam); + + if(dxw.dwFlags1 & MODIFYMOUSE){ + switch (Msg){ + case WM_MOUSEMOVE: + case WM_MOUSEWHEEL: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDBLCLK: + // revert here the WindowProc mouse correction + POINT prev, curr; + RECT rect; + prev.x = LOWORD(lParam); + prev.y = HIWORD(lParam); + (*pGetClientRect)(dxw.GethWnd(), &rect); + curr.x = (prev.x * rect.right) / dxw.GetScreenWidth(); + curr.y = (prev.y * rect.bottom) / dxw.GetScreenHeight(); + if (Msg == WM_MOUSEWHEEL){ // v2.02.33 mousewheel fix + POINT upleft={0,0}; + (*pClientToScreen)(dxw.GethWnd(), &upleft); + curr = dxw.AddCoordinates(curr, upleft); + } + lParam = MAKELPARAM(curr.x, curr.y); + OutTraceC("%s: hwnd=%x pos XY=(%d,%d)->(%d,%d)\n", apiname, hwnd, prev.x, prev.y, curr.x, curr.y); + break; + default: + break; + } + } + ret=(*pSendMessage)(hwnd, Msg, wParam, lParam); + OutTraceW("%s: lresult=%x\n", apiname, ret); + return ret; +} + +LRESULT WINAPI extSendMessageA(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + return extSendMessage("SendMessageA", pSendMessageA, hwnd, Msg, wParam, lParam); +} + +LRESULT WINAPI extSendMessageW(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + return extSendMessage("SendMessageW", pSendMessageW, hwnd, Msg, wParam, lParam); +} + +HCURSOR WINAPI extSetCursor(HCURSOR hCursor) +{ + HCURSOR ret; + + ret=(*pSetCursor)(hCursor); + OutTraceDW("GDI.SetCursor: Cursor=%x, ret=%x\n", hCursor, ret); + //MessageBox(0, "SelectPalette", "GDI32.dll", MB_OK | MB_ICONEXCLAMATION); + return ret; +} + +BOOL WINAPI extGetCursorPos(LPPOINT lppoint) +{ + HRESULT res; + static int PrevX, PrevY; + POINT prev; + + if(dxw.dwFlags1 & SLOWDOWN) dxw.DoSlow(2); + + if (pGetCursorPos) { + res=(*pGetCursorPos)(lppoint); + } + else { + lppoint->x =0; lppoint->y=0; + res=1; + } + + prev=*lppoint; + *lppoint=dxw.ScreenToClient(*lppoint); + *lppoint=dxw.FixCursorPos(*lppoint); + + GetHookInfo()->CursorX=(short)lppoint->x; + GetHookInfo()->CursorY=(short)lppoint->y; + OutTraceC("GetCursorPos: FIXED pos=(%d,%d)->(%d,%d)\n", prev.x, prev.y, lppoint->x, lppoint->y); + + return res; +} + +BOOL WINAPI extSetCursorPos(int x, int y) +{ + BOOL res; + int PrevX, PrevY; + + PrevX=x; + PrevY=y; + + if(dxw.dwFlags2 & KEEPCURSORFIXED) { + OutTraceC("SetCursorPos: FIXED pos=(%d,%d)\n", x, y); + LastCurPosX=x; + LastCurPosY=y; + return 1; + } + + if(dxw.dwFlags1 & SLOWDOWN) dxw.DoSlow(2); + + if(dxw.dwFlags1 & KEEPCURSORWITHIN){ + // Intercept SetCursorPos outside screen boundaries (used as Cursor OFF in some games) + if ((y<0)||(y>=(int)dxw.GetScreenHeight())||(x<0)||(x>=(int)dxw.GetScreenWidth())) return 1; + } + + if(dxw.dwFlags1 & MODIFYMOUSE){ + // v2.03.41 + POINT cur; + cur.x = x; + cur.y = y; + dxw.MapWindow(&cur); + x = cur.x; + y = cur.y; + } + + res=0; + if (pSetCursorPos) res=(*pSetCursorPos)(x,y); + + OutTraceC("SetCursorPos: res=%x XY=(%d,%d)->(%d,%d)\n", res, PrevX, PrevY, x, y); + return res; +} + +BOOL WINAPI extPeekMessage(LPMSG lpMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) +{ + BOOL res; + + if((wMsgFilterMin==0) && (wMsgFilterMax == 0)){ + // no filtering, everything is good + res=(*pPeekMessage)(lpMsg, hwnd, wMsgFilterMin, wMsgFilterMax, (wRemoveMsg & 0x000F)); + } + else { + MSG Dummy; + // better eliminate all messages before and after the selected range !!!! + //if(wMsgFilterMin)(*pPeekMessage)(&Dummy, hwnd, 0, wMsgFilterMin-1, TRUE); + if(wMsgFilterMin>0x0F)(*pPeekMessage)(&Dummy, hwnd, 0x0F, wMsgFilterMin-1, TRUE); + res=(*pPeekMessage)(lpMsg, hwnd, wMsgFilterMin, wMsgFilterMax, (wRemoveMsg & 0x000F)); + if(wMsgFilterMaxhwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, ExplainPeekRemoveMsg(wRemoveMsg), + lpMsg->message, ExplainWinMessage(lpMsg->message & 0xFFFF), + lpMsg->wParam, lpMsg->lParam, lpMsg->pt.x, lpMsg->pt.y, res); + else + OutTraceW("PeekMessage: ANY lpmsg=%x hwnd=%x filter=(%x-%x) remove=%x(%s) res=%x\n", + lpMsg, lpMsg->hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, ExplainPeekRemoveMsg(wRemoveMsg), res); + + + return res; +} + +BOOL WINAPI extClientToScreen(HWND hwnd, LPPOINT lppoint) +{ + // v2.02.10: fully revised to handle scaled windows + BOOL res; + + OutTraceB("ClientToScreen: hwnd=%x hWnd=%x FullScreen=%x point=(%d,%d)\n", + hwnd, dxw.GethWnd(), dxw.IsFullScreen(), lppoint->x, lppoint->y); + if (lppoint && dxw.IsFullScreen()){ + // optimization: in fullscreen mode, coordinate conversion for the desktop window + // should always keep the same values inaltered + if(hwnd != dxw.GethWnd()){ + *lppoint = dxw.AddCoordinates(*lppoint, dxw.ClientOffset(hwnd)); + } + OutTraceB("ClientToScreen: FIXED point=(%d,%d)\n", lppoint->x, lppoint->y); + res=TRUE; + } + else { + res=(*pClientToScreen)(hwnd, lppoint); + } + return res; +} + +BOOL WINAPI extScreenToClient(HWND hwnd, LPPOINT lppoint) +{ + // v2.02.10: fully revised to handle scaled windows + BOOL res; + OutTraceB("ScreenToClient: hwnd=%x hWnd=%x FullScreen=%x point=(%d,%d)\n", + hwnd, dxw.GethWnd(), dxw.IsFullScreen(), lppoint->x, lppoint->y); + + if (lppoint && (lppoint->x == -32000) && (lppoint->y == -32000)) return 1; + + if (lppoint && dxw.IsFullScreen()){ + // optimization: in fullscreen mode, coordinate conversion for the desktop window + // should always keep the same values inaltered + if(hwnd != dxw.GethWnd()){ + *lppoint = dxw.SubCoordinates(*lppoint, dxw.ClientOffset(hwnd)); + OutTraceB("ScreenToClient: FIXED point=(%d,%d)\n", lppoint->x, lppoint->y); + } + res=TRUE; + } + else { + res=(*pScreenToClient)(hwnd, lppoint); + } + return res; +} + +BOOL WINAPI extGetClientRect(HWND hwnd, LPRECT lpRect) +{ + BOOL ret; + OutTraceB("GetClientRect: whnd=%x FullScreen=%x\n", hwnd, dxw.IsFullScreen()); + + if(!lpRect) return 0; + + // proxed call + ret=(*pGetClientRect)(hwnd, lpRect); + if(!ret) { + OutTraceE("GetClientRect: ERROR hwnd=%x err=%d at %d\n", hwnd, GetLastError(), __LINE__); + return ret; + } + OutTraceB("GetClientRect: actual rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + + if (dxw.IsDesktop(hwnd)){ + *lpRect = dxw.GetScreenRect(); + OutTraceB("GetClientRect: desktop rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + else + if (dxw.IsFullScreen()){ + int w, h; + if(FIXCHILDSIZE){ + if(dxwws.GetSize(hwnd, &w, &h)){ + lpRect->top=lpRect->left=0; + lpRect->right=w; + lpRect->bottom=h; + OutTraceB("GetClientRect: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + return TRUE; + } + } + *lpRect=dxw.GetClientRect(*lpRect); + OutTraceB("GetClientRect: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + return ret; +} + +BOOL WINAPI extGetWindowRect(HWND hwnd, LPRECT lpRect) +{ + BOOL ret; + OutTraceB("GetWindowRect: hwnd=%x hWnd=%x FullScreen=%x\n", hwnd, dxw.GethWnd(), dxw.IsFullScreen()); + + if(dxw.IsRealDesktop(hwnd)) hwnd = dxw.GethWnd(); // v2.03.52: fix for "Storm Angel" + + ret=(*pGetWindowRect)(hwnd, lpRect); + if(!ret) { + OutTraceE("GetWindowRect: GetWindowRect hwnd=%x error %d at %d\n", hwnd, GetLastError(), __LINE__); + return ret; + } + OutTraceB("GetWindowRect: rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + + // minimized windows behaviour + if((lpRect->left == -32000)||(lpRect->top == -32000)) return ret; + + if (dxw.IsDesktop(hwnd)){ + // to avoid keeping track of window frame + *lpRect = dxw.GetScreenRect(); + OutTraceB("GetWindowRect: desktop rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + else + if (dxw.IsFullScreen()){ + *lpRect=dxw.GetWindowRect(*lpRect); + + // Diablo fix: it retrieves coordinates for the explorer window, that are as big as the real desktop!!! + if(lpRect->left < 0) lpRect->left=0; +// if(lpRect->left > (LONG)dxw.GetScreenWidth()) lpRect->left=dxw.GetScreenWidth(); +// if(lpRect->right < 0) lpRect->right=0; + if(lpRect->right > (LONG)dxw.GetScreenWidth()) lpRect->right=dxw.GetScreenWidth(); + if(lpRect->top < 0) lpRect->top=0; +// if(lpRect->top > (LONG)dxw.GetScreenHeight()) lpRect->top=dxw.GetScreenHeight(); +// if(lpRect->bottom < 0) lpRect->bottom=0; + if(lpRect->bottom > (LONG)dxw.GetScreenHeight()) lpRect->bottom=dxw.GetScreenHeight(); + + OutTraceB("GetWindowRect: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + + return ret; +} + +int WINAPI extMapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints) +{ + UINT pi; + int ret; + // a rarely used API, but responsible for a painful headache: needs hooking for "Commandos 2", "Alien Nations". + // used also in "Full Pipe" activemovie + // used also in "NBA Live 99" menu screen + + OutTraceDW("MapWindowPoints: hWndFrom=%x%s hWndTo=%x%s cPoints=%d FullScreen=%x\n", + hWndFrom, dxw.IsDesktop(hWndFrom)?"(DESKTOP)":"", + hWndTo, dxw.IsDesktop(hWndTo)?"(DESKTOP)":"", + cPoints, dxw.IsFullScreen()); + if(IsDebug){ + OutTrace("Points: "); + for(pi=0; pi>16, ret&0x0000FFFF); + return ret; +} + +HWND WINAPI extGetDesktopWindow(void) +{ + HWND res; + + if((!dxw.Windowize) || (dxw.dwFlags5 & DIABLOTWEAK)) { + HWND ret; + ret = (*pGetDesktopWindow)(); + OutTraceDW("GetDesktopWindow: BYPASS ret=%x\n", ret); + return ret; + } + + OutTraceDW("GetDesktopWindow: FullScreen=%x\n", dxw.IsFullScreen()); + if (dxw.IsFullScreen()){ + if(dxw.dwFlags6 & CREATEDESKTOP){ + extern HWND hDesktopWindow; + OutTraceDW("GetDesktopWindow: returning desktop emulated hwnd=%x\n", hDesktopWindow); + return hDesktopWindow; + } + OutTraceDW("GetDesktopWindow: returning main window hwnd=%x\n", dxw.GethWnd()); + return dxw.GethWnd(); + } + else{ + res=(*pGetDesktopWindow)(); + OutTraceDW("GetDesktopWindow: returning desktop window hwnd=%x\n", res); + return res; + } +} + +int WINAPI extGetSystemMetrics(int nindex) +{ + HRESULT res; + + res=(*pGetSystemMetrics)(nindex); + OutTraceDW("GetSystemMetrics: index=%x(%s), res=%d\n", nindex, ExplainsSystemMetrics(nindex), res); + + if(!dxw.Windowize){ + // v2.02.95: if not in window mode, just implement the HIDEMULTIMONITOR flag + if( (nindex ==SM_CMONITORS) && + (dxw.dwFlags2 & HIDEMULTIMONITOR) && + res>1) { + res=1; + OutTraceDW("GetSystemMetrics: fix SM_CMONITORS=%d\n", res); + } + return res; + } + + switch(nindex){ + case SM_CXFULLSCREEN: + case SM_CXSCREEN: + case SM_CXVIRTUALSCREEN: // v2.02.31 + res= dxw.GetScreenWidth(); + OutTraceDW("GetSystemMetrics: fix SM_CXSCREEN=%d\n", res); + break; + case SM_CYFULLSCREEN: + case SM_CYSCREEN: + case SM_CYVIRTUALSCREEN: // v2.02.31 + res= dxw.GetScreenHeight(); + OutTraceDW("GetSystemMetrics: fix SM_CYSCREEN=%d\n", res); + break; + case SM_CMONITORS: + if((dxw.dwFlags2 & HIDEMULTIMONITOR) && res>1) { + res=1; + OutTraceDW("GetSystemMetrics: fix SM_CMONITORS=%d\n", res); + } + break; + } + + return res; +} + +ATOM WINAPI extRegisterClassExA(WNDCLASSEX *lpwcx) +{ + OutTraceDW("RegisterClassEx: PROXED ClassName=%s style=%x(%s) WndProc=%x cbClsExtra=%d cbWndExtra=%d hInstance=%x\n", + lpwcx->lpszClassName, lpwcx->style, ExplainStyle(lpwcx->style), lpwcx->lpfnWndProc, lpwcx->cbClsExtra, lpwcx->cbWndExtra, lpwcx->hInstance); + return (*pRegisterClassExA)(lpwcx); +} + +ATOM WINAPI extRegisterClassA(WNDCLASS *lpwcx) +{ + // referenced by Syberia, together with RegisterClassExA + OutTraceDW("RegisterClass: PROXED ClassName=%s style=%x(%s) WndProc=%x cbClsExtra=%d cbWndExtra=%d hInstance=%x\n", + lpwcx->lpszClassName, lpwcx->style, ExplainStyle(lpwcx->style), lpwcx->lpfnWndProc, lpwcx->cbClsExtra, lpwcx->cbWndExtra, lpwcx->hInstance); + return (*pRegisterClassA)(lpwcx); +} + +static void HookChildWndProc(HWND hwnd, DWORD dwStyle, LPCTSTR ApiName) +{ + // child window inherit the father's windproc, so if it's redirected to + // a hooker (either extWindowProc or extChildWindowProc) you have to retrieve + // the correct value (dxwws.GetProc) before saving it (dxwws.PutProc). + long res; + WNDPROC pWindowProc; + + if(dxw.dwFlags6 & NOWINDOWHOOKS) return; + + pWindowProc = (WNDPROC)(*pGetWindowLongA)(hwnd, GWL_WNDPROC); + if((pWindowProc == extWindowProc) || + (pWindowProc == extChildWindowProc) || + (pWindowProc == extDialogWindowProc)){ // avoid recursions + HWND Father; + WNDPROC pFatherProc; + Father=(*pGetParent)(hwnd); + pFatherProc=dxwws.GetProc(Father); + OutTraceDW("%s: WndProc=%s father=%x WndProc=%x\n", ApiName, + (pWindowProc == extWindowProc) ? "extWindowProc" : ((pWindowProc == extChildWindowProc) ? "extChildWindowProc" : "extDialogWindowProc"), + Father, pFatherProc); + pWindowProc = pFatherProc; + } + dxwws.PutProc(hwnd, pWindowProc); + if(dwStyle & WS_CHILD){ + OutTraceDW("%s: Hooking CHILD hwnd=%x father WindowProc %x->%x\n", ApiName, hwnd, pWindowProc, extChildWindowProc); + res=(*pSetWindowLongA)(hwnd, GWL_WNDPROC, (LONG)extChildWindowProc); + } + else { // must be dwStyle & WS_DLGFRAME + OutTraceDW("%s: Hooking DLGFRAME hwnd=%x father WindowProc %x->%x\n", ApiName, hwnd, pWindowProc, extDialogWindowProc); + res=(*pSetWindowLongA)(hwnd, GWL_WNDPROC, (LONG)extDialogWindowProc); + } + if(!res) OutTraceE("%s: SetWindowLong ERROR %x\n", ApiName, GetLastError()); +} + +HWND hControlParentWnd = NULL; + +// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms632679%28v=vs.85%29.aspx + +static BOOL IsFullscreenWindow( + void *lpClassName, + DWORD dwStyle, + DWORD dwExStyle, + HWND hWndParent, + int x, + int y, + int nWidth, + int nHeight) +{ + if (dwExStyle & WS_EX_CONTROLPARENT) return FALSE; // "Diablo" fix + if ((dwStyle & WS_CHILD) && (!dxw.IsDesktop(hWndParent))) return FALSE; // Diablo fix + // if maximized. + if(dwStyle & WS_MAXIMIZE) return TRUE; + // go through here only when WS_CHILD of desktop window + if((x == CW_USEDEFAULT) && (dwStyle & (WS_POPUP|WS_CHILD))) x = y = 0; + if(nWidth == CW_USEDEFAULT){ + if (dwStyle & (WS_POPUP|WS_CHILD)) nWidth = nHeight = 0; + else nWidth = dxw.GetScreenWidth() - x; + } + // msdn undocumented case: x,y=(-1000, CW_USEDEFAULT) w,h=(CW_USEDEFAULT,CW_USEDEFAULT) in "Imperialism" + if(nHeight == CW_USEDEFAULT){ + y = 0; + nHeight = dxw.GetScreenHeight(); + } + // if bigger than screen ... + if((x<=0)&& + (y<=0)&& + (nWidth>=(int)dxw.GetScreenWidth())&& + (nHeight>=(int)dxw.GetScreenHeight())) return TRUE; + return FALSE; +} + +static HWND WINAPI extCreateWindowCommon( + LPCTSTR ApiName, + BOOL WideChar, + DWORD dwExStyle, + void *lpClassName, + void *lpWindowName, + DWORD dwStyle, + int x, + int y, + int nWidth, + int nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam) +{ + HWND hwnd; + BOOL isValidHandle=TRUE; + int iOrigW, iOrigH; + + iOrigW=nWidth; + iOrigH=nHeight; + if(!dxw.Windowize || (hWndParent == HWND_MESSAGE)){ // v2.02.87: don't process message windows (hWndParent == HWND_MESSAGE) + if(WideChar) + hwnd= (*pCreateWindowExW)(dwExStyle, (LPCWSTR)lpClassName, (LPCWSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + else + hwnd= (*pCreateWindowExA)(dwExStyle, (LPCSTR)lpClassName, (LPCSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + + if ((dxw.dwFlags1 & HOOKCHILDWIN) && (dwStyle & (WS_CHILD|WS_DLGFRAME))) + HookChildWndProc(hwnd, dwStyle, ApiName); + + OutTraceDW("%s: ret=%x\n", ApiName, hwnd); + return hwnd; + } + + // no maximized windows in any case + if (dxw.dwFlags1 & PREVENTMAXIMIZE){ + OutTraceDW("%s: handling PREVENTMAXIMIZE mode\n", ApiName); + dwStyle &= ~WS_MAXIMIZE; + } + + if(dxw.dwFlags6 & CREATEDESKTOP){ + extern HWND hDesktopWindow; + if (dxw.IsRealDesktop(hWndParent)){ + OutTraceE("%s: new parent win %x->%x\n", ApiName, hWndParent, hDesktopWindow); + hWndParent=hDesktopWindow; + } + } + + // v2.1.92: fixes size & position for auxiliary big window, often used + // for intro movies etc. : needed for ...... + // evidently, this was supposed to be a fullscreen window.... + // v2.1.100: fixes for "The Grinch": this game creates a new main window for OpenGL + // rendering using CW_USEDEFAULT placement and 800x600 size while the previous + // main win was 640x480 only! + // v2.02.13: if it's a WS_CHILD window, don't reposition the x,y, placement for BIG win. + // v2.02.30: fix (Fable - lost chapters) Fable creates a bigger win with negative x,y coordinates. + // v2.03.53: revised code, logic moved to IsFullscreenWindow + + if(IsFullscreenWindow(lpClassName, dwStyle, dwExStyle, hWndParent, x, y, nWidth, nHeight)){ + RECT screen; + POINT upleft = {0,0}; + + // update virtual screen size if it has grown + dxw.SetScreenSize(nWidth, nHeight); + + // inserted some checks here, since the main window could be destroyed + // or minimized (see "Jedi Outcast") so that you may get a dangerous + // zero size. In this case, better renew the hWnd assignement and its coordinates. + do { // fake loop + isValidHandle = FALSE; + if (!(*pGetClientRect)(dxw.GethWnd(),&screen)) break; + if (!(*pClientToScreen)(dxw.GethWnd(),&upleft)) break; + if (screen.right==0 || screen.bottom==0) break; + isValidHandle = TRUE; + } while(FALSE); + if (isValidHandle){ // use parent's coordinates + if (!(dwStyle & WS_CHILD)){ + x=upleft.x; + y=upleft.y; + } + nWidth=screen.right; + nHeight=screen.bottom; + OutTraceDW("%s: fixed BIG win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); + } + else { + x=dxw.iPosX; + y=dxw.iPosY; + nWidth=dxw.iSizX; + nHeight=dxw.iSizY; + OutTraceDW("%s: renewed BIG win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); + } + dxw.SetFullScreen(TRUE); + if(dxw.Coordinates==DXW_DESKTOP_WORKAREA){ + RECT workarea; + (*pSystemParametersInfoA)(SPI_GETWORKAREA, NULL, &workarea, 0); + x=0; + y=0; + nWidth=workarea.right; + nHeight=workarea.bottom; + dwStyle=0; + OutTraceDW("%s: WORKAREA win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); + } + else if(dxw.Coordinates==DXW_DESKTOP_FULL){ + RECT workarea; + (*pGetClientRect)((*pGetDesktopWindow)(), &workarea); + x=0; + y=0; + nWidth=workarea.right; + nHeight=workarea.bottom; + dwStyle=0; + OutTraceDW("%s: FULLDESKTOP win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); + } + } + + if(!dxw.IsFullScreen()){ // v2.1.63: needed for "Monster Truck Madness" + if(WideChar) + hwnd= (*pCreateWindowExW)(dwExStyle, (LPCWSTR)lpClassName, (LPCWSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + else + hwnd= (*pCreateWindowExA)(dwExStyle, (LPCSTR)lpClassName, (LPCSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + OutTraceDW("%s: windowed mode ret=%x\n", ApiName, hwnd); + return hwnd; + } + + // from here on, fullscreen is garanteed + + if (dwStyle & WS_CHILD){ + // tested on Gangsters: coordinates must be window-relative!!! + // Age of Empires.... + dxw.MapClient(&x, &y, &nWidth, &nHeight); + OutTraceDW("%s: fixed WS_CHILD pos=(%d,%d) size=(%d,%d)\n", + ApiName, x, y, nWidth, nHeight); + } + else { + if ((dwExStyle & WS_EX_CONTROLPARENT) || (dwStyle & WS_POPUP)){ + // needed for "Diablo", that creates a new WS_EX_CONTROLPARENT window that must be + // overlapped to the directdraw surface. + // needed for "Riven", that creates a new WS_POPUP window with the menu bar that must be + // overlapped to the directdraw surface. + dxw.MapWindow(&x, &y, &nWidth, &nHeight); + OutTraceDW("%s: fixed pos=(%d,%d) size=(%d,%d)\n", + ApiName, x, y, nWidth, nHeight); + } + } + + OutTraceB("%s: fixed pos=(%d,%d) size=(%d,%d) Style=%x(%s) ExStyle=%x(%s)\n", + ApiName, x, y, nWidth, nHeight, dwStyle, ExplainStyle(dwStyle), dwExStyle, ExplainExStyle(dwExStyle)); + + if(WideChar) + hwnd= (*pCreateWindowExW)(dwExStyle, (LPCWSTR)lpClassName, (LPCWSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + else + hwnd= (*pCreateWindowExA)(dwExStyle, (LPCSTR)lpClassName, (LPCSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + if (hwnd==(HWND)NULL){ + OutTraceE("%s: ERROR err=%d Style=%x(%s) ExStyle=%x\n", + ApiName, GetLastError(), dwStyle, ExplainStyle(dwStyle), dwExStyle); + return hwnd; + } + + if (dwExStyle & WS_EX_CONTROLPARENT) hControlParentWnd=hwnd; + + if ((!isValidHandle) && dxw.IsFullScreen()){ + dxw.SethWnd(hwnd); + extern void AdjustWindowPos(HWND, DWORD, DWORD); + (*pSetWindowLongA)(hwnd, GWL_STYLE, (dxw.dwFlags2 & MODALSTYLE) ? 0 : WS_OVERLAPPEDWINDOW); + (*pSetWindowLongA)(hwnd, GWL_EXSTYLE, 0); + OutTraceDW("%s: hwnd=%x, set style=WS_OVERLAPPEDWINDOW extstyle=0\n", ApiName, hwnd); + AdjustWindowPos(hwnd, nWidth, nHeight); + (*pShowWindow)(hwnd, SW_SHOWNORMAL); + } + + //if ((dxw.dwFlags1 & FIXWINFRAME) && !(dwStyle & WS_CHILD)) + if ((dxw.dwFlags1 & FIXWINFRAME) && !(dwStyle & WS_CHILD) && dxw.IsDesktop(hwnd)) + dxw.FixWindowFrame(hwnd); + + if ((dxw.dwFlags1 & HOOKCHILDWIN) && (dwStyle & (WS_CHILD|WS_DLGFRAME))) + HookChildWndProc(hwnd, dwStyle, ApiName); + + if ((FIXCHILDSIZE) && (dwStyle & (WS_CHILD|WS_DLGFRAME))) + dxwws.PutSize(hwnd, iOrigW, iOrigH); + + // "Hoyle Casino Empire" needs to be in a maximized state to continue after the intro movie. + // Sending a SW_MAXIMIZE message intercepted by the PREVENTMAXIMIZE handling fixes the problem. + //if (dxw.IsFullScreen() && (dxw.dwFlags1 & PREVENTMAXIMIZE)){ + if ((hwnd == dxw.GethWnd()) && dxw.IsFullScreen() && (dxw.dwFlags1 & PREVENTMAXIMIZE)){ + OutTraceDW("%s: entering maximized state\n", ApiName); + (*pShowWindow)(hwnd, SW_MAXIMIZE); + } + + if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor(); + + OutTraceDW("%s: ret=%x\n", ApiName, hwnd); + return hwnd; +} + +static LPCSTR ClassToStr(LPCSTR Class) +{ + static char AtomBuf[20+1]; + if(((DWORD)Class & 0xFFFF0000) == 0){ + sprintf(AtomBuf, "ATOM(%X)", (DWORD)Class); + return AtomBuf; + } + return Class; +} + +static LPCWSTR ClassToWStr(LPCWSTR Class) +{ + static WCHAR AtomBuf[20+1]; + if(((DWORD)Class & 0xFFFF0000) == 0){ + swprintf(AtomBuf, L"ATOM(%X)", (DWORD)Class); + return AtomBuf; + } + return Class; +} +// to do: implement and use ClassToWStr() for widechar call + +HWND WINAPI extCreateWindowExW( + DWORD dwExStyle, + LPCWSTR lpClassName, + LPCWSTR lpWindowName, + DWORD dwStyle, + int x, + int y, + int nWidth, + int nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam) +{ + if(IsTraceDW){ + char xString[20], yString[20], wString[20], hString[20]; + if (x==CW_USEDEFAULT) strcpy(xString,"CW_USEDEFAULT"); + else sprintf(xString,"%d", x); + if (y==CW_USEDEFAULT) strcpy(yString,"CW_USEDEFAULT"); + else sprintf(yString,"%d", y); + if (nWidth==CW_USEDEFAULT) strcpy(wString,"CW_USEDEFAULT"); + else sprintf(wString,"%d", nWidth); + if (nHeight==CW_USEDEFAULT) strcpy(hString,"CW_USEDEFAULT"); + else sprintf(hString,"%d", nHeight); + OutTrace("CreateWindowExW: class=\"%ls\" wname=\"%ls\" pos=(%s,%s) size=(%s,%s) Style=%x(%s) ExStyle=%x(%s) hWndParent=%x%s hMenu=%x\n", + ClassToWStr(lpClassName), lpWindowName, xString, yString, wString, hString, + dwStyle, ExplainStyle(dwStyle), dwExStyle, ExplainExStyle(dwExStyle), + hWndParent, hWndParent==HWND_MESSAGE?"(HWND_MESSAGE)":"", hMenu); + } + OutTraceB("CreateWindowExW: DEBUG fullscreen=%x mainwin=%x screen=(%d,%d)\n", + dxw.IsFullScreen(), dxw.GethWnd(), dxw.GetScreenWidth(), dxw.GetScreenHeight()); + + if((dxw.dwFlags6 & STRETCHMOVIES) && !wcscmp(lpWindowName, L"ActiveMovie Window")){ + RECT MainWin; + (*pGetClientRect)(dxw.GethWnd(), &MainWin); + nWidth = MainWin.right; + nHeight = MainWin.bottom; + } + + return extCreateWindowCommon("CreateWindowExW", TRUE, dwExStyle, (void *)lpClassName, (void *)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); +} + +// GHO: pro Diablo +HWND WINAPI extCreateWindowExA( + DWORD dwExStyle, + LPCTSTR lpClassName, + LPCTSTR lpWindowName, + DWORD dwStyle, + int x, + int y, + int nWidth, + int nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam) +{ + if(IsTraceDW){ + char xString[20], yString[20], wString[20], hString[20]; + if (x==CW_USEDEFAULT) strcpy(xString,"CW_USEDEFAULT"); + else sprintf(xString,"%d", x); + if (y==CW_USEDEFAULT) strcpy(yString,"CW_USEDEFAULT"); + else sprintf(yString,"%d", y); + if (nWidth==CW_USEDEFAULT) strcpy(wString,"CW_USEDEFAULT"); + else sprintf(wString,"%d", nWidth); + if (nHeight==CW_USEDEFAULT) strcpy(hString,"CW_USEDEFAULT"); + else sprintf(hString,"%d", nHeight); + OutTrace("CreateWindowExA: class=\"%s\" wname=\"%s\" pos=(%s,%s) size=(%s,%s) Style=%x(%s) ExStyle=%x(%s) hWndParent=%x%s hMenu=%x\n", + ClassToStr(lpClassName), lpWindowName, xString, yString, wString, hString, + dwStyle, ExplainStyle(dwStyle), dwExStyle, ExplainExStyle(dwExStyle), + hWndParent, hWndParent==HWND_MESSAGE?"(HWND_MESSAGE)":"", hMenu); + } + OutTraceB("CreateWindowExA: DEBUG fullscreen=%x mainwin=%x screen=(%d,%d)\n", + dxw.IsFullScreen(), dxw.GethWnd(), dxw.GetScreenWidth(), dxw.GetScreenHeight()); + + if((dxw.dwFlags6 & STRETCHMOVIES) && !strcmp(lpWindowName, "ActiveMovie Window")){ + RECT MainWin; + (*pGetClientRect)(dxw.GethWnd(), &MainWin); + nWidth = MainWin.right; + nHeight = MainWin.bottom; + } + + return extCreateWindowCommon("CreateWindowExA", FALSE, dwExStyle, (void *)lpClassName, (void *)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); +} + +LRESULT WINAPI extCallWindowProcA(WNDPROC lpPrevWndFunc, HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + // v2.02.30: fix (Imperialism II): apply to main window only !!! + HRESULT res; + + res = -1; + if(hwnd == dxw.GethWnd()) res=FixWindowProc("CallWindowProcA", hwnd, Msg, wParam, &lParam); + + if (res==(HRESULT)-1) + return (*pCallWindowProcA)(lpPrevWndFunc, hwnd, Msg, wParam, lParam); + else + return res; +} + +LRESULT WINAPI extCallWindowProcW(WNDPROC lpPrevWndFunc, HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + // v2.02.30: fix (Imperialism II): apply to main window only !!! + HRESULT res; + + res = -1; + if(hwnd == dxw.GethWnd()) res=FixWindowProc("CallWindowProcW", hwnd, Msg, wParam, &lParam); + + if (res==(HRESULT)-1) + return (*pCallWindowProcW)(lpPrevWndFunc, hwnd, Msg, wParam, lParam); + else + return res; +} + +LRESULT WINAPI extDefWindowProcA(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + // v2.02.30: fix (Imperialism II): apply to main window only !!! + // v2.03.50: fix - do clip cursor only after the window has got focus + HRESULT res; + res = (HRESULT)-1; + if(hwnd == dxw.GethWnd()) res=FixWindowProc("DefWindowProcA", hwnd, Msg, wParam, &lParam); + if (res==(HRESULT)-1) res = (*pDefWindowProcA)(hwnd, Msg, wParam, lParam); + if((Msg == WM_SETFOCUS) && (dxw.dwFlags1 & CLIPCURSOR)) dxw.SetClipCursor(); + return res; +} + +LRESULT WINAPI extDefWindowProcW(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + // v2.02.30: fix (Imperialism II): apply to main window only !!! + // v2.03.50: fix - do clip cursor only after the window has got focus + HRESULT res; + res = (HRESULT)-1; + if(hwnd == dxw.GethWnd()) res=FixWindowProc("DefWindowProcW", hwnd, Msg, wParam, &lParam); + if (res==(HRESULT)-1) res = (*pDefWindowProcW)(hwnd, Msg, wParam, lParam); + if((Msg == WM_SETFOCUS) && (dxw.dwFlags1 & CLIPCURSOR)) dxw.SetClipCursor(); + return res; +} + +static int HandleRect(char *ApiName, void *pFun, HDC hdc, const RECT *lprc, HBRUSH hbr) +{ + // used for both FillRect and FrameRect calls + int res; + RECT rc; + OutTraceDW("%s: hdc=%x hbrush=%x rect=(%d,%d)-(%d,%d)\n", ApiName, hdc, hbr, lprc->left, lprc->top, lprc->right, lprc->bottom); + + if(dxw.dwFlags4 & NOFILLRECT) { + OutTraceDW("%s: SUPPRESS\n", ApiName, hdc, hbr, lprc->left, lprc->top, lprc->right, lprc->bottom); + return TRUE; + } + + memcpy(&rc, lprc, sizeof(rc)); + + // Be careful: when you call CreateCompatibleDC with NULL DC, it is created a memory DC + // with same characteristics as desktop. That would return true from the call to + // dxw.IsRealDesktop(WindowFromDC(hdc)) because WindowFromDC(hdc) is null. + // So, it's fundamental to check also the hdc type (OBJ_DC is a window's DC) + + if((dxw.IsRealDesktop(WindowFromDC(hdc)) && (OBJ_DC == GetObjectType(hdc)))) { + HWND VirtualDesktop; + VirtualDesktop=dxw.GethWnd(); + if(VirtualDesktop==NULL){ + OutTraceDW("%s: no virtual desktop\n", ApiName); + return TRUE; + } + OutTraceDW("%s: remapped hdc to virtual desktop hwnd=%x\n", ApiName, dxw.GethWnd()); + hdc=(*pGDIGetDC)(dxw.GethWnd()); + } + + if(dxw.IsToRemap(hdc)) { + if(rc.left < 0) rc.left = 0; + if(rc.top < 0) rc.top = 0; + if((DWORD)rc.right > dxw.GetScreenWidth()) rc.right = dxw.GetScreenWidth(); + if((DWORD)rc.bottom > dxw.GetScreenHeight()) rc.bottom = dxw.GetScreenHeight(); + + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + if (sdc.GetPrimaryDC(hdc)){ + res=(*(FillRect_Type)pFun)(sdc.GetHdc(), &rc, hbr); + sdc.PutPrimaryDC(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + return res; + } + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&rc); + OutTraceDW("%s: fixed rect=(%d,%d)-(%d,%d)\n", ApiName, rc.left, rc.top, rc.right, rc.bottom); + break; + default: + break; + } + } + else { + // when not in fullscreen mode, just proxy the call + // but check coordinates: some games may use excessive coordinates: see "Premier Manager 98" + RECT client; + HWND hwnd; + hwnd=WindowFromDC(hdc); + (*pGetClientRect)(hwnd, &client); + if(rc.left < 0) rc.left=0; + if(rc.top < 0) rc.top=0; + if(rc.right > client.right) rc.right=client.right; + if(rc.bottom > client.bottom) rc.bottom=client.bottom; + OutTraceDW("%s: remapped hdc from hwnd=%x to rect=(%d,%d)-(%d,%d)\n", ApiName, hwnd, rc.left, rc.top, rc.right, rc.bottom); + } + + res=(*(FillRect_Type)pFun)(hdc, &rc, hbr); + return res; +} + +int WINAPI extFillRect(HDC hdc, const RECT *lprc, HBRUSH hbr) +{ + return HandleRect("FillRect", (void *)pFillRect, hdc, lprc, hbr); +} + +int WINAPI extFrameRect(HDC hdc, const RECT *lprc, HBRUSH hbr) +{ + return HandleRect("FramelRect", (void *)pFrameRect, hdc, lprc, hbr); +} + +BOOL WINAPI extInvertRect(HDC hdc, const RECT *lprc) +{ + int res; + RECT rc; + OutTraceDW("InvertRect: hdc=%x rect=(%d,%d)-(%d,%d)\n", hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); + + memcpy(&rc, lprc, sizeof(rc)); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + if(sdc.GetPrimaryDC(hdc)){ + res=(*pInvertRect)(sdc.GetHdc(), &rc); + sdc.PutPrimaryDC(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + return res; + } + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&rc); + OutTraceDW("InvertRect: fixed rect=(%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + break; + default: + break; + } + } + + res=(*pInvertRect)(hdc, &rc); + return res; +} + +int WINAPI extValidateRect(HWND hwnd, const RECT *lprc) +{ + int res; + RECT rc; + + OutTraceDW("ValidateRect: hwnd=%x rect=(%d,%d)-(%d,%d)\n", + hwnd, lprc->left, lprc->top, lprc->right, lprc->bottom); + + memcpy(&rc, lprc, sizeof(rc)); + + if(dxw.IsFullScreen()) { + if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); + dxw.MapClient(&rc); + OutTraceDW("ValidateRect: fixed rect=(%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + } + + res=(*pValidateRect)(hwnd, &rc); + return res; +} + +BOOL WINAPI extClipCursor(RECT *lpRectArg) +{ + // reference: hooking and setting ClipCursor is mandatori in "Emergency: Fighters for Life" + // where the application expects the cursor to be moved just in a inner rect within the + // main window surface. + + BOOL res; + RECT *lpRect; + RECT Rect; + + if(IsTraceC){ + if (lpRectArg) + OutTrace("ClipCursor: rect=(%d,%d)-(%d,%d)\n", + lpRectArg->left,lpRectArg->top,lpRectArg->right,lpRectArg->bottom); + else + OutTrace("ClipCursor: rect=(NULL)\n"); + } + + if (!(dxw.dwFlags1 & ENABLECLIPPING)) return 1; + + if(lpRectArg){ + Rect=*lpRectArg; + lpRect=&Rect; + } + else + lpRect=NULL; + + if(dxw.dwFlags1 & MODIFYMOUSE){ + // save desired clip region + // v2.02.39: fix - do not attempt to write to NULL lpRect + if (lpRect) { + ClipRegion=*lpRectArg; + lpClipRegion=&ClipRegion; + *lpRect=dxw.MapWindowRect(lpRect); + } + else + lpClipRegion=NULL; + } + + if (pClipCursor) res=(*pClipCursor)(lpRect); + if (lpRect) OutTraceDW("ClipCursor: REMAPPED rect=(%d,%d)-(%d,%d) res=%x\n", lpRect->left,lpRect->top,lpRect->right,lpRect->bottom, res); + + return TRUE; +} + +BOOL WINAPI extGetClipCursor(LPRECT lpRect) +{ + // v2.1.93: if ENABLECLIPPING, return the saved clip rect coordinates + + BOOL ret; + + // proxy.... + if (!(dxw.dwFlags1 & ENABLECLIPPING)) { + ret=(*pGetClipCursor)(lpRect); + // v2.03.11: fix for "SubCulture" mouse movement + if(lpRect && dxw.Windowize) *lpRect = dxw.GetScreenRect(); + if(IsTraceDDRAW){ + if (lpRect) + OutTrace("GetClipCursor: rect=(%d,%d)-(%d,%d) ret=%d\n", + lpRect->left,lpRect->top,lpRect->right,lpRect->bottom, ret); + else + OutTrace("GetClipCursor: rect=(NULL) ret=%d\n", ret); + } + return ret; + } + + if(lpRect){ + if(lpClipRegion) + *lpRect=ClipRegion; + else + *lpRect=dxw.GetScreenRect(); + OutTraceDW("GetClipCursor: rect=(%d,%d)-(%d,%d) ret=%d\n", + lpRect->left,lpRect->top,lpRect->right,lpRect->bottom, TRUE); + } + + return TRUE; +} + +LONG WINAPI extEnumDisplaySettings(LPCTSTR lpszDeviceName, DWORD iModeNum, DEVMODE *lpDevMode) +{ + LONG res; + OSVERSIONINFO osinfo; + + osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + (*pGetVersionExA)(&osinfo); + OutTraceDW("EnumDisplaySettings: Devicename=%s ModeNum=%x OS=%d.%d\n", lpszDeviceName, iModeNum, osinfo.dwMajorVersion, osinfo.dwMinorVersion); + + if(dxw.dwFlags4 & NATIVERES){ + // lists video card native resolutions, though faking emulated color resolutions + if((osinfo.dwMajorVersion >= 6) && (dxw.dwFlags1 & EMULATESURFACE)){ + switch(iModeNum){ + case ENUM_CURRENT_SETTINGS: + case ENUM_REGISTRY_SETTINGS: // lie ... + res=(*pEnumDisplaySettings)(lpszDeviceName, iModeNum, lpDevMode); + if(dxw.dwFlags2 & INIT8BPP) lpDevMode->dmBitsPerPel = 8; + if(dxw.dwFlags2 & INIT16BPP) lpDevMode->dmBitsPerPel = 16; + if(dxw.dwFlags3 & FORCE16BPP) lpDevMode->dmBitsPerPel = 16; + break; + default: + res=(*pEnumDisplaySettings)(lpszDeviceName, iModeNum / SUPPORTED_DEPTHS_NUMBER, lpDevMode); + lpDevMode->dmBitsPerPel = (DWORD)SupportedDepths[iModeNum % SUPPORTED_DEPTHS_NUMBER]; + break; + } + } + else + res=(*pEnumDisplaySettings)(lpszDeviceName, iModeNum, lpDevMode); + + } + else { // simulated modes: VGA or HDTV + //int SupportedDepths[5]={8,16,24,32,0}; + SupportedRes_Type *SupportedRes; + SupportedRes = (dxw.dwFlags4 & SUPPORTHDTV) ? &SupportedHDTVRes[0] : &SupportedSVGARes[0]; + res=(*pEnumDisplaySettings)(lpszDeviceName, ENUM_CURRENT_SETTINGS, lpDevMode); + switch(iModeNum){ + case ENUM_CURRENT_SETTINGS: + case ENUM_REGISTRY_SETTINGS: // lie ... + lpDevMode->dmPelsHeight = 600; + lpDevMode->dmPelsWidth = 800; + if(dxw.dwFlags2 & INIT8BPP) lpDevMode->dmBitsPerPel = 8; + if(dxw.dwFlags2 & INIT16BPP) lpDevMode->dmBitsPerPel = 16; + if(dxw.dwFlags3 & FORCE16BPP) lpDevMode->dmBitsPerPel = 16; + break; + default: + lpDevMode->dmPelsHeight = SupportedRes[iModeNum / 4].h; + lpDevMode->dmPelsWidth = SupportedRes[iModeNum / 4].w; + lpDevMode->dmBitsPerPel = SupportedDepths[iModeNum % 4]; + if(lpDevMode->dmPelsHeight == 0) res = 0; // end of list + break; + } + } + + if(dxw.dwFlags4 & LIMITSCREENRES){ + #define HUGE 100000 + DWORD maxw, maxh; + maxw = maxh = HUGE; + switch(dxw.MaxScreenRes){ + case DXW_NO_LIMIT: maxw=HUGE; maxh=HUGE; break; + case DXW_LIMIT_320x200: maxw=320; maxh=200; break; + case DXW_LIMIT_640x480: maxw=640; maxh=480; break; + case DXW_LIMIT_800x600: maxw=800; maxh=600; break; + case DXW_LIMIT_1024x768: maxw=1024; maxh=768; break; + case DXW_LIMIT_1280x960: maxw=1280; maxh=960; break; + } + if((lpDevMode->dmPelsWidth > maxw) || (lpDevMode->dmPelsHeight > maxh)){ + OutTraceDW("EnumDisplaySettings: limit device size=(%d,%d)\n", maxw, maxh); + lpDevMode->dmPelsWidth = maxw; + lpDevMode->dmPelsHeight = maxh; + } + } + + OutTraceDW("EnumDisplaySettings: color=%dBPP size=(%dx%d) refresh=%dHz\n", + lpDevMode->dmBitsPerPel, lpDevMode->dmPelsWidth, lpDevMode->dmPelsHeight, lpDevMode->dmDisplayFrequency); + return res; +} + +LONG WINAPI extChangeDisplaySettingsA(DEVMODEA *lpDevMode, DWORD dwflags) +{ + if(IsTraceDDRAW){ + char sInfo[1024]; + strcpy(sInfo, ""); + if (lpDevMode) sprintf(sInfo, " DeviceName=%s fields=%x(%s) size=(%d x %d) bpp=%d", + lpDevMode->dmDeviceName, lpDevMode->dmFields, ExplainDevModeFields(lpDevMode->dmFields), + lpDevMode->dmPelsWidth, lpDevMode->dmPelsHeight, lpDevMode->dmBitsPerPel); + OutTrace("ChangeDisplaySettingsA: lpDevMode=%x flags=%x(%s)%s\n", + lpDevMode, dwflags, ExplainChangeDisplaySettingsFlags(dwflags), sInfo); + } + + if(dxw.Windowize) + return MyChangeDisplaySettings("ChangeDisplaySettingsA", FALSE, lpDevMode, dwflags); + else + return (*pChangeDisplaySettingsExA)(NULL, lpDevMode, NULL, dwflags, NULL); +} + +LONG WINAPI extChangeDisplaySettingsW(DEVMODEW *lpDevMode, DWORD dwflags) +{ + if(IsTraceDDRAW){ + char sInfo[1024]; + strcpy(sInfo, ""); + if (lpDevMode) sprintf(sInfo, " DeviceName=%ls fields=%x(%s) size=(%d x %d) bpp=%d", + lpDevMode->dmDeviceName, lpDevMode->dmFields, ExplainDevModeFields(lpDevMode->dmFields), + lpDevMode->dmPelsWidth, lpDevMode->dmPelsHeight, lpDevMode->dmBitsPerPel); + OutTrace("ChangeDisplaySettingsW: lpDevMode=%x flags=%x(%s)%s\n", + lpDevMode, dwflags, ExplainChangeDisplaySettingsFlags(dwflags), sInfo); + } + + if(dxw.Windowize) + return MyChangeDisplaySettings("ChangeDisplaySettingsW", TRUE, lpDevMode, dwflags); + else + return (*pChangeDisplaySettingsW)(lpDevMode, dwflags); +} + +LONG WINAPI extChangeDisplaySettingsExA(LPCTSTR lpszDeviceName, DEVMODEA *lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam) +{ + if(IsTraceDDRAW){ + char sInfo[1024]; + strcpy(sInfo, ""); + if (lpDevMode) sprintf(sInfo, " DeviceName=%s fields=%x(%s) size=(%d x %d) bpp=%d", + lpDevMode->dmDeviceName, lpDevMode->dmFields, ExplainDevModeFields(lpDevMode->dmFields), + lpDevMode->dmPelsWidth, lpDevMode->dmPelsHeight, lpDevMode->dmBitsPerPel); + OutTrace("ChangeDisplaySettingsExA: DeviceName=%s lpDevMode=%x flags=%x(%s)%s\n", + lpszDeviceName, lpDevMode, dwflags, ExplainChangeDisplaySettingsFlags(dwflags), sInfo); + } + + if(dxw.Windowize) + return MyChangeDisplaySettings("ChangeDisplaySettingsExA", FALSE, lpDevMode, dwflags); + else + return (*pChangeDisplaySettingsExA)(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam); +} + +LONG WINAPI extChangeDisplaySettingsExW(LPCTSTR lpszDeviceName, DEVMODEW *lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam) +{ + if(IsTraceDDRAW){ + char sInfo[1024]; + strcpy(sInfo, ""); + if (lpDevMode) sprintf(sInfo, " DeviceName=%ls fields=%x(%s) size=(%d x %d) bpp=%d", + lpDevMode->dmDeviceName, lpDevMode->dmFields, ExplainDevModeFields(lpDevMode->dmFields), + lpDevMode->dmPelsWidth, lpDevMode->dmPelsHeight, lpDevMode->dmBitsPerPel); + OutTrace("ChangeDisplaySettingsExW: DeviceName=%ls lpDevMode=%x flags=%x(%s)%s\n", + lpszDeviceName, lpDevMode, dwflags, ExplainChangeDisplaySettingsFlags(dwflags), sInfo); + } + + if(dxw.Windowize) + return MyChangeDisplaySettings("ChangeDisplaySettingsExW", TRUE, lpDevMode, dwflags); + else + return (*pChangeDisplaySettingsExW)(lpszDeviceName, lpDevMode, hwnd, dwflags, lParam); +} + +static HDC WINAPI sGetDC(HWND hwnd, char *ApiName) +{ + // to do: add parameter and reference to pGDIGetDCEx to merge properly GetDC and GetDCEx + HDC ret; + HWND lochwnd; + + if(!dxw.IsFullScreen() || (dxw.dwFlags6 & SHAREDDC)) return(*pGDIGetDC)(hwnd); + + lochwnd=hwnd; + + if (dxw.IsRealDesktop(hwnd)) { + OutTraceDW("%s: desktop remapping hwnd=%x->%x\n", ApiName, hwnd, dxw.GethWnd()); + lochwnd=dxw.GethWnd(); + } + + //if(bFlippedDC) { + // ret = dxw.AcquireSharedDC(hwnd); + // if(ret) return ret; + //} + + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + ret=(*pGDIGetDC)(lochwnd); + break; + case GDIMODE_EMULATED: + ret=dxw.AcquireEmulatedDC(lochwnd); + break; + } + + if(ret){ + OutTraceDW("%s: hwnd=%x ret=%x\n", ApiName, lochwnd, ret); + } + else{ + int err; + err=GetLastError(); + OutTraceE("%s ERROR: hwnd=%x err=%d at %d\n", ApiName, lochwnd, err, __LINE__); + if((err==ERROR_INVALID_WINDOW_HANDLE) && (lochwnd!=hwnd)){ + ret=(*pGDIGetDC)(hwnd); + if(ret) + OutTraceDW("%s: hwnd=%x ret=%x\n", ApiName, hwnd, ret); + else + OutTraceE("%s ERROR: hwnd=%x err=%d at %d\n", ApiName, hwnd, GetLastError(), __LINE__); + } + } + + return ret; +} + +HDC WINAPI extGDIGetDC(HWND hwnd) +{ + OutTraceDW("GDI.GetDC: hwnd=%x\n", hwnd); + return sGetDC(hwnd, "GDI.GetDC"); +} + +HDC WINAPI extGDIGetDCEx(HWND hwnd, HRGN hrgnClip, DWORD flags) +{ + // used by Star Wars Shadow of the Empire + OutTraceDW("GDI.GetDCEx: hwnd=%x hrgnClip=%x flags=%x(%s)\n", hwnd, hrgnClip, flags, ExplainGetDCExFlags(flags)); + return sGetDC(hwnd, "GDI.GetDCEx"); +} + +HDC WINAPI extGDIGetWindowDC(HWND hwnd) +{ + OutTraceDW("GDI.GetWindowDC: hwnd=%x\n", hwnd); + + // if not fullscreen or not desktop win, just proxy the call + if(!dxw.IsFullScreen() || !dxw.IsDesktop(hwnd)){ + HDC ret; + ret=(*pGDIGetWindowDC)(hwnd); + OutTraceDW("GDI.GetWindowDC: hwnd=%x hdc=%x\n", hwnd, ret); + return ret; + } + + return sGetDC(hwnd, "GDI.GetWindowDC"); +} + +int WINAPI extGDIReleaseDC(HWND hwnd, HDC hDC) +{ + int res; + + OutTraceDW("GDI.ReleaseDC: hwnd=%x hdc=%x\n", hwnd, hDC); + + if (dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); + if(hwnd == 0) return(TRUE); + + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + res=(*pGDIReleaseDC)(hwnd, hDC); + break; + case GDIMODE_EMULATED: + res=dxw.ReleaseEmulatedDC(hwnd); + break; + } + + if (!res) OutTraceE("GDI.ReleaseDC ERROR: err=%d at %d\n", GetLastError(), __LINE__); + return(res); +} + +HDC WINAPI extBeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint) +{ + HDC hdc; + + OutTraceDW("GDI.BeginPaint: hwnd=%x lpPaint=%x FullScreen=%x\n", hwnd, lpPaint, dxw.IsFullScreen()); + + // avoid access to real desktop + if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); + + hdc=(*pBeginPaint)(hwnd, lpPaint); + + // if not in fullscreen mode, that's all! + if(!dxw.IsFullScreen()) return hdc; + + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + // on CLIENTREMAPPING, resize the paint area to virtual screen size + //if(dxw.dwFlags1 & CLIENTREMAPPING) lpPaint->rcPaint=dxw.GetScreenRect(); + if(dxw.dwFlags1 & CLIENTREMAPPING) dxw.UnmapClient(&(lpPaint->rcPaint)); + break; + case GDIMODE_EMULATED: + HDC EmuHDC; + EmuHDC = dxw.AcquireEmulatedDC(hwnd); + lpPaint->hdc=EmuHDC; + hdc = EmuHDC; + break; + } + + + OutTraceDW("GDI.BeginPaint: hdc=%x rcPaint=(%d,%d)-(%d,%d)\n", + hdc, lpPaint->rcPaint.left, lpPaint->rcPaint.top, lpPaint->rcPaint.right, lpPaint->rcPaint.bottom); + return hdc; +} + +BOOL WINAPI extEndPaint(HWND hwnd, const PAINTSTRUCT *lpPaint) +{ + BOOL ret; + + OutTraceDW("GDI.EndPaint: hwnd=%x lpPaint=%x lpPaint.hdc=%x lpPaint.rcpaint=(%d,%d)-(%d-%d)\n", + hwnd, lpPaint, lpPaint->hdc, lpPaint->rcPaint.left, lpPaint->rcPaint.top, lpPaint->rcPaint.right, lpPaint->rcPaint.bottom); + + // if not fullscreen or not desktop win, just proxy the call + if(!dxw.IsFullScreen() || (dxw.dwFlags6 & SHAREDDC)){ + ret=(*pEndPaint)(hwnd, lpPaint); + return ret; + } + + // avoid access to real desktop + if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); + + switch(dxw.GDIEmulationMode){ + case GDIMODE_EMULATED: + ret=dxw.ReleaseEmulatedDC(hwnd); + break; + default: + ret=(*pEndPaint)(hwnd, lpPaint); + break; + } + + if(ret){ + OutTraceDW("GDI.EndPaint: hwnd=%x ret=%x\n", hwnd, ret); + } + else{ + OutTraceE("GDI.EndPaint ERROR: err=%d at %d\n", GetLastError(), __LINE__); + } + + return ret; +} + +HWND WINAPI extCreateDialogIndirectParam(HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM lParamInit) +{ + HWND RetHWND; + BOOL FullScreen; + FullScreen = dxw.IsFullScreen(); + OutTraceDW("CreateDialogIndirectParam: hInstance=%x lpTemplate=(style=%x extstyle=%x items=%d pos=(%d,%d) size=(%dx%d)) hWndParent=%x lpDialogFunc=%x lParamInit=%x\n", + hInstance, + lpTemplate->style, lpTemplate->dwExtendedStyle, lpTemplate->cdit, lpTemplate->x, lpTemplate->y, lpTemplate->cx, lpTemplate->cy, + hWndParent, lpDialogFunc, lParamInit); + if(dxw.IsFullScreen() && hWndParent==NULL) hWndParent=dxw.GethWnd(); + dxw.SetFullScreen(FALSE); + RetHWND=(*pCreateDialogIndirectParam)(hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit); + dxw.SetFullScreen(FullScreen); + + // v2.02.73: redirect lpDialogFunc only when it is nor NULL + if( lpDialogFunc && + !(dxw.dwFlags6 & NOWINDOWHOOKS)){ // v2.03.41 - debug option + dxwws.PutProc(RetHWND, (WNDPROC)lpDialogFunc); + if(!(*pSetWindowLongA)(RetHWND, DWL_DLGPROC, (LONG)extDialogWindowProc)) + OutTraceE("SetWindowLong: ERROR err=%d at %d\n", GetLastError(), __LINE__); + } + + OutTraceDW("CreateDialogIndirectParam: hwnd=%x\n", RetHWND); + return RetHWND; +} + +HWND WINAPI extCreateDialogParam(HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM lParamInit) +{ + HWND RetHWND; + BOOL FullScreen; + FullScreen = dxw.IsFullScreen(); + OutTraceDW("CreateDialogParam: hInstance=%x lpTemplateName=%s hWndParent=%x lpDialogFunc=%x lParamInit=%x\n", + hInstance, sTemplateName(lpTemplateName), hWndParent, lpDialogFunc, lParamInit); + if(hWndParent==NULL) hWndParent=dxw.GethWnd(); + dxw.SetFullScreen(FALSE); + RetHWND=(*pCreateDialogParam)(hInstance, lpTemplateName, hWndParent, lpDialogFunc, lParamInit); + dxw.SetFullScreen(FullScreen); + + // v2.02.73: redirect lpDialogFunc only when it is nor NULL: fix for "LEGO Stunt Rally" + if( lpDialogFunc && + !(dxw.dwFlags6 & NOWINDOWHOOKS)){ // v2.03.41 - debug option + dxwws.PutProc(RetHWND, (WNDPROC)lpDialogFunc); + if(!(*pSetWindowLongA)(RetHWND, DWL_DLGPROC, (LONG)extDialogWindowProc)) + OutTraceE("SetWindowLong: ERROR err=%d at %d\n", GetLastError(), __LINE__); + } + + OutTraceDW("CreateDialogParam: hwnd=%x\n", RetHWND); + return RetHWND; +} + +BOOL WINAPI extMoveWindow(HWND hwnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint) +{ + BOOL ret; + OutTraceDW("MoveWindow: hwnd=%x xy=(%d,%d) size=(%d,%d) repaint=%x fullscreen=%x\n", + hwnd, X, Y, nWidth, nHeight, bRepaint, dxw.IsFullScreen()); + + if(dxw.Windowize){ + if(dxw.IsDesktop(hwnd)){ + // v2.1.93: happens in "Emergency Fighters for Life" ... + // what is the meaning of this? is it related to video stretching? + OutTraceDW("MoveWindow: prevent moving desktop win\n"); + return TRUE; + } + + if((hwnd==dxw.GethWnd()) || (hwnd==dxw.hParentWnd)){ + OutTraceDW("MoveWindow: prevent moving main win\n"); + return TRUE; + } + + if (dxw.IsFullScreen() && (dxw.dwFlags1 & CLIENTREMAPPING)){ + POINT upleft={0,0}; + RECT client; + BOOL isChild; + (*pClientToScreen)(dxw.GethWnd(),&upleft); + (*pGetClientRect)(dxw.GethWnd(),&client); + if ((*pGetWindowLongA)(hwnd, GWL_STYLE) & WS_CHILD){ + isChild=TRUE; + // child coordinate adjustement + X = (X * client.right) / dxw.GetScreenWidth(); + Y = (Y * client.bottom) / dxw.GetScreenHeight(); + nWidth = (nWidth * client.right) / dxw.GetScreenWidth(); + nHeight = (nHeight * client.bottom) / dxw.GetScreenHeight(); + } + else { + isChild=FALSE; + // regular win coordinate adjustement + X = upleft.x + (X * client.right) / dxw.GetScreenWidth(); + Y = upleft.y + (Y * client.bottom) / dxw.GetScreenHeight(); + nWidth = (nWidth * client.right) / dxw.GetScreenWidth(); + nHeight = (nHeight * client.bottom) / dxw.GetScreenHeight(); + } + OutTraceDW("MoveWindow: DEBUG client=(%d,%d) screen=(%d,%d)\n", + client.right, client.bottom, dxw.GetScreenWidth(), dxw.GetScreenHeight()); + OutTraceDW("MoveWindow: hwnd=%x child=%x relocated to xy=(%d,%d) size=(%d,%d)\n", + hwnd, isChild, X, Y, nWidth, nHeight); + } + else{ + if((X==0)&&(Y==0)&&(nWidth==dxw.GetScreenWidth())&&(nHeight==dxw.GetScreenHeight())){ + // evidently, this was supposed to be a fullscreen window.... + RECT screen; + DWORD dwStyle; + POINT upleft = {0,0}; + (*pGetClientRect)(dxw.GethWnd(),&screen); + (*pClientToScreen)(dxw.GethWnd(),&upleft); + if((dwStyle=(*pGetWindowLongA)(hwnd, GWL_STYLE)) && WS_CHILDWINDOW){ + // Big main child window: see "Reah" + X=Y=0; + } + else{ + // Regular big main window, usual case. + X=upleft.x; + Y=upleft.y; + } + nWidth=screen.right; + nHeight=screen.bottom; + OutTraceDW("MoveWindow: fixed BIG win pos=(%d,%d) size=(%d,%d)\n", X, Y, nWidth, nHeight); + } + } + } + + ret=(*pMoveWindow)(hwnd, X, Y, nWidth, nHeight, bRepaint); + if(!ret) OutTraceE("MoveWindow: ERROR err=%d at %d\n", GetLastError(), __LINE__); + return ret; +} + +int WINAPI extShowCursor(BOOL bShow) +{ + static int iFakeCounter; + int ret; + + OutTraceC("ShowCursor: bShow=%x\n", bShow); + if (bShow){ + if (dxw.dwFlags1 & HIDEHWCURSOR){ + iFakeCounter++; + OutTraceC("ShowCursor: HIDEHWCURSOR ret=%x\n", iFakeCounter); + return iFakeCounter; + } + } + else { + if (dxw.dwFlags2 & SHOWHWCURSOR){ + iFakeCounter--; + OutTraceC("ShowCursor: SHOWHWCURSOR ret=%x\n", iFakeCounter); + return iFakeCounter; + } + } + ret=(*pShowCursor)(bShow); + OutTraceC("ShowCursor: ret=%x\n", ret); + return ret; +} + +BOOL WINAPI extDrawFocusRect(HDC hDC, const RECT *lprc) +{ + return TRUE; +} + +BOOL WINAPI extScrollDC(HDC hDC, int dx, int dy, const RECT *lprcScroll, const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate) +{ + MessageBox(0, "ScrollDC", "to do", MB_OK); + return TRUE; +} + +HWND WINAPI extGetTopWindow(HWND hwnd) +{ + HWND ret; + OutTraceDW("GetTopWindow: hwnd=%x fullscreen=%x\n", hwnd, dxw.IsFullScreen()); + // a fullscreen program is supposed to be always top Z-order on the desktop! + ret = (dxw.IsFullScreen() && dxw.IsDesktop(hwnd)) ? dxw.GethWnd() : (*pGetTopWindow)(hwnd); + OutTraceDW("GetTopWindow: ret=%x\n", ret); + return ret; +} + +LONG WINAPI extTabbedTextOutA(HDC hdc, int X, int Y, LPCTSTR lpString, int nCount, int nTabPositions, const LPINT lpnTabStopPositions, int nTabOrigin) +{ + BOOL res; + OutTraceDW("TabbedTextOut: hdc=%x xy=(%d,%d) nCount=%d nTP=%d nTOS=%d str=(%d)\"%s\"\n", + hdc, X, Y, nCount, nTabPositions, nTabOrigin, lpString); + + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + if(sdc.GetPrimaryDC(hdc)){ + res=(*pTabbedTextOutA)(sdc.GetHdc(), X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + sdc.PutPrimaryDC(hdc); + return res; + } + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + break; + case GDIMODE_EMULATED: + if(dxw.IsVirtual(hdc)){ + X+=dxw.VirtualOffsetX; + Y+=dxw.VirtualOffsetY; + } + break; + default: + break; + } + OutTraceDW("TextOut: fixed dest=(%d,%d)\n", X, Y); + } + + res=(*pTabbedTextOutA)(hdc, X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + return res; +} + +BOOL WINAPI extDestroyWindow(HWND hWnd) +{ + // v2.02.43: "Empire Earth" builds test surfaces that must be destroyed! + // v2.03.20: "Prince of Persia 3D" destroys the main window that must be preserved! + BOOL res; + OutTraceB("DestroyWindow: hwnd=%x\n", hWnd); + if (hWnd == dxw.GethWnd()) { + if(dxw.dwFlags6 & NODESTROYWINDOW) { + OutTraceDW("DestroyWindow: do NOT destroy main hwnd=%x\n", hWnd); + return TRUE; + } + OutTraceDW("DestroyWindow: destroy main hwnd=%x\n", hWnd); + dxw.SethWnd(NULL); + } + if (hControlParentWnd && (hWnd == hControlParentWnd)) { + OutTraceDW("DestroyWindow: destroy control parent hwnd=%x\n", hWnd); + hControlParentWnd = NULL; + } + res=(*pDestroyWindow)(hWnd); + if(!res)OutTraceE("DestroyWindow: ERROR err=%d\n", GetLastError()); + return res; +} + +static char *ExplainTAAlign(UINT c) +{ + static char eb[256]; + unsigned int l; + strcpy(eb,"TA_"); + strcat(eb, (c & TA_UPDATECP) ? "UPDATECP+" : "NOUPDATECP+"); + strcat(eb, (c & TA_RIGHT) ? (((c & TA_CENTER) == TA_CENTER) ? "CENTER+" : "RIGHT+") : "LEFT+"); + strcat(eb, (c & TA_BOTTOM) ? "BOTTOM+" : "TOP+"); + if ((c & TA_BASELINE)==TA_BASELINE) strcat(eb, "BASELINE+"); + if (c & TA_RTLREADING) strcat(eb, "RTLREADING+"); + l=strlen(eb); + eb[l-1]=0; + return(eb); +} + +static char *ExplainDTFormat(UINT c) +{ + static char eb[256]; + unsigned int l; + strcpy(eb,"DT_"); + if(!(c & (DT_CENTER|DT_RIGHT))) strcat(eb, "LEFT+"); + if(c & DT_CENTER) strcat(eb, "CENTER+"); + if(c & DT_RIGHT) strcat(eb, "RIGHT+"); + if(!(c & (DT_VCENTER|DT_BOTTOM))) strcat(eb, "TOP+"); + if(c & DT_VCENTER) strcat(eb, "VCENTER+"); + if(c & DT_BOTTOM) strcat(eb, "BOTTOM+"); + if(c & DT_WORDBREAK) strcat(eb, "WORDBREAK+"); + if(c & DT_SINGLELINE) strcat(eb, "SINGLELINE+"); + if(c & DT_EXPANDTABS) strcat(eb, "EXPANDTABS+"); + if(c & DT_TABSTOP) strcat(eb, "TABSTOP+"); + if(c & DT_NOCLIP) strcat(eb, "NOCLIP+"); + if(c & DT_EXTERNALLEADING) strcat(eb, "EXTERNALLEADING+"); + if(c & DT_CALCRECT) strcat(eb, "CALCRECT+"); + if(c & DT_NOPREFIX) strcat(eb, "NOPREFIX+"); + if(c & DT_INTERNAL) strcat(eb, "INTERNAL+"); + l=strlen(eb); + eb[l-1]=0; + return(eb); +} + +BOOL gFixed; + +int WINAPI extDrawTextA(HDC hdc, LPCTSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat) +{ + int ret; + OutTraceDW("DrawText: hdc=%x rect=(%d,%d)-(%d,%d) Format=%x(%s) Text=(%d)\"%s\"\n", + hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, uFormat, ExplainDTFormat(uFormat), nCount, lpchText); + + gFixed = TRUE; // semaphore to avoid multiple scaling with HOT patching + if(dxw.IsToRemap(hdc)){ + + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + if(sdc.GetPrimaryDC(hdc)){ + ret=(*pDrawText)(sdc.GetHdc(), lpchText, nCount, lpRect, uFormat); + sdc.PutPrimaryDC(hdc, lpRect->left, lpRect->top, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top); + return ret; + } + break; + case GDIMODE_STRETCHED: + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawText: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + ret=(*pDrawText)(hdc, lpchText, nCount, lpRect, uFormat); + dxw.UnmapClient((RECT *)lpRect); + OutTraceDW("DrawText: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + break; + default: + ret=(*pDrawText)(hdc, lpchText, nCount, lpRect, uFormat); + break; + } + } + else { + ret=(*pDrawText)(hdc, lpchText, nCount, lpRect, uFormat); + } + gFixed = FALSE; + + // if nCount is zero, DrawRect returns 0 as text heigth, but this is not an error! (ref. "Imperialism II") + if(nCount && !ret) OutTraceE("DrawText: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} + +int WINAPI extDrawTextExA(HDC hdc, LPTSTR lpchText, int nCount, LPRECT lpRect, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) +{ + int ret; + OutTraceDW("DrawTextEx: hdc=%x rect=(%d,%d)-(%d,%d) DTFormat=%x Text=(%d)\"%s\"\n", + hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, dwDTFormat, nCount, lpchText); + if (IsDebug){ + if(lpDTParams) + OutTrace("DTParams: size=%d (L,R)margins=(%d,%d) TabLength=%d lDrawn=%d\n", + lpDTParams->cbSize, lpDTParams->iLeftMargin, lpDTParams->iRightMargin, + lpDTParams->iTabLength, lpDTParams->uiLengthDrawn); + else + OutTrace("DTParams: NULL\n"); + } + + gFixed = TRUE; // semaphore to avoid multiple scaling with HOT patching + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + if(sdc.GetPrimaryDC(hdc)){ + ret=(*pDrawTextEx)(sdc.GetHdc(), lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + sdc.PutPrimaryDC(hdc, lpRect->left, lpRect->top, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top); + return ret; + } + break; + case GDIMODE_STRETCHED: + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawText: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + ret=(*pDrawTextEx)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + dxw.UnmapClient((RECT *)lpRect); + OutTraceDW("DrawText: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + break; + default: + ret=(*pDrawTextEx)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + break; + } + } + else { + ret=(*pDrawTextEx)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + } + gFixed = FALSE; + + // if nCount is zero, DrawRect returns 0 as text heigth, but this is not an error! (ref. "Imperialism II") + if(nCount && !ret) OutTraceE("DrawText: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} + +BOOL WINAPI extCloseWindow(HWND hWnd) +{ + // from MSDN: Minimizes (but does not destroy) the specified window. + BOOL res; + OutTraceB("CloseWindow: hwnd=%x\n", hWnd); + if (hWnd == dxw.GethWnd()) { + OutTraceDW("CloseWindow: close main hwnd=%x\n", hWnd); + // do not delete the reference to main hWnd. + } + res=(*pCloseWindow)(hWnd); + if(!res)OutTraceE("CloseWindow: ERROR err=%d\n", GetLastError()); + return res; +} + +BOOL WINAPI extSetSysColors(int cElements, const INT *lpaElements, const COLORREF *lpaRgbValues) +{ + // v2.02.32: added to avoid SysColors changes by "Western Front" + BOOL ret; + OutTraceDW("SetSysColors: Elements=%d\n", cElements); + + if(dxw.dwFlags3 & LOCKSYSCOLORS) return TRUE; + + ret=(*pSetSysColors)(cElements, lpaElements, lpaRgbValues); + if(!ret) OutTraceE("SetSysColors: ERROR er=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extUpdateWindow(HWND hwnd) +{ + BOOL ret; + OutTraceDW("UpdateWindow: hwnd=%x\n", hwnd); + + if(dxw.Windowize && dxw.IsRealDesktop(hwnd)){ + OutTraceDW("UpdateWindow: remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); + hwnd=dxw.GethWnd(); + } + + ret=(*pUpdateWindow)(hwnd); + if(!ret) OutTraceE("UpdateWindow: ERROR er=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extRedrawWindow(HWND hWnd, const RECT *lprcUpdate, HRGN hrgnUpdate, UINT flags) +{ + RECT rcUpdate; + BOOL ret; + + OutTraceDW("RedrawWindow: hwnd=%x flags=%x\n", hWnd, flags); + + rcUpdate = *lprcUpdate; + // avoid redrawing the whole desktop + if(dxw.Windowize && dxw.IsRealDesktop(hWnd)) hWnd=dxw.GethWnd(); + if(dxw.IsFullScreen()){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + rcUpdate = dxw.MapClientRect((LPRECT)lprcUpdate); + break; + default: + break; + } + } + + ret = (*pRedrawWindow)(hWnd, &rcUpdate, hrgnUpdate, flags); + if(ret) OutTraceE("RedrawWindow ERROR: err=%d\n", GetLastError()); + return ret; +} + + +BOOL WINAPI extGetWindowPlacement(HWND hwnd, WINDOWPLACEMENT *lpwndpl) +{ + BOOL ret; + OutTraceDW("GetWindowPlacement: hwnd=%x\n", hwnd); + + if(dxw.IsRealDesktop(hwnd)){ + OutTraceDW("GetWindowPlacement: remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); + hwnd=dxw.GethWnd(); + } + + ret=(*pGetWindowPlacement)(hwnd, lpwndpl); + OutTraceDW("GetWindowPlacement: flags=%x showCmd=%x MinPosition=(%d,%d) MaxPosition=(%d,%d) NormalPosition=(%d,%d)-(%d,%d)\n", + lpwndpl->flags, lpwndpl->showCmd, + lpwndpl->ptMinPosition.x, lpwndpl->ptMinPosition.y, + lpwndpl->ptMaxPosition.x, lpwndpl->ptMaxPosition.y, + lpwndpl->rcNormalPosition.left, lpwndpl->rcNormalPosition.top, lpwndpl->rcNormalPosition.right, lpwndpl->rcNormalPosition.bottom); + + switch (lpwndpl->showCmd){ + case SW_SHOW: + if (dxw.IsFullScreen()){ + lpwndpl->showCmd = SW_MAXIMIZE; + OutTraceDW("GetWindowPlacement: forcing SW_MAXIMIZE state\n"); + } + break; + } + if(!ret) OutTraceE("GetWindowPlacement: ERROR er=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extSetWindowPlacement(HWND hwnd, WINDOWPLACEMENT *lpwndpl) +{ + BOOL ret; + OutTraceDW("SetWindowPlacement: hwnd=%x\n", hwnd); + + if(dxw.IsRealDesktop(hwnd)){ + OutTraceDW("SetWindowPlacement: remapping hwnd=%x->%x\n", hwnd, dxw.GethWnd()); + hwnd=dxw.GethWnd(); + } + + OutTraceDW("SetWindowPlacement: flags=%x showCmd=%x MinPosition=(%d,%d) MaxPosition=(%d,%d) NormalPosition=(%d,%d)-(%d,%d)\n", + lpwndpl->flags, lpwndpl->showCmd, + lpwndpl->ptMinPosition.x, lpwndpl->ptMinPosition.y, + lpwndpl->ptMaxPosition.x, lpwndpl->ptMaxPosition.y, + lpwndpl->rcNormalPosition.left, lpwndpl->rcNormalPosition.top, lpwndpl->rcNormalPosition.right, lpwndpl->rcNormalPosition.bottom); + + switch (lpwndpl->showCmd){ + case SW_MAXIMIZE: + if (dxw.IsFullScreen()){ + lpwndpl->showCmd = SW_SHOW; + OutTraceDW("SetWindowPlacement: forcing SW_SHOW state\n"); + } + break; + } + ret=(*pSetWindowPlacement)(hwnd, lpwndpl); + if(!ret) OutTraceE("SetWindowPlacement: ERROR er=%d\n", GetLastError()); + return ret; +} + +HWND WINAPI extSetCapture(HWND hwnd) +{ + HWND ret; + OutTraceDW("SetCapture: hwnd=%x\n", hwnd); + ret=(*pSetCapture)(hwnd); + OutTraceDW("SetCapture: ret=%x\n", ret); + return ret; +} + +HWND WINAPI extGetActiveWindow(void) +{ + HWND ret; + ret=(*pGetActiveWindow)(); + if(dxw.Windowize && dxw.IsFullScreen()) { + OutTraceDW("GetActiveWindow: ret=%x->%x\n", ret, dxw.GethWnd()); + return dxw.GethWnd(); + } + return ret; +} + +HWND WINAPI extGetForegroundWindow(void) +{ + HWND ret; + ret=(*pGetForegroundWindow)(); + if(dxw.Windowize && dxw.IsFullScreen()) { + OutTraceDW("GetForegroundWindow: ret=%x->%x\n", ret, dxw.GethWnd()); + return dxw.GethWnd(); + } + return ret; +} + +BOOL WINAPI extIsWindowVisible(HWND hwnd) +{ + BOOL ret; + ret=(*pIsWindowVisible)(hwnd); + OutTraceB("IsWindowVisible: hwnd=%x ret=%x\n", hwnd, ret); + if(dxw.IsDesktop(hwnd) && !ret){ + OutTraceDW("IsWindowVisible: FORCING ret=TRUE\n"); + ret=TRUE; + } + return ret; +} + +BOOL WINAPI extSystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni) +{ + BOOL ret; + OutTraceDW("SystemParametersInfoA: Action=%x Param=%x WinIni=%x\n", uiAction, uiParam, fWinIni); + switch(uiAction){ + case SPI_SETKEYBOARDDELAY: + case SPI_SETKEYBOARDSPEED: + OutTraceDW("SystemParametersInfoA: bypass action=%x\n", uiAction); + return TRUE; + break; + } + ret=(*pSystemParametersInfoA)(uiAction, uiParam, pvParam, fWinIni); + if(uiAction==SPI_GETWORKAREA){ + LPRECT cli = (LPRECT)pvParam; + *cli = dxw.GetScreenRect(); + OutTraceDW("SystemParametersInfoA: resized client workarea rect=(%d,%d)-(%d,%d)\n", cli->left, cli->top, cli->right, cli->bottom); + } + return ret; +} + +BOOL WINAPI extSystemParametersInfoW(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni) +{ + BOOL ret; + OutTraceDW("SystemParametersInfoW: Action=%x Param=%x WinIni=%x\n", uiAction, uiParam, fWinIni); + switch(uiAction){ + case SPI_SETKEYBOARDDELAY: + case SPI_SETKEYBOARDSPEED: + OutTraceDW("SystemParametersInfoW: bypass action=%x\n", uiAction); + return TRUE; + break; + } + ret=(*pSystemParametersInfoW)(uiAction, uiParam, pvParam, fWinIni); + if(uiAction==SPI_GETWORKAREA){ + LPRECT cli = (LPRECT)pvParam; + *cli = dxw.GetScreenRect(); + OutTraceDW("SystemParametersInfoW: resized client workarea rect=(%d,%d)-(%d,%d)\n", cli->left, cli->top, cli->right, cli->bottom); + } + return ret; +} + +#undef OutTraceDW +#define OutTraceDW OutTrace + +UINT_PTR WINAPI extSetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) +{ + UINT uShiftedElapse; + UINT_PTR ret; + // beware: the quicker the time flows, the more the time clicks are incremented, + // and the lesser the pauses must be lasting! Shift operations are reverted in + // GetSystemTime vs. Sleep or SetTimer + uShiftedElapse = dxw.StretchTime(uElapse); + OutTraceDW("SetTimer: hwnd=%x TimerFunc=%x elapse=%d->%d timeshift=%d\n", hWnd, lpTimerFunc, uElapse, uShiftedElapse, dxw.TimeShift); + ret = (*pSetTimer)(hWnd, nIDEvent, uShiftedElapse, lpTimerFunc); + if(ret) dxw.PushTimer(hWnd, ret, uElapse, lpTimerFunc); + OutTraceDW("SetTimer: IDEvent=%x ret=%x\n", nIDEvent, ret); + return ret; +} + +BOOL WINAPI extKillTimer(HWND hWnd, UINT_PTR uIDEvent) +{ + BOOL ret; + OutTraceDW("KillTimer: hwnd=%x IDEvent=%x\n", hWnd, uIDEvent); + ret = (*pKillTimer)(hWnd, uIDEvent); + OutTraceDW("KillTimer: ret=%x\n", ret); + if(ret) dxw.PopTimer(hWnd, uIDEvent); + return ret; +} + +BOOL WINAPI extGetUpdateRect(HWND hWnd, LPRECT lpRect, BOOL bErase) +{ + BOOL ret; + OutTraceDW("GetUpdateRect: hwnd=%x Erase=%x\n", hWnd, bErase); + ret = (*pGetUpdateRect)(hWnd, lpRect, bErase); + if(ret){ + OutTraceDW("GetUpdateRect: rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + if(dxw.IsFullScreen()){ + dxw.UnmapClient(lpRect); + OutTraceDW("GetUpdateRect: FIXED rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + } + else + OutTraceE("GetUpdateRect ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extGetCursorInfo(PCURSORINFO pci) +{ + BOOL ret; + OutTraceDW("GetCursorInfo\n"); + ret = (*pGetCursorInfo)(pci); + if(ret){ + OutTraceDW("GetCursorInfo: flags=%x hcursor=%x pos=(%d,%d)\n", pci->flags, pci->hCursor, pci->ptScreenPos.x, pci->ptScreenPos.y); + if(dxw.IsFullScreen()){ + dxw.UnmapClient(&(pci->ptScreenPos)); + OutTraceDW("GetCursorInfo: FIXED pos=(%d,%d)\n", pci->ptScreenPos.x, pci->ptScreenPos.y); + } + } + else + OutTraceE("GetCursorInfo ERROR: err=%d\n", GetLastError()); + return ret; +} + +// --- to be hooked .... + +HWND WINAPI extWindowFromPoint(POINT Point) +{ + HWND ret; + OutTraceDW("WindowFromPoint: point=(%d,%d)\n", Point.x, Point.y); + if(dxw.IsFullScreen()){ + dxw.UnmapWindow(&Point); + OutTraceDW("WindowFromPoint: FIXED point=(%d,%d)\n", Point.x, Point.y); + } + ret = (*pWindowFromPoint)(Point); + OutTraceDW("WindowFromPoint: hwnd=%x\n", ret); + return ret; +} + +HWND WINAPI extChildWindowFromPoint(HWND hWndParent, POINT Point) +{ + HWND ret; + OutTraceDW("ChildWindowFromPoint: hWndParent=%x point=(%d,%d)\n", hWndParent, Point.x, Point.y); + if(dxw.IsDesktop(hWndParent) && dxw.IsFullScreen() && dxw.Windowize){ + dxw.UnmapClient(&Point); + OutTraceDW("ChildWindowFromPoint: FIXED point=(%d,%d)\n", Point.x, Point.y); + } + ret = (*pChildWindowFromPoint)(hWndParent, Point); + OutTraceDW("ChildWindowFromPoint: hwnd=%x\n", ret); + return ret; +} + +HWND WINAPI extChildWindowFromPointEx(HWND hWndParent, POINT Point, UINT uFlags) +{ + HWND ret; + OutTraceDW("ChildWindowFromPoint: hWndParent=%x point=(%d,%d) flags=%x\n", hWndParent, Point.x, Point.y, uFlags); + if(dxw.IsDesktop(hWndParent) && dxw.IsFullScreen() && dxw.Windowize){ + dxw.UnmapClient(&Point); + OutTraceDW("ChildWindowFromPointEx: FIXED point=(%d,%d)\n", Point.x, Point.y); + } + ret = (*pChildWindowFromPointEx)(hWndParent, Point, uFlags); + OutTraceDW("ChildWindowFromPointEx: hwnd=%x\n", ret); + return ret; +} + +BOOL extGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpmi, GetMonitorInfo_Type pGetMonitorInfo) +{ + BOOL res; + OutTraceDW("GetMonitorInfo: hMonitor=%x mi=MONITORINFO%s\n", hMonitor, lpmi->cbSize==sizeof(MONITORINFO)?"":"EX"); + res=(*pGetMonitorInfo)(hMonitor, lpmi); + //v2.03.15 - must fix the coordinates also in case of error: that may depend on the windowed mode. + if(dxw.Windowize){ + OutTraceDW("GetMonitorInfo: FIX Work=(%d,%d)-(%d,%d) Monitor=(%d,%d)-(%d,%d) -> (%d,%d)-(%d,%d)\n", + lpmi->rcWork.left, lpmi->rcWork.top, lpmi->rcWork.right, lpmi->rcWork.bottom, + lpmi->rcMonitor.left, lpmi->rcMonitor.top, lpmi->rcMonitor.right, lpmi->rcMonitor.bottom, + 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight()); + lpmi->rcWork = dxw.GetScreenRect(); + lpmi->rcMonitor = dxw.GetScreenRect(); + res=TRUE; + } + else + OutTraceE("GetMonitorInfo: ERROR err=%d\n", GetLastError()); + + return res; +} + +BOOL WINAPI extGetMonitorInfoA(HMONITOR hMonitor, LPMONITORINFO lpmi) +{ + return extGetMonitorInfo(hMonitor, lpmi, pGetMonitorInfoA); +} + +BOOL WINAPI extGetMonitorInfoW(HMONITOR hMonitor, LPMONITORINFO lpmi) +{ + return extGetMonitorInfo(hMonitor, lpmi, pGetMonitorInfoW); +} + +int WINAPI extGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase) +{ + int regionType; + regionType=(*pGetUpdateRgn)(hWnd, hRgn, bErase); + OutTraceDW("GetUpdateRgn: hwnd=%x hrgn=%x erase=%x regionType=%x(%s)\n", + hWnd, hRgn, bErase, regionType, ExplainRegionType(regionType)); + + if(dxw.IsFullScreen()){ + if(regionType == SIMPLEREGION){ + RECT rc; + if(!pGetRgnBox) pGetRgnBox=GetRgnBox; + regionType = (*pGetRgnBox)(hRgn, &rc); + OutTraceDW("GetUpdateRgn: regionType=%x(%s) box=(%d,%d)-(%d,%d)\n", + regionType, ExplainRegionType(regionType), rc.left, rc.top, rc.right, rc.bottom); + if(regionType == SIMPLEREGION){ + dxw.UnmapClient(&rc); + if(SetRectRgn(hRgn, rc.left, rc.top, rc.right, rc.bottom )){ + // success + OutTraceDW("GetUpdateRgn: FIXED box=(%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + } + } + } +#if 0 + if(regionType == COMPLEXREGION){ + RECT rc; + if(!pGetRgnBox) pGetRgnBox=GetRgnBox; + regionType = (*pGetRgnBox)(hRgn, &rc); + OutTraceDW("GetUpdateRgn: regionType=%x(%s) box=(%d,%d)-(%d,%d)\n", + regionType, ExplainRegionType(regionType), rc.left, rc.top, rc.right, rc.bottom); + if(regionType == COMPLEXREGION){ + //dxw.UnmapClient(&rc); + //if(SetRectRgn(hRgn, rc.left, rc.top, rc.right, rc.bottom )){ + if(SetRectRgn(hRgn, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight())){ + // success + OutTraceDW("GetUpdateRgn: FIXED box=(%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + } + } + } +#endif + } + + return regionType; +} + +#ifdef TRACEPALETTE +UINT WINAPI extGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, RGBQUAD *pColors) +{ + UINT ret; + OutTraceDW("GetDIBColorTable: hdc=%x start=%d entries=%d\n", hdc, uStartIndex, cEntries); + + //if((OBJ_DC == GetObjectType(hdc)) && (dxw.dwFlags1 & EMULATESURFACE)){ + // //extern PALETTEENTRY PalEntries[256]; + // extern DWORD *PaletteEntries; + // if((uStartIndex+cEntries) > 256) cEntries = 256 - uStartIndex; + // for(UINT i=0; i 256) cEntries = 256 - uStartIndex; + // for(UINT i=0; ileft, lpRect->top, lpRect->right, lpRect->bottom); + else + OutTrace("ValidateRect: hwnd=%x rect=NULL\n", hWnd); + } + ret = (*pValidateRect)(hWnd, lpRect); + return ret; +} + +int WINAPI extGetWindowTextA(HWND hWnd, LPTSTR lpString, int nMaxCount) +{ + // purpose of this wrapped call is to clear the FPS indicator (format " ~ (%d FPS)") + // from the window title, if present. It crashes games such as "Panzer General 3 Scorched Earth" + // when FPS on window title is activated. + int ret; + OutTraceDW("GetWindowTextA: hwnd=%x MaxCount=%d\n", hWnd, nMaxCount); + ret=(*pGetWindowTextA)(hWnd, lpString, nMaxCount); + if(ret) OutTraceDW("GetWindowTextA: ret=%d String=\"%s\"\n", ret, lpString); + if (ret && (dxw.dwFlags2 & SHOWFPS) && dxw.ishWndFPS(hWnd)){ + char *p; + p=strstr(lpString, " ~ ("); + if(p){ + *p = NULL; + ret = strlen(lpString); + OutTraceDW("GetWindowTextA: FIXED ret=%d String=\"%s\"\n", ret, lpString); + } + } + return ret; +} +#endif + +BOOL WINAPI extBringWindowToTop(HWND hwnd) +{ + BOOL res; + OutTraceDW("BringWindowToTop: hwnd=%x\n", hwnd); + if(dxw.dwFlags5 & UNLOCKZORDER) return TRUE; + res=(*pBringWindowToTop)(hwnd); + return res; +} + +BOOL WINAPI extSetForegroundWindow(HWND hwnd) +{ + BOOL res; + OutTraceDW("SetForegroundWindow: hwnd=%x\n", hwnd); + if(dxw.dwFlags5 & UNLOCKZORDER) return TRUE; + res=(*pSetForegroundWindow)(hwnd); + return res; +} + +/* +HOOKPROC glpMouseHookProcessFunction; +LRESULT CALLBACK extMouseHookProc(int code, WPARAM wParam, LPARAM lParam) +{ + LRESULT ret; + OutTrace("HookProc intercepted: code=%x wParam=%x lParam=%x\n", code, wParam, lParam); + MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam; + if (pMouseStruct != NULL){ + dxw.UnmapWindow(&(pMouseStruct->pt)); + } + ret= (*glpMouseHookProcessFunction)(code, wParam, lParam); + return ret; +} +*/ + +HOOKPROC glpMessageHookProcessFunction; + +LRESULT CALLBACK extMessageHookProc(int code, WPARAM wParam, LPARAM lParam) +{ + LRESULT ret; + OutTrace("MessageHookProc: code=%x wParam=%x lParam=%x\n", code, wParam, lParam); + MSG * pMessage = (MSG *)lParam; + ret = NULL; + if(pMessage){ + UINT message = pMessage->message; + if ((message >= 0x600) || // custom messages + ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST)) || // keyboard messages + ((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST)) // mouse messages + ) + ret = (*glpMessageHookProcessFunction)(code, wParam, lParam); + } + return ret; +} + +HHOOK WINAPI extSetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId) +{ + HHOOK ret; + if(dxw.dwFlags5 & EASPORTSHACK){ + if(idHook == WH_MOUSE) return NULL; + if(idHook == WH_GETMESSAGE) { + glpMessageHookProcessFunction = lpfn; + lpfn=extMessageHookProc; + } + } + // v2.03.39: "One Must Fall Battlegrounds" keyboard fix + if((idHook == WH_KEYBOARD) && (dwThreadId == NULL)) dwThreadId = GetCurrentThreadId(); + + ret=(*pSetWindowsHookEx)(idHook, lpfn, hMod, dwThreadId); + + return ret; +} + + +HRESULT WINAPI extMessageBoxTimeoutA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwMilliseconds) +{ + HRESULT res; + if(1) dwMilliseconds=1000; + res=(*pMessageBoxTimeoutA)(hWnd, lpText, lpCaption, uType, wLanguageId, dwMilliseconds); + return res; +} + +HRESULT WINAPI extMessageBoxTimeoutW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwMilliseconds) +{ + HRESULT res; + if(1) dwMilliseconds=1000; + res=(*pMessageBoxTimeoutW)(hWnd, lpText, lpCaption, uType, wLanguageId, dwMilliseconds); + return res; +} + +HDESK WINAPI extCreateDesktop( LPCTSTR lpszDesktop, LPCTSTR lpszDevice, DEVMODE *pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa) +{ + //OutTrace("CreateDesktop: SUPPRESS Desktop=%s Device=%s flags=%x access=%x\n", lpszDesktop, lpszDevice, dwFlags, dwDesiredAccess); + OutTraceDW("CreateDesktop: SUPPRESS flags=%x access=%x\n", dwFlags, dwDesiredAccess); + return (HDESK)0xDEADBEEF; // fake handle + //return (HDESK)NULL; // fake handle +} + +BOOL WINAPI extSwitchDesktop(HDESK hDesktop) +{ + OutTraceDW("SwitchDesktop: SUPPRESS hDesktop=%x\n", hDesktop); + return TRUE; +} + +HDESK WINAPI extOpenDesktop(LPTSTR lpszDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess) +{ + OutTraceDW("CreateDesktop: SUPPRESS flags=%x access=%x\n", dwFlags, dwDesiredAccess); + return (HDESK)0xDEADBEEF; // fake handle + //return (HDESK)NULL; // fake handle +} + +BOOL WINAPI extCloseDesktop(HDESK hDesktop) +{ + OutTraceDW("CloseDesktop: SUPPRESS hDesktop=%x\n", hDesktop); + return TRUE; +} + +INT_PTR WINAPI extDialogBoxParamA(HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +{ + BOOL ret, FullScreen; + FullScreen = dxw.IsFullScreen(); + OutTraceDW("DialogBoxParamA: FullScreen=%x TemplateName=\"%s\" WndParent=%x\n", + FullScreen, sTemplateName(lpTemplateName), hWndParent); + dxw.SetFullScreen(FALSE); + ret = (*pDialogBoxParamA)(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); + dxw.SetFullScreen(FullScreen); + OutTraceDW("DialogBoxParamA: ret=%x\n", ret); + return ret; +} + +BOOL WINAPI extIsZoomed(HWND hWnd) +{ + BOOL ret; + ret = (*pIsZoomed)(hWnd); + OutTraceDW("IsZoomed: hwnd=%x ret=%x\n", hWnd, ret); + //if(dxw.IsFullScreen()) ret = FALSE; + return ret; +} + +BOOL WINAPI extIsIconic(HWND hWnd) +{ + BOOL ret; + ret = (*pIsIconic)(hWnd); + OutTraceDW("IsIconic: hwnd=%x ret=%x\n", hWnd, ret); + //return FALSE; + return ret; +} + +BOOL extScrollWindow(HWND hWnd, int XAmount, int YAmount, const RECT *lpRect, const RECT *lpClipRect) +{ + RECT Rect, ClipRect; + BOOL res; + + OutTraceDW("ScrollWindow: hwnd=%x amount=(%d,%d) rect=(%d,%d)-(%d,%d) clip=(%d,%d)-(%d,%d)\n", + hWnd, XAmount, YAmount, + lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, + lpClipRect->left, lpClipRect->top, lpClipRect->right, lpClipRect->bottom); + + Rect = *lpRect; + ClipRect = *lpClipRect; + if(dxw.Windowize && dxw.IsFullScreen()){ + dxw.MapClient(&XAmount, &YAmount); + dxw.MapClient(&Rect); + dxw.MapClient(&ClipRect); + } + + res=(*pScrollWindow)(hWnd, XAmount, YAmount, (const RECT *)&Rect, (const RECT *)&ClipRect); + if(!res) OutTraceE("ScrollWindow ERROR: err=%d\n", GetLastError()); + return res; +} + +#if 0 +// avoid invalidating whole desktop!!! +BOOL InvalidateRgn( + _In_ HWND hWnd, + _In_ HRGN hRgn, + _In_ BOOL bErase +); + +#endif + +HWND WINAPI extGetParent(HWND hWnd) +{ + HWND ret; + + ret = (*pGetParent)(hWnd); + OutTraceB("GetParent: hwnd=%x ret=%x\n", hWnd, ret); + + if(dxw.IsFullScreen()){ + if(ret == dxw.GethWnd()) { + OutTraceDW("GetParent: setting desktop reached\n"); + ret = 0; // simulate reaching the desktop + } + } + + return ret; +} + +BOOL WINAPI extInvalidateRgn(HWND hWnd, HRGN hRgn, BOOL bErase) +{ + OutTraceDW("InvalidateRgn: hwnd=%x hrgn=%x erase=%x\n", hWnd, hRgn, bErase); + + if(dxw.IsFullScreen()){ + if (dxw.IsRealDesktop(hWnd) && bErase) return true; + } + + return (*pInvalidateRgn)(hWnd, hRgn, bErase); +} diff --git a/dll/user32.cpp b/dll/user32.cpp index 8d0adf1..425ce1b 100644 --- a/dll/user32.cpp +++ b/dll/user32.cpp @@ -11,17 +11,16 @@ #include "dxhook.h" #include "hddraw.h" #include "dxhelper.h" +#include "shareddc.hpp" +#include #define FIXCHILDSIZE FALSE +#define _Warn(s) MessageBox(0, s, "to do", MB_ICONEXCLAMATION) BOOL IsChangeDisplaySettingsHotPatched = FALSE; extern BOOL bFlippedDC; extern HDC hFlippedDC; -//typedef BOOL (WINAPI *ValidateRect_Type)(HWND, const RECT *); -//BOOL WINAPI extValidateRect(HWND, const RECT *); -//ValidateRect_Type pValidateRect = NULL; - //typedef BOOL (WINAPI *EnumDisplayMonitors_Type)(HDC, LPCRECT, MONITORENUMPROC, LPARAM); //EnumDisplayMonitors_Type pEnumDisplayMonitors = NULL; //BOOL WINAPI extEnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM); @@ -62,10 +61,39 @@ HDESK WINAPI extOpenDesktop(LPTSTR, DWORD, BOOL, ACCESS_MASK); typedef BOOL (WINAPI *CloseDesktop_Type)(HDESK); CloseDesktop_Type pCloseDesktop = NULL; BOOL WINAPI extCloseDesktop(HDESK); - +typedef int (WINAPI *ValidateRect_Type)(HWND, const RECT *); +ValidateRect_Type pValidateRect = NULL; +int WINAPI extValidateRect(HWND, const RECT *); +typedef BOOL (WINAPI *ScrollWindow_Type)(HWND, int, int, const RECT *, const RECT *); +ScrollWindow_Type pScrollWindow = NULL; +BOOL extScrollWindow(HWND, int, int, const RECT *, const RECT *); typedef INT_PTR (WINAPI *DialogBoxParamA_Type)(HINSTANCE, LPCTSTR, HWND, DLGPROC, LPARAM); DialogBoxParamA_Type pDialogBoxParamA = NULL; INT_PTR WINAPI extDialogBoxParamA(HINSTANCE, LPCTSTR, HWND, DLGPROC, LPARAM); +typedef HWND (WINAPI *GetParent_Type)(HWND); +GetParent_Type pGetParent = NULL; +HWND WINAPI extGetParent(HWND); +typedef BOOL (WINAPI *InvalidateRgn_Type)(HWND, HRGN, BOOL); +InvalidateRgn_Type pInvalidateRgn = NULL; +BOOL WINAPI extInvalidateRgn(HWND, HRGN, BOOL); +typedef BOOL (WINAPI *InvertRect_Type)(HDC, const RECT *); +InvertRect_Type pInvertRect = NULL; +BOOL WINAPI extInvertRect(HDC, const RECT *); +typedef BOOL (WINAPI *ScrollDC_Type)(HDC, int, int, const RECT *, const RECT *, HRGN, LPRECT); +ScrollDC_Type pScrollDC = NULL; +BOOL WINAPI extScrollDC(HDC, int, int, const RECT *, const RECT *, HRGN, LPRECT); +typedef BOOL (WINAPI *DrawIcon_Type)(HDC hDC, int X, int Y, HICON hIcon); +DrawIcon_Type pDrawIcon = NULL; +BOOL WINAPI extDrawIcon(HDC hDC, int X, int Y, HICON hIcon); +typedef BOOL (WINAPI *DrawIconEx_Type)(HDC, int, int, HICON, int, int, UINT, HBRUSH, UINT); +DrawIconEx_Type pDrawIconEx = NULL; +BOOL WINAPI extDrawIconEx(HDC, int, int, HICON, int, int, UINT, HBRUSH, UINT); +typedef BOOL (WINAPI *DrawCaption_Type)(HWND, HDC, LPCRECT, UINT); +DrawCaption_Type pDrawCaption = NULL; +BOOL WINAPI extDrawCaption(HWND, HDC, LPCRECT, UINT); +typedef BOOL (WINAPI *PaintDesktop_Type)(HDC); +PaintDesktop_Type pPaintDesktop = NULL; +BOOL WINAPI extPaintDesktop(HDC); #ifdef TRACEPALETTE typedef UINT (WINAPI *GetDIBColorTable_Type)(HDC, UINT, UINT, RGBQUAD *); @@ -86,7 +114,7 @@ static HookEntry_Type Hooks[]={ {HOOK_HOT_CANDIDATE, "ChangeDisplaySettingsExW", (FARPROC)NULL, (FARPROC *)&pChangeDisplaySettingsExW, (FARPROC)extChangeDisplaySettingsExW}, {HOOK_HOT_CANDIDATE, "GetMonitorInfoA", (FARPROC)GetMonitorInfoA, (FARPROC *)&pGetMonitorInfoA, (FARPROC)extGetMonitorInfoA}, {HOOK_HOT_CANDIDATE, "GetMonitorInfoW", (FARPROC)GetMonitorInfoW, (FARPROC *)&pGetMonitorInfoW, (FARPROC)extGetMonitorInfoW}, - {HOOK_IAT_CANDIDATE, "ShowCursor", (FARPROC)ShowCursor, (FARPROC *)&pShowCursor, (FARPROC)extShowCursor}, + {HOOK_HOT_CANDIDATE, "ShowCursor", (FARPROC)ShowCursor, (FARPROC *)&pShowCursor, (FARPROC)extShowCursor}, {HOOK_IAT_CANDIDATE, "CreateDialogIndirectParamA", (FARPROC)CreateDialogIndirectParamA, (FARPROC *)&pCreateDialogIndirectParam, (FARPROC)extCreateDialogIndirectParam}, {HOOK_IAT_CANDIDATE, "CreateDialogParamA", (FARPROC)CreateDialogParamA, (FARPROC *)&pCreateDialogParam, (FARPROC)extCreateDialogParam}, {HOOK_IAT_CANDIDATE, "MoveWindow", (FARPROC)MoveWindow, (FARPROC *)&pMoveWindow, (FARPROC)extMoveWindow}, @@ -99,6 +127,8 @@ static HookEntry_Type Hooks[]={ {HOOK_HOT_CANDIDATE, "CreateWindowExW", (FARPROC)CreateWindowExW, (FARPROC *)&pCreateWindowExW, (FARPROC)extCreateWindowExW}, {HOOK_IAT_CANDIDATE, "RegisterClassExA", (FARPROC)RegisterClassExA, (FARPROC *)&pRegisterClassExA, (FARPROC)extRegisterClassExA}, {HOOK_IAT_CANDIDATE, "RegisterClassA", (FARPROC)RegisterClassA, (FARPROC *)&pRegisterClassA, (FARPROC)extRegisterClassA}, + {HOOK_IAT_CANDIDATE, "RegisterClassExW", (FARPROC)RegisterClassExW, (FARPROC *)&pRegisterClassExW, (FARPROC)extRegisterClassExW}, + {HOOK_IAT_CANDIDATE, "RegisterClassW", (FARPROC)RegisterClassW, (FARPROC *)&pRegisterClassW, (FARPROC)extRegisterClassW}, {HOOK_HOT_CANDIDATE, "GetSystemMetrics", (FARPROC)GetSystemMetrics, (FARPROC *)&pGetSystemMetrics, (FARPROC)extGetSystemMetrics}, {HOOK_HOT_CANDIDATE, "GetDesktopWindow", (FARPROC)GetDesktopWindow, (FARPROC *)&pGetDesktopWindow, (FARPROC)extGetDesktopWindow}, {HOOK_IAT_CANDIDATE, "CloseWindow", (FARPROC)NULL, (FARPROC *)&pCloseWindow, (FARPROC)extCloseWindow}, @@ -127,7 +157,7 @@ static HookEntry_Type Hooks[]={ {HOOK_HOT_CANDIDATE, "ChildWindowFromPoint", (FARPROC)ChildWindowFromPoint, (FARPROC *)&pChildWindowFromPoint, (FARPROC)extChildWindowFromPoint}, {HOOK_HOT_CANDIDATE, "ChildWindowFromPointEx", (FARPROC)ChildWindowFromPointEx, (FARPROC *)&pChildWindowFromPointEx, (FARPROC)extChildWindowFromPointEx}, {HOOK_HOT_CANDIDATE, "WindowFromPoint", (FARPROC)WindowFromPoint, (FARPROC *)&pWindowFromPoint, (FARPROC)extWindowFromPoint}, - {HOOK_HOT_CANDIDATE, "SetWindowsHookExA", (FARPROC)SetWindowsHookExA, (FARPROC *)&pSetWindowsHookEx, (FARPROC)extSetWindowsHookEx}, + {HOOK_HOT_REQUIRED , "SetWindowsHookExA", (FARPROC)SetWindowsHookExA, (FARPROC *)&pSetWindowsHookEx, (FARPROC)extSetWindowsHookEx}, //{HOOK_HOT_CANDIDATE, "MessageBoxTimeoutA", (FARPROC)NULL, (FARPROC *)&pMessageBoxTimeoutA, (FARPROC)extMessageBoxTimeoutA}, //{HOOK_HOT_CANDIDATE, "MessageBoxTimeoutW", (FARPROC)NULL, (FARPROC *)&pMessageBoxTimeoutW, (FARPROC)extMessageBoxTimeoutW}, @@ -144,52 +174,58 @@ static HookEntry_Type Hooks[]={ //{HOOK_IAT_CANDIDATE, "IsZoomed", (FARPROC)NULL, (FARPROC *)&pIsZoomed, (FARPROC)extIsZoomed}, //{HOOK_HOT_CANDIDATE, "IsIconic", (FARPROC)IsIconic, (FARPROC *)&pIsIconic, (FARPROC)extIsIconic}, + {HOOK_HOT_CANDIDATE, "ScrollDC", (FARPROC)NULL, (FARPROC *)&pScrollDC, (FARPROC)extScrollDC}, - {HOOK_HOT_CANDIDATE, "FillRect", (FARPROC)NULL, (FARPROC *)&pFillRect, (FARPROC)extFillRect}, - - {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator -}; - -static HookEntry_Type NoGDIHooks[]={ - {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator -}; - -static HookEntry_Type EmulateHooks[]={ - //{HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extGDIGetDC}, - //{HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)GetDCEx, (FARPROC *)&pGDIGetDCEx, (FARPROC)extGDIGetDCEx}, - //{HOOK_IAT_CANDIDATE, "GetWindowDC", (FARPROC)GetWindowDC, (FARPROC *)&pGDIGetWindowDC, (FARPROC)extGDIGetWindowDC}, - //{HOOK_IAT_CANDIDATE, "ReleaseDC", (FARPROC)ReleaseDC, (FARPROC *)&pGDIReleaseDC, (FARPROC)extGDIReleaseDC}, - //{HOOK_IAT_CANDIDATE, "InvalidateRect", (FARPROC)InvalidateRect, (FARPROC *)&pInvalidateRect, (FARPROC)extInvalidateRect}, - {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator -}; - -static HookEntry_Type ScaledHooks[]={ - {HOOK_IAT_CANDIDATE, "FrameRect", (FARPROC)NULL, (FARPROC *)&pFrameRect, (FARPROC)extFrameRect}, - {HOOK_IAT_CANDIDATE, "TabbedTextOutA", (FARPROC)TabbedTextOutA, (FARPROC *)&pTabbedTextOutA, (FARPROC)extTabbedTextOutA}, - {HOOK_IAT_CANDIDATE, "DrawTextA", (FARPROC)DrawTextA, (FARPROC *)&pDrawText, (FARPROC)extDrawTextA}, - {HOOK_IAT_CANDIDATE, "DrawTextExA", (FARPROC)DrawTextExA, (FARPROC *)&pDrawTextEx, (FARPROC)extDrawTextExA}, - //{HOOK_HOT_CANDIDATE, "FillRect", (FARPROC)NULL, (FARPROC *)&pFillRect, (FARPROC)extFillRect}, - //{HOOK_IAT_CANDIDATE, "GetDC", (FARPROC)GetDC, (FARPROC *)&pGDIGetDC, (FARPROC)extGDIGetDC}, - //{HOOK_IAT_CANDIDATE, "GetDCEx", (FARPROC)NULL, (FARPROC *)&pGDIGetDCEx, (FARPROC)extGDIGetDCEx}, - //{HOOK_IAT_CANDIDATE, "GetWindowDC", (FARPROC)GetWindowDC, (FARPROC *)&pGDIGetWindowDC, (FARPROC)extGDIGetWindowDC}, - //{HOOK_IAT_CANDIDATE, "ReleaseDC", (FARPROC)ReleaseDC, (FARPROC *)&pGDIReleaseDC, (FARPROC)extGDIReleaseDC}, - {HOOK_IAT_CANDIDATE, "InvalidateRect", (FARPROC)InvalidateRect, (FARPROC *)&pInvalidateRect, (FARPROC)extInvalidateRect}, - //{HOOK_IAT_CANDIDATE, "ValidateRect", (FARPROC)ValidateRect, (FARPROC *)&pValidateRect, (FARPROC)extValidateRect}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; static HookEntry_Type RemapHooks[]={ - {HOOK_IAT_CANDIDATE, "ScreenToClient", (FARPROC)ScreenToClient, (FARPROC *)&pScreenToClient, (FARPROC)extScreenToClient}, - {HOOK_IAT_CANDIDATE, "ClientToScreen", (FARPROC)ClientToScreen, (FARPROC *)&pClientToScreen, (FARPROC)extClientToScreen}, - {HOOK_IAT_CANDIDATE, "GetClientRect", (FARPROC)GetClientRect, (FARPROC *)&pGetClientRect, (FARPROC)extGetClientRect}, - {HOOK_IAT_CANDIDATE, "GetWindowRect", (FARPROC)GetWindowRect, (FARPROC *)&pGetWindowRect, (FARPROC)extGetWindowRect}, - {HOOK_IAT_CANDIDATE, "MapWindowPoints", (FARPROC)MapWindowPoints, (FARPROC *)&pMapWindowPoints, (FARPROC)extMapWindowPoints}, - {HOOK_IAT_CANDIDATE, "GetUpdateRgn", (FARPROC)GetUpdateRgn, (FARPROC *)&pGetUpdateRgn, (FARPROC)extGetUpdateRgn}, + {HOOK_HOT_CANDIDATE, "ScreenToClient", (FARPROC)ScreenToClient, (FARPROC *)&pScreenToClient, (FARPROC)extScreenToClient}, + {HOOK_HOT_CANDIDATE, "ClientToScreen", (FARPROC)ClientToScreen, (FARPROC *)&pClientToScreen, (FARPROC)extClientToScreen}, + {HOOK_HOT_CANDIDATE, "GetClientRect", (FARPROC)GetClientRect, (FARPROC *)&pGetClientRect, (FARPROC)extGetClientRect}, + {HOOK_HOT_CANDIDATE, "GetWindowRect", (FARPROC)GetWindowRect, (FARPROC *)&pGetWindowRect, (FARPROC)extGetWindowRect}, + {HOOK_HOT_CANDIDATE, "MapWindowPoints", (FARPROC)MapWindowPoints, (FARPROC *)&pMapWindowPoints, (FARPROC)extMapWindowPoints}, + {HOOK_HOT_CANDIDATE, "GetUpdateRgn", (FARPROC)GetUpdateRgn, (FARPROC *)&pGetUpdateRgn, (FARPROC)extGetUpdateRgn}, //{HOOK_IAT_CANDIDATE, "GetUpdateRect", (FARPROC)GetUpdateRect, (FARPROC *)&pGetUpdateRect, (FARPROC)extGetUpdateRect}, //{HOOK_IAT_CANDIDATE, "RedrawWindow", (FARPROC)RedrawWindow, (FARPROC *)&pRedrawWindow, (FARPROC)extRedrawWindow}, {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; +static HookEntry_Type SyscallHooks[]={ + {HOOK_IAT_CANDIDATE, "FrameRect", (FARPROC)FrameRect, (FARPROC *)&pFrameRect, (FARPROC)extFrameRect}, + {HOOK_IAT_CANDIDATE, "RedrawWindow", (FARPROC)RedrawWindow, (FARPROC *)&pRedrawWindow, (FARPROC)extRedrawWindow}, + {HOOK_IAT_CANDIDATE, "GetParent", (FARPROC)GetParent, (FARPROC *)&pGetParent, (FARPROC)extGetParent}, + {HOOK_HOT_CANDIDATE, "InvalidateRgn", (FARPROC)InvalidateRgn, (FARPROC *)&pInvalidateRgn, (FARPROC)extInvalidateRgn}, + {HOOK_IAT_CANDIDATE, "TabbedTextOutA", (FARPROC)TabbedTextOutA, (FARPROC *)&pTabbedTextOutA, (FARPROC)extTabbedTextOutA}, + {HOOK_IAT_CANDIDATE, "TabbedTextOutW", (FARPROC)TabbedTextOutW, (FARPROC *)&pTabbedTextOutW, (FARPROC)extTabbedTextOutW}, + {HOOK_IAT_CANDIDATE, "ScrollDC", (FARPROC)ScrollDC, (FARPROC *)&pScrollDC, (FARPROC)extScrollDC}, + {HOOK_IAT_CANDIDATE, "InvalidateRect", (FARPROC)InvalidateRect, (FARPROC *)&pInvalidateRect, (FARPROC)extInvalidateRect}, + {HOOK_IAT_CANDIDATE, "DrawTextA", (FARPROC)DrawTextA, (FARPROC *)&pDrawTextA, (FARPROC)extDrawTextA}, + {HOOK_IAT_CANDIDATE, "DrawTextExA", (FARPROC)DrawTextExA, (FARPROC *)&pDrawTextExA, (FARPROC)extDrawTextExA}, + {HOOK_IAT_CANDIDATE, "DrawTextW", (FARPROC)DrawTextW, (FARPROC *)&pDrawTextW, (FARPROC)extDrawTextW}, + {HOOK_IAT_CANDIDATE, "DrawTextExW", (FARPROC)DrawTextExW, (FARPROC *)&pDrawTextExW, (FARPROC)extDrawTextExW}, + {HOOK_HOT_CANDIDATE, "FillRect", (FARPROC)NULL, (FARPROC *)&pFillRect, (FARPROC)extFillRect}, + {HOOK_HOT_CANDIDATE, "InvertRect", (FARPROC)NULL, (FARPROC *)&pInvertRect, (FARPROC)extInvertRect}, + {HOOK_HOT_CANDIDATE, "DrawIcon", (FARPROC)NULL, (FARPROC *)&pDrawIcon, (FARPROC)extDrawIcon}, + {HOOK_HOT_CANDIDATE, "DrawIconEx", (FARPROC)NULL, (FARPROC *)&pDrawIconEx, (FARPROC)extDrawIconEx}, + {HOOK_HOT_CANDIDATE, "DrawCaption", (FARPROC)NULL, (FARPROC *)&pDrawCaption, (FARPROC)extDrawCaption}, + //TODO {HOOK_HOT_CANDIDATE, "DrawEdge", (FARPROC)NULL, (FARPROC *)&pDrawEdge, (FARPROC)extDrawEdge}, + //TODO {HOOK_HOT_CANDIDATE, "DrawFocusRect", (FARPROC)NULL, (FARPROC *)&pDrawFocusRect, (FARPROC)extDrawFocusRect}, + //TODO {HOOK_HOT_CANDIDATE, "DrawFrameControl", (FARPROC)NULL, (FARPROC *)&pDrawFrameControl, (FARPROC)extDrawFrameControl}, + //TODO {HOOK_HOT_CANDIDATE, "DrawStateA", (FARPROC)NULL, (FARPROC *)&pDrawStateA, (FARPROC)extDrawStateA}, + //TODO {HOOK_HOT_CANDIDATE, "DrawStateW", (FARPROC)NULL, (FARPROC *)&pDrawStateW, (FARPROC)extDrawStateW}, + //TODO {HOOK_HOT_CANDIDATE, "GrayStringA", (FARPROC)NULL, (FARPROC *)&pGrayStringA, (FARPROC)extGrayStringA}, + //TODO {HOOK_HOT_CANDIDATE, "GrayStringW", (FARPROC)NULL, (FARPROC *)&pGrayStringW, (FARPROC)extGrayStringW}, + //TODO {HOOK_HOT_CANDIDATE, "PaintDesktop", (FARPROC)NULL, (FARPROC *)&pPaintDesktop, (FARPROC)extPaintDesktop}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + +static HookEntry_Type ScaledHooks[]={ + {HOOK_IAT_CANDIDATE, "ValidateRect", (FARPROC)ValidateRect, (FARPROC *)&pValidateRect, (FARPROC)extValidateRect}, + {HOOK_IAT_CANDIDATE, "ScrollWindow", (FARPROC)ScrollWindow, (FARPROC *)&pScrollWindow, (FARPROC)extScrollWindow}, + {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator +}; + static HookEntry_Type PeekAllHooks[]={ {HOOK_IAT_CANDIDATE, "PeekMessageA", (FARPROC)NULL, (FARPROC *)&pPeekMessage, (FARPROC)extPeekMessage}, {HOOK_IAT_CANDIDATE, "PeekMessageW", (FARPROC)NULL, (FARPROC *)&pPeekMessage, (FARPROC)extPeekMessage}, @@ -230,39 +266,13 @@ static HookEntry_Type DesktopHooks[]={ // currently unused, needed for X-Files {HOOK_IAT_CANDIDATE, 0, NULL, 0, 0} // terminator }; -FARPROC Remap_user32_ProcAddress(LPCSTR proc, HMODULE hModule) -{ - FARPROC addr; - if (addr=RemapLibrary(proc, hModule, Hooks)) return addr; - if (dxw.dwFlags1 & CLIENTREMAPPING) if (addr=RemapLibrary(proc, hModule, RemapHooks)) return addr; - - if (dxw.dwFlags2 & GDISTRETCHED) - if (addr=RemapLibrary(proc, hModule, ScaledHooks)) return addr; - if (dxw.dwFlags3 & GDIEMULATEDC) - if (addr=RemapLibrary(proc, hModule, EmulateHooks)) return addr; - if (!(dxw.dwFlags2 & GDISTRETCHED) && !(dxw.dwFlags3 & GDIEMULATEDC)) - if (addr=RemapLibrary(proc, hModule, NoGDIHooks)) return addr; - if (dxw.dwFlags1 & (PREVENTMAXIMIZE|FIXWINFRAME|LOCKWINPOS|LOCKWINSTYLE)) - if (addr=RemapLibrary(proc, hModule, WinHooks)) return addr; - if ((dxw.dwFlags1 & (MODIFYMOUSE|SLOWDOWN|KEEPCURSORWITHIN)) || (dxw.dwFlags2 & KEEPCURSORFIXED)) - if (addr=RemapLibrary(proc, hModule, MouseHooks)) return addr; - if (dxw.dwFlags3 & PEEKALLMESSAGES) - if (addr=RemapLibrary(proc, hModule, PeekAllHooks)) return addr; - if((dxw.dwFlags2 & TIMESTRETCH) && (dxw.dwFlags4 & STRETCHTIMERS)) - if (addr=RemapLibrary(proc, hModule, TimeHooks)) return addr; - - return NULL; -} - static char *libname = "user32.dll"; void HookUser32(HMODULE hModule) { HookLibrary(hModule, Hooks, libname); - if (!(dxw.dwFlags2 & GDISTRETCHED) && !(dxw.dwFlags3 & GDIEMULATEDC)) - HookLibrary(hModule, NoGDIHooks, libname); - if (dxw.dwFlags3 & GDIEMULATEDC) HookLibrary(hModule, EmulateHooks, libname); + if (dxw.GDIEmulationMode != GDIMODE_NONE) HookLibrary(hModule, SyscallHooks, libname); if (dxw.dwFlags2 & GDISTRETCHED) HookLibrary(hModule, ScaledHooks, libname); if (dxw.dwFlags1 & CLIENTREMAPPING) HookLibrary(hModule, RemapHooks, libname); @@ -278,13 +288,34 @@ void HookUser32(HMODULE hModule) void HookUser32Init() { HookLibInit(Hooks); + HookLibInit(SyscallHooks); HookLibInit(ScaledHooks); - HookLibInit(EmulateHooks); HookLibInit(RemapHooks); HookLibInit(MouseHooks); HookLibInit(WinHooks); } +FARPROC Remap_user32_ProcAddress(LPCSTR proc, HMODULE hModule) +{ + FARPROC addr; + if (addr=RemapLibrary(proc, hModule, Hooks)) return addr; + if (dxw.dwFlags1 & CLIENTREMAPPING) if (addr=RemapLibrary(proc, hModule, RemapHooks)) return addr; + if (dxw.GDIEmulationMode != GDIMODE_NONE) if(addr=RemapLibrary(proc, hModule, SyscallHooks)) return addr; + + if (dxw.dwFlags2 & GDISTRETCHED) + if (addr=RemapLibrary(proc, hModule, ScaledHooks)) return addr; + if (dxw.dwFlags1 & (PREVENTMAXIMIZE|FIXWINFRAME|LOCKWINPOS|LOCKWINSTYLE)) + if (addr=RemapLibrary(proc, hModule, WinHooks)) return addr; + if ((dxw.dwFlags1 & (MODIFYMOUSE|SLOWDOWN|KEEPCURSORWITHIN)) || (dxw.dwFlags2 & KEEPCURSORFIXED)) + if (addr=RemapLibrary(proc, hModule, MouseHooks)) return addr; + if (dxw.dwFlags3 & PEEKALLMESSAGES) + if (addr=RemapLibrary(proc, hModule, PeekAllHooks)) return addr; + if((dxw.dwFlags2 & TIMESTRETCH) && (dxw.dwFlags4 & STRETCHTIMERS)) + if (addr=RemapLibrary(proc, hModule, TimeHooks)) return addr; + + return NULL; +} + /* ------------------------------------------------------------------------------ */ // auxiliary (static) functions /* ------------------------------------------------------------------------------ */ @@ -601,19 +632,20 @@ static LRESULT WINAPI FixWindowProc(char *ApiName, HWND hwnd, UINT Msg, WPARAM w BOOL WINAPI extInvalidateRect(HWND hwnd, RECT *lpRect, BOOL bErase) { - if(lpRect) - OutTraceDW("InvalidateRect: hwnd=%x rect=(%d,%d)-(%d,%d) erase=%x\n", - hwnd, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, bErase); - else - OutTraceDW("InvalidateRect: hwnd=%x rect=NULL erase=%x\n", - hwnd, bErase); + if(IsTraceDW){ + char sRect[81]; + if(lpRect) sprintf(sRect, "(%d,%d)-(%d,%d)", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + else strcpy(sRect, "NULL"); + OutTrace("InvalidateRect: hwnd=%x rect=%s erase=%x\n", hwnd, sRect, bErase); + } - if(dxw.IsFullScreen()) { + if(dxw.IsFullScreen()) { switch(dxw.GDIEmulationMode){ case GDIMODE_STRETCHED: + case GDIMODE_SHAREDDC: + case GDIMODE_EMULATED: if(lpRect) dxw.MapClient(lpRect); break; - case GDIMODE_EMULATED: default: break; } @@ -957,6 +989,9 @@ BOOL WINAPI extGetCursorPos(LPPOINT lppoint) GetHookInfo()->CursorY=(short)lppoint->y; OutTraceC("GetCursorPos: FIXED pos=(%d,%d)->(%d,%d)\n", prev.x, prev.y, lppoint->x, lppoint->y); + if((dxw.dwFlags1 & HIDEHWCURSOR) && dxw.IsFullScreen()) while((*pShowCursor)(0) >= 0); + if(dxw.dwFlags2 & SHOWHWCURSOR) while((*pShowCursor)(1) < 0); + return res; } @@ -1154,6 +1189,7 @@ BOOL WINAPI extGetWindowRect(HWND hwnd, LPRECT lpRect) return ret; } + int WINAPI extMapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints) { UINT pi; @@ -1180,14 +1216,22 @@ int WINAPI extMapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT ret=(*pMapWindowPoints)(hWndFrom, hWndTo, lpPoints, cPoints); // v2.03.16: now must scale every point (fixes "NBA Live 99") // v2.03.18: in some cases it should not! "New Your Race"... - for(pi=0; pilpszClassName, lpwcx->style, ExplainStyle(lpwcx->style), lpwcx->lpfnWndProc, lpwcx->cbClsExtra, lpwcx->cbWndExtra, lpwcx->hInstance); - return (*pRegisterClassExA)(lpwcx); + ret = (*pRegisterClassExA)(lpwcx); + OutTraceDW("RegisterClassExA: atom=%x\n", ret); + return ret; } -ATOM WINAPI extRegisterClassA(WNDCLASS *lpwcx) +ATOM WINAPI extRegisterClassA(WNDCLASSA *lpwcx) { + ATOM ret; // referenced by Syberia, together with RegisterClassExA - OutTraceDW("RegisterClass: PROXED ClassName=%s style=%x(%s) WndProc=%x cbClsExtra=%d cbWndExtra=%d hInstance=%x\n", + OutTraceDW("RegisterClassA: PROXED ClassName=%s style=%x(%s) WndProc=%x cbClsExtra=%d cbWndExtra=%d hInstance=%x\n", lpwcx->lpszClassName, lpwcx->style, ExplainStyle(lpwcx->style), lpwcx->lpfnWndProc, lpwcx->cbClsExtra, lpwcx->cbWndExtra, lpwcx->hInstance); - return (*pRegisterClassA)(lpwcx); + ret = (*pRegisterClassA)(lpwcx); + OutTraceDW("RegisterClassA: atom=%x\n", ret); + return ret; +} + +ATOM WINAPI extRegisterClassExW(WNDCLASSEXW *lpwcx) +{ + ATOM ret; + OutTraceDW("RegisterClassExW: PROXED ClassName=%ls style=%x(%s) WndProc=%x cbClsExtra=%d cbWndExtra=%d hInstance=%x\n", + lpwcx->lpszClassName, lpwcx->style, ExplainStyle(lpwcx->style), lpwcx->lpfnWndProc, lpwcx->cbClsExtra, lpwcx->cbWndExtra, lpwcx->hInstance); + ret = (*pRegisterClassExW)(lpwcx); + OutTraceDW("RegisterClassExW: atom=%x\n", ret); + return ret; +} + +ATOM WINAPI extRegisterClassW(WNDCLASSW *lpwcx) +{ + ATOM ret; + OutTraceDW("RegisterClassW: PROXED ClassName=%ls style=%x(%s) WndProc=%x cbClsExtra=%d cbWndExtra=%d hInstance=%x\n", + lpwcx->lpszClassName, lpwcx->style, ExplainStyle(lpwcx->style), lpwcx->lpfnWndProc, lpwcx->cbClsExtra, lpwcx->cbWndExtra, lpwcx->hInstance); + ret = (*pRegisterClassW)(lpwcx); + OutTraceDW("RegisterClassW: atom=%x\n", ret); + return ret; } static void HookChildWndProc(HWND hwnd, DWORD dwStyle, LPCTSTR ApiName) @@ -1302,7 +1372,7 @@ static void HookChildWndProc(HWND hwnd, DWORD dwStyle, LPCTSTR ApiName) (pWindowProc == extDialogWindowProc)){ // avoid recursions HWND Father; WNDPROC pFatherProc; - Father=GetParent(hwnd); + Father=(*pGetParent)(hwnd); pFatherProc=dxwws.GetProc(Father); OutTraceDW("%s: WndProc=%s father=%x WndProc=%x\n", ApiName, (pWindowProc == extWindowProc) ? "extWindowProc" : ((pWindowProc == extChildWindowProc) ? "extChildWindowProc" : "extDialogWindowProc"), @@ -1323,6 +1393,41 @@ static void HookChildWndProc(HWND hwnd, DWORD dwStyle, LPCTSTR ApiName) HWND hControlParentWnd = NULL; +// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms632679%28v=vs.85%29.aspx + +static BOOL IsFullscreenWindow( + void *lpClassName, + DWORD dwStyle, + DWORD dwExStyle, + HWND hWndParent, + int x, + int y, + int nWidth, + int nHeight) +{ + if (dwExStyle & WS_EX_CONTROLPARENT) return FALSE; // "Diablo" fix + if ((dwStyle & WS_CHILD) && (!dxw.IsDesktop(hWndParent))) return FALSE; // Diablo fix + // if maximized. + if(dwStyle & WS_MAXIMIZE) return TRUE; + // go through here only when WS_CHILD of desktop window + if((x == CW_USEDEFAULT) && (dwStyle & (WS_POPUP|WS_CHILD))) x = y = 0; + if(nWidth == CW_USEDEFAULT){ + if (dwStyle & (WS_POPUP|WS_CHILD)) nWidth = nHeight = 0; + else nWidth = dxw.GetScreenWidth() - x; + } + // msdn undocumented case: x,y=(-1000, CW_USEDEFAULT) w,h=(CW_USEDEFAULT,CW_USEDEFAULT) in "Imperialism" + if(nHeight == CW_USEDEFAULT){ + y = 0; + nHeight = dxw.GetScreenHeight(); + } + // if bigger than screen ... + if((x<=0)&& + (y<=0)&& + (nWidth>=(int)dxw.GetScreenWidth())&& + (nHeight>=(int)dxw.GetScreenHeight())) return TRUE; + return FALSE; +} + static HWND WINAPI extCreateWindowCommon( LPCTSTR ApiName, BOOL WideChar, @@ -1380,33 +1485,15 @@ static HWND WINAPI extCreateWindowCommon( // main win was 640x480 only! // v2.02.13: if it's a WS_CHILD window, don't reposition the x,y, placement for BIG win. // v2.02.30: fix (Fable - lost chapters) Fable creates a bigger win with negative x,y coordinates. -if ( - ( - ((x<=0)&&(y<=0)) - || - ((x==CW_USEDEFAULT)&&(y==CW_USEDEFAULT)) - ) - && - ( - ((nWidth>=(int)dxw.GetScreenWidth())&&(nHeight>=(int)dxw.GetScreenHeight())) - || - ((nWidth==CW_USEDEFAULT)&&(nHeight==CW_USEDEFAULT)) // good for Imperialism, but is it general? - ) - && - !(dwExStyle & WS_EX_CONTROLPARENT) // Diablo fix - && - !(dwStyle & WS_CHILD) // Diablo fix - ) - { + // v2.03.53: revised code, logic moved to IsFullscreenWindow + + if(IsFullscreenWindow(lpClassName, dwStyle, dwExStyle, hWndParent, x, y, nWidth, nHeight)){ RECT screen; POINT upleft = {0,0}; - // v2.02.30: fix (Fable - lost chapters) - if(nWidth==CW_USEDEFAULT) nWidth=dxw.GetScreenWidth(); - if(nHeight==CW_USEDEFAULT) nHeight=dxw.GetScreenHeight(); - // update virtual screen size if it has grown dxw.SetScreenSize(nWidth, nHeight); + // inserted some checks here, since the main window could be destroyed // or minimized (see "Jedi Outcast") so that you may get a dangerous // zero size. In this case, better renew the hWnd assignement and its coordinates. @@ -1427,12 +1514,8 @@ if ( OutTraceDW("%s: fixed BIG win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); } else { - // invalid parent coordinates: use initial placement, but leave the size. - // should also fix the window style and compensate for borders here? - // if (!(dwStyle & WS_CHILD)){ // commented out: can't be! see if condition - x=dxw.iPosX; - y=dxw.iPosY; - //} + x=dxw.iPosX; + y=dxw.iPosY; nWidth=dxw.iSizX; nHeight=dxw.iSizY; OutTraceDW("%s: renewed BIG win pos=(%d,%d) size=(%d,%d)\n", ApiName, x, y, nWidth, nHeight); @@ -1711,7 +1794,12 @@ static int HandleRect(char *ApiName, void *pFun, HDC hdc, const RECT *lprc, HBRU memcpy(&rc, lprc, sizeof(rc)); - if(dxw.IsRealDesktop(WindowFromDC(hdc))) { + // Be careful: when you call CreateCompatibleDC with NULL DC, it is created a memory DC + // with same characteristics as desktop. That would return true from the call to + // dxw.IsRealDesktop(WindowFromDC(hdc)) because WindowFromDC(hdc) is null. + // So, it's fundamental to check also the hdc type (OBJ_DC is a window's DC) + + if((dxw.IsRealDesktop(WindowFromDC(hdc)) && (OBJ_DC == (*pGetObjectType)(hdc)))) { HWND VirtualDesktop; VirtualDesktop=dxw.GethWnd(); if(VirtualDesktop==NULL){ @@ -1722,7 +1810,28 @@ static int HandleRect(char *ApiName, void *pFun, HDC hdc, const RECT *lprc, HBRU hdc=(*pGDIGetDC)(dxw.GethWnd()); } - if(!dxw.IsFullScreen()) { + if(dxw.IsToRemap(hdc)) { + if(rc.left < 0) rc.left = 0; + if(rc.top < 0) rc.top = 0; + if((DWORD)rc.right > dxw.GetScreenWidth()) rc.right = dxw.GetScreenWidth(); + if((DWORD)rc.bottom > dxw.GetScreenHeight()) rc.bottom = dxw.GetScreenHeight(); + + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + res=(*(FillRect_Type)pFun)(sdc.GetHdc(), &rc, hbr); + sdc.PutPrimaryDC(hdc, TRUE, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + return res; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&rc); + OutTraceDW("%s: fixed rect=(%d,%d)-(%d,%d)\n", ApiName, rc.left, rc.top, rc.right, rc.bottom); + break; + default: + break; + } + } + else { // when not in fullscreen mode, just proxy the call // but check coordinates: some games may use excessive coordinates: see "Premier Manager 98" RECT client; @@ -1735,18 +1844,7 @@ static int HandleRect(char *ApiName, void *pFun, HDC hdc, const RECT *lprc, HBRU if(rc.bottom > client.bottom) rc.bottom=client.bottom; OutTraceDW("%s: remapped hdc from hwnd=%x to rect=(%d,%d)-(%d,%d)\n", ApiName, hwnd, rc.left, rc.top, rc.right, rc.bottom); } - else { - if(OBJ_DC == GetObjectType(hdc)){ - if(rc.left < 0) rc.left = 0; - if(rc.top < 0) rc.top = 0; - if((DWORD)rc.right > dxw.GetScreenWidth()) rc.right = dxw.GetScreenWidth(); - if((DWORD)rc.bottom > dxw.GetScreenHeight()) rc.bottom = dxw.GetScreenHeight(); - dxw.MapClient(&rc); - OutTraceDW("%s: fixed rect=(%d,%d)-(%d,%d)\n", ApiName, rc.left, rc.top, rc.right, rc.bottom); - } - } - //res=(*pFillRect)(hdc, &rc, hbr); res=(*(FillRect_Type)pFun)(hdc, &rc, hbr); return res; } @@ -1761,6 +1859,55 @@ int WINAPI extFrameRect(HDC hdc, const RECT *lprc, HBRUSH hbr) return HandleRect("FramelRect", (void *)pFrameRect, hdc, lprc, hbr); } +BOOL WINAPI extInvertRect(HDC hdc, const RECT *lprc) +{ + int res; + RECT rc; + OutTraceDW("InvertRect: hdc=%x rect=(%d,%d)-(%d,%d)\n", hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); + + memcpy(&rc, lprc, sizeof(rc)); + + if(dxw.IsToRemap(hdc)) { + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + res=(*pInvertRect)(sdc.GetHdc(), &rc); + sdc.PutPrimaryDC(hdc, TRUE, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top); + return res; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&rc); + OutTraceDW("InvertRect: fixed rect=(%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + break; + default: + break; + } + } + + res=(*pInvertRect)(hdc, &rc); + return res; +} + +int WINAPI extValidateRect(HWND hwnd, const RECT *lprc) +{ + int res; + RECT rc; + + OutTraceDW("ValidateRect: hwnd=%x rect=(%d,%d)-(%d,%d)\n", + hwnd, lprc->left, lprc->top, lprc->right, lprc->bottom); + + memcpy(&rc, lprc, sizeof(rc)); + + if(dxw.IsFullScreen()) { + if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); + dxw.MapClient(&rc); + OutTraceDW("ValidateRect: fixed rect=(%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + } + + res=(*pValidateRect)(hwnd, &rc); + return res; +} + BOOL WINAPI extClipCursor(RECT *lpRectArg) { // reference: hooking and setting ClipCursor is mandatori in "Emergency: Fighters for Life" @@ -2003,18 +2150,15 @@ static HDC WINAPI sGetDC(HWND hwnd, char *ApiName) lochwnd=dxw.GethWnd(); } - if(bFlippedDC) { - ret = dxw.AcquireSharedDC(hwnd); - if(ret) return ret; - } - switch(dxw.GDIEmulationMode){ - case GDIMODE_STRETCHED: - ret=(*pGDIGetDC)(lochwnd); - break; case GDIMODE_EMULATED: ret=dxw.AcquireEmulatedDC(lochwnd); break; + case GDIMODE_STRETCHED: + case GDIMODE_SHAREDDC: + default: + ret=(*pGDIGetDC)(lochwnd); + break; } if(ret){ @@ -2073,15 +2217,15 @@ int WINAPI extGDIReleaseDC(HWND hwnd, HDC hDC) if (dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); if(hwnd == 0) return(TRUE); - if(bFlippedDC && (hDC == hFlippedDC)) return dxw.ReleaseSharedDC(hwnd, hDC); - switch(dxw.GDIEmulationMode){ - case GDIMODE_STRETCHED: - res=(*pGDIReleaseDC)(hwnd, hDC); - break; case GDIMODE_EMULATED: res=dxw.ReleaseEmulatedDC(hwnd); break; + case GDIMODE_STRETCHED: + case GDIMODE_SHAREDDC: + default: + res=(*pGDIReleaseDC)(hwnd, hDC); + break; } if (!res) OutTraceE("GDI.ReleaseDC ERROR: err=%d at %d\n", GetLastError(), __LINE__); @@ -2102,27 +2246,29 @@ HDC WINAPI extBeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint) // if not in fullscreen mode, that's all! if(!dxw.IsFullScreen()) return hdc; - - if(bFlippedDC) { - hdc = dxw.AcquireSharedDC(hwnd); - } - else { - switch(dxw.GDIEmulationMode){ - case GDIMODE_STRETCHED: - // on CLIENTREMAPPING, resize the paint area to virtual screen size - //if(dxw.dwFlags1 & CLIENTREMAPPING) lpPaint->rcPaint=dxw.GetScreenRect(); - if(dxw.dwFlags1 & CLIENTREMAPPING) dxw.UnmapClient(&(lpPaint->rcPaint)); - break; - case GDIMODE_EMULATED: - HDC EmuHDC; - EmuHDC = dxw.AcquireEmulatedDC(hwnd); - lpPaint->hdc=EmuHDC; - hdc = EmuHDC; - break; - } + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + if(dxw.dwFlags1 & CLIENTREMAPPING) dxw.UnmapClient(&(RECT)(lpPaint->rcPaint)); + break; + case GDIMODE_EMULATED: + HDC EmuHDC; + EmuHDC = dxw.AcquireEmulatedDC(hwnd); + lpPaint->hdc=EmuHDC; + hdc = EmuHDC; + break; + case GDIMODE_SHAREDDC: +#if 0 + sdc.GetPrimaryDC(hdc); + lpPaint->hdc = sdc.GetHdc(); + (*pBeginPaint)(hwnd, lpPaint); + lpPaint->hdc = hdc; + sdc.PutPrimaryDC(hdc, FALSE); +#endif + break; + default: + break; } - OutTraceDW("GDI.BeginPaint: hdc=%x rcPaint=(%d,%d)-(%d,%d)\n", hdc, lpPaint->rcPaint.left, lpPaint->rcPaint.top, lpPaint->rcPaint.right, lpPaint->rcPaint.bottom); return hdc; @@ -2136,21 +2282,33 @@ BOOL WINAPI extEndPaint(HWND hwnd, const PAINTSTRUCT *lpPaint) hwnd, lpPaint, lpPaint->hdc, lpPaint->rcPaint.left, lpPaint->rcPaint.top, lpPaint->rcPaint.right, lpPaint->rcPaint.bottom); // if not fullscreen or not desktop win, just proxy the call - if(!dxw.IsFullScreen() || !dxw.Windowize){ + if(!dxw.IsFullScreen()){ ret=(*pEndPaint)(hwnd, lpPaint); return ret; } // avoid access to real desktop if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); - switch(dxw.GDIEmulationMode){ - case GDIMODE_STRETCHED: - ret=(*pEndPaint)(hwnd, lpPaint); - break; case GDIMODE_EMULATED: ret=dxw.ReleaseEmulatedDC(hwnd); break; + case GDIMODE_SHAREDDC: +#if 1 + if(lpPaint) dxw.MapClient((LPRECT)&(lpPaint->rcPaint)); + ret=(*pEndPaint)(hwnd, lpPaint); +#else + PAINTSTRUCT Paint; + Paint = *lpPaint; + Paint.hdc = sdc.GetHdc(); + (*pEndPaint)(hwnd, &Paint); + if(lpPaint) dxw.MapClient((LPRECT)&(lpPaint->rcPaint)); + ret=(*pEndPaint)(hwnd, lpPaint); +#endif + break; + default: + ret=(*pEndPaint)(hwnd, lpPaint); + break; } if(ret){ @@ -2318,9 +2476,53 @@ BOOL WINAPI extDrawFocusRect(HDC hDC, const RECT *lprc) return TRUE; } -BOOL WINAPI extScrollDC(HDC hDC, int dx, int dy, const RECT *lprcScroll, const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate) +BOOL WINAPI extScrollDC(HDC hdc, int dx, int dy, const RECT *lprcScroll, const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate) { - return TRUE; + BOOL res; + if(IsTraceDW){ + char sRect[81]; + if(lprcScroll) sprintf(sRect, "(%d,%d)-(%d,%d)", lprcScroll->left, lprcScroll->top, lprcScroll->right, lprcScroll->bottom); + else strcpy(sRect, "NULL"); + char sClip[81]; + if(lprcClip) sprintf(sClip, "(%d,%d)-(%d,%d)", lprcClip->left, lprcClip->top, lprcClip->right, lprcClip->bottom); + else strcpy(sClip, "NULL"); + OutTraceDW("ScrollDC: hdc=%x dxy=(%d,%d) scrollrect=%s cliprect=%s hrgn=%x\n", + hdc, dx, dy, sRect, sClip, hrgnUpdate); + } + + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + res=(*pScrollDC)(sdc.GetHdc(), dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate); + sdc.PutPrimaryDC(hdc, TRUE, lprcUpdate->left, lprcUpdate->top, lprcUpdate->right-lprcUpdate->left, lprcUpdate->bottom-lprcUpdate->top); + return res; + break; + case GDIMODE_EMULATED: +#if 0 + // not working with 688(I) sonar !!! + if(dxw.IsVirtual(hdc)){ + RECT rcScroll, rcClip; + if(lprcScroll) { + rcScroll = *lprcScroll; + OffsetRect(&rcScroll, dxw.VirtualOffsetX, dxw.VirtualOffsetY); + } + if(lprcClip) { + rcClip = *lprcClip; + OffsetRect(&rcClip, dxw.VirtualOffsetX, dxw.VirtualOffsetY); + } + res=(*pScrollDC)(hdc, dx, dy, &rcScroll, &rcClip, hrgnUpdate, lprcUpdate); + return res; + } +#endif + break; + default: + break; + } + } + + res=(*pScrollDC)(hdc, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate); + return res; } HWND WINAPI extGetTopWindow(HWND hwnd) @@ -2339,15 +2541,66 @@ LONG WINAPI extTabbedTextOutA(HDC hdc, int X, int Y, LPCTSTR lpString, int nCoun OutTraceDW("TabbedTextOut: hdc=%x xy=(%d,%d) nCount=%d nTP=%d nTOS=%d str=(%d)\"%s\"\n", hdc, X, Y, nCount, nTabPositions, nTabOrigin, lpString); - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient(&X, &Y); - OutTraceDW("TextOut: fixed dest=(%d,%d)\n", X, Y); + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + res=(*pTabbedTextOutA)(sdc.GetHdc(), X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + sdc.PutPrimaryDC(hdc, TRUE); + return res; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + break; + case GDIMODE_EMULATED: + if(dxw.IsVirtual(hdc)){ + X+=dxw.VirtualOffsetX; + Y+=dxw.VirtualOffsetY; + } + break; + default: + break; + } + OutTraceDW("TabbedTextOutA: fixed dest=(%d,%d)\n", X, Y); } res=(*pTabbedTextOutA)(hdc, X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); return res; } +LONG WINAPI extTabbedTextOutW(HDC hdc, int X, int Y, LPCWSTR lpString, int nCount, int nTabPositions, const LPINT lpnTabStopPositions, int nTabOrigin) +{ + BOOL res; + OutTraceDW("TabbedTextOutW: hdc=%x xy=(%d,%d) nCount=%d nTP=%d nTOS=%d str=(%d)\"%ls\"\n", + hdc, X, Y, nCount, nTabPositions, nTabOrigin, lpString); + + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + res=(*pTabbedTextOutW)(sdc.GetHdc(), X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + sdc.PutPrimaryDC(hdc, TRUE); + return res; + break; + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + break; + case GDIMODE_EMULATED: + if(dxw.IsVirtual(hdc)){ + X+=dxw.VirtualOffsetX; + Y+=dxw.VirtualOffsetY; + } + break; + default: + break; + } + OutTraceDW("TabbedTextOutW: fixed dest=(%d,%d)\n", X, Y); + } + + res=(*pTabbedTextOutW)(hdc, X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); + return res; +} + BOOL WINAPI extDestroyWindow(HWND hWnd) { // v2.02.43: "Empire Earth" builds test surfaces that must be destroyed! @@ -2416,37 +2669,47 @@ BOOL gFixed; int WINAPI extDrawTextA(HDC hdc, LPCTSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat) { int ret; - BOOL MustScale; - OutTraceDW("DrawText: hdc=%x rect=(%d,%d)-(%d,%d) Format=%x(%s) Text=(%d)\"%s\"\n", + OutTraceDW("DrawTextA: hdc=%x rect=(%d,%d)-(%d,%d) Format=%x(%s) Text=(%d)\"%s\"\n", hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, uFormat, ExplainDTFormat(uFormat), nCount, lpchText); + gFixed = TRUE; // semaphore to avoid multiple scaling with HOT patching + if(dxw.IsToRemap(hdc)){ - MustScale = dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc)); - if (MustScale){ - dxw.MapClient((RECT *)lpRect); - OutTraceDW("DrawText: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pDrawTextA)(sdc.GetHdc(), lpchText, nCount, lpRect, uFormat); + if(nCount) + sdc.PutPrimaryDC(hdc, TRUE, lpRect->left, lpRect->top, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top); + else + sdc.PutPrimaryDC(hdc, FALSE); // Diablo makes a DrawText of nuull string in the intro ... + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawTextA: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + ret=(*pDrawTextA)(hdc, lpchText, nCount, lpRect, uFormat); + dxw.UnmapClient((RECT *)lpRect); + OutTraceDW("DrawTextA: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + break; + default: + ret=(*pDrawTextA)(hdc, lpchText, nCount, lpRect, uFormat); + break; + } + } + else { + ret=(*pDrawTextA)(hdc, lpchText, nCount, lpRect, uFormat); } - - gFixed = TRUE; - ret=(*pDrawText)(hdc, lpchText, nCount, lpRect, uFormat); gFixed = FALSE; // if nCount is zero, DrawRect returns 0 as text heigth, but this is not an error! (ref. "Imperialism II") - if(nCount && !ret) OutTraceE("DrawText: ERROR ret=%x err=%d\n", ret, GetLastError()); - - if (MustScale){ - dxw.UnmapClient((RECT *)lpRect); - OutTraceDW("DrawText: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - + if(nCount && !ret) OutTraceE("DrawTextA: ERROR ret=%x err=%d\n", ret, GetLastError()); return ret; } int WINAPI extDrawTextExA(HDC hdc, LPTSTR lpchText, int nCount, LPRECT lpRect, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) { int ret; - BOOL MustScale; - - OutTraceDW("DrawTextEx: hdc=%x rect=(%d,%d)-(%d,%d) DTFormat=%x Text=(%d)\"%s\"\n", + OutTraceDW("DrawTextExA: hdc=%x rect=(%d,%d)-(%d,%d) DTFormat=%x Text=(%d)\"%s\"\n", hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, dwDTFormat, nCount, lpchText); if (IsDebug){ if(lpDTParams) @@ -2457,23 +2720,117 @@ int WINAPI extDrawTextExA(HDC hdc, LPTSTR lpchText, int nCount, LPRECT lpRect, U OutTrace("DTParams: NULL\n"); } - MustScale = dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc)); - - if (MustScale){ - dxw.MapClient((RECT *)lpRect); - OutTraceDW("DrawTextEx: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + gFixed = TRUE; // semaphore to avoid multiple scaling with HOT patching + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pDrawTextExA)(sdc.GetHdc(), lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + sdc.PutPrimaryDC(hdc, TRUE, lpRect->left, lpRect->top, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawTextA: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + ret=(*pDrawTextExA)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + dxw.UnmapClient((RECT *)lpRect); + OutTraceDW("DrawTextA: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + break; + default: + ret=(*pDrawTextExA)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + break; + } } + else { + ret=(*pDrawTextExA)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + } + gFixed = FALSE; - gFixed = TRUE; - ret=(*pDrawTextEx)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); - gFixed = FALSE; - if(nCount && !ret) OutTraceE("DrawTextEx: ERROR ret=%x err=%d\n", ret, GetLastError()); + // if nCount is zero, DrawRect returns 0 as text heigth, but this is not an error! (ref. "Imperialism II") + if(nCount && !ret) OutTraceE("DrawTextA: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} - if (MustScale){ - dxw.UnmapClient((RECT *)lpRect); - OutTraceDW("DrawTextEx: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); +int WINAPI extDrawTextW(HDC hdc, LPCWSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat) +{ + int ret; + OutTraceDW("DrawTextW: hdc=%x rect=(%d,%d)-(%d,%d) Format=%x(%s) Text=(%d)\"%ls\"\n", + hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, uFormat, ExplainDTFormat(uFormat), nCount, lpchText); + + gFixed = TRUE; // semaphore to avoid multiple scaling with HOT patching + if(dxw.IsToRemap(hdc)){ + + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pDrawTextW)(sdc.GetHdc(), lpchText, nCount, lpRect, uFormat); + sdc.PutPrimaryDC(hdc, TRUE, lpRect->left, lpRect->top, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawTextW: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + ret=(*pDrawTextW)(hdc, lpchText, nCount, lpRect, uFormat); + dxw.UnmapClient((RECT *)lpRect); + OutTraceDW("DrawTextW: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + break; + default: + ret=(*pDrawTextW)(hdc, lpchText, nCount, lpRect, uFormat); + break; + } + } + else { + ret=(*pDrawTextW)(hdc, lpchText, nCount, lpRect, uFormat); + } + gFixed = FALSE; + + // if nCount is zero, DrawRect returns 0 as text heigth, but this is not an error! (ref. "Imperialism II") + if(nCount && !ret) OutTraceE("DrawTextW: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} + +int WINAPI extDrawTextExW(HDC hdc, LPCWSTR lpchText, int nCount, LPRECT lpRect, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) +{ + int ret; + OutTraceDW("DrawTextExW: hdc=%x rect=(%d,%d)-(%d,%d) DTFormat=%x Text=(%d)\"%ls\"\n", + hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, dwDTFormat, nCount, lpchText); + if (IsDebug){ + if(lpDTParams) + OutTrace("DTParams: size=%d (L,R)margins=(%d,%d) TabLength=%d lDrawn=%d\n", + lpDTParams->cbSize, lpDTParams->iLeftMargin, lpDTParams->iRightMargin, + lpDTParams->iTabLength, lpDTParams->uiLengthDrawn); + else + OutTrace("DTParams: NULL\n"); } + gFixed = TRUE; // semaphore to avoid multiple scaling with HOT patching + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pDrawTextExW)(sdc.GetHdc(), lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + sdc.PutPrimaryDC(hdc, TRUE, lpRect->left, lpRect->top, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top); + return ret; + break; + case GDIMODE_STRETCHED: + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawTextExW: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + ret=(*pDrawTextExW)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + dxw.UnmapClient((RECT *)lpRect); + OutTraceDW("DrawTextExW: fixed output rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + break; + default: + ret=(*pDrawTextExW)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + break; + } + } + else { + ret=(*pDrawTextExW)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + } + gFixed = FALSE; + + // if nCount is zero, DrawRect returns 0 as text heigth, but this is not an error! (ref. "Imperialism II") + if(nCount && !ret) OutTraceE("DrawTextExW: ERROR ret=%x err=%d\n", ret, GetLastError()); return ret; } @@ -2521,8 +2878,27 @@ BOOL WINAPI extUpdateWindow(HWND hwnd) BOOL WINAPI extRedrawWindow(HWND hWnd, const RECT *lprcUpdate, HRGN hrgnUpdate, UINT flags) { + RECT rcUpdate; + BOOL ret; + OutTraceDW("RedrawWindow: hwnd=%x flags=%x\n", hWnd, flags); - return (*pRedrawWindow)(hWnd, lprcUpdate, hrgnUpdate, flags); + + rcUpdate = *lprcUpdate; + // avoid redrawing the whole desktop + if(dxw.Windowize && dxw.IsRealDesktop(hWnd)) hWnd=dxw.GethWnd(); + if(dxw.IsFullScreen()){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + rcUpdate = dxw.MapClientRect((LPRECT)lprcUpdate); + break; + default: + break; + } + } + + ret = (*pRedrawWindow)(hWnd, &rcUpdate, hrgnUpdate, flags); + if(ret) OutTraceE("RedrawWindow ERROR: err=%d\n", GetLastError()); + return ret; } @@ -2808,7 +3184,7 @@ int WINAPI extGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase) OutTraceDW("GetUpdateRgn: hwnd=%x hrgn=%x erase=%x regionType=%x(%s)\n", hWnd, hRgn, bErase, regionType, ExplainRegionType(regionType)); - if(dxw.Windowize && dxw.IsFullScreen()){ + if(dxw.IsFullScreen()){ if(regionType == SIMPLEREGION){ RECT rc; if(!pGetRgnBox) pGetRgnBox=GetRgnBox; @@ -2851,7 +3227,7 @@ UINT WINAPI extGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, RGBQUA UINT ret; OutTraceDW("GetDIBColorTable: hdc=%x start=%d entries=%d\n", hdc, uStartIndex, cEntries); - //if((OBJ_DC == GetObjectType(hdc)) && (dxw.dwFlags1 & EMULATESURFACE)){ + //if((OBJ_DC == (*pGetObjectType)(hdc)) && (dxw.dwFlags1 & EMULATESURFACE)){ // //extern PALETTEENTRY PalEntries[256]; // extern DWORD *PaletteEntries; // if((uStartIndex+cEntries) > 256) cEntries = 256 - uStartIndex; @@ -3005,6 +3381,9 @@ HHOOK WINAPI extSetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWOR // v2.03.39: "One Must Fall Battlegrounds" keyboard fix if((idHook == WH_KEYBOARD) && (dwThreadId == NULL)) dwThreadId = GetCurrentThreadId(); + // v2.03.54: disable the disable Alt-Tab fix + if((dxw.dwFlags7 & DISABLEDISABLEALTTAB) && (idHook == WH_KEYBOARD_LL)) return NULL; + ret=(*pSetWindowsHookEx)(idHook, lpfn, hMod, dwThreadId); return ret; @@ -3071,7 +3450,7 @@ BOOL WINAPI extIsZoomed(HWND hWnd) { BOOL ret; ret = (*pIsZoomed)(hWnd); - OutTrace("IsZoomed: hwnd=%x ret=%x\n", hWnd, ret); + OutTraceDW("IsZoomed: hwnd=%x ret=%x\n", hWnd, ret); //if(dxw.IsFullScreen()) ret = FALSE; return ret; } @@ -3080,7 +3459,168 @@ BOOL WINAPI extIsIconic(HWND hWnd) { BOOL ret; ret = (*pIsIconic)(hWnd); - OutTrace("IsIconic: hwnd=%x ret=%x\n", hWnd, ret); + OutTraceDW("IsIconic: hwnd=%x ret=%x\n", hWnd, ret); //return FALSE; return ret; } + +BOOL extScrollWindow(HWND hWnd, int XAmount, int YAmount, const RECT *lpRect, const RECT *lpClipRect) +{ + RECT Rect, ClipRect; + BOOL res; + + OutTraceDW("ScrollWindow: hwnd=%x amount=(%d,%d) rect=(%d,%d)-(%d,%d) clip=(%d,%d)-(%d,%d)\n", + hWnd, XAmount, YAmount, + lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, + lpClipRect->left, lpClipRect->top, lpClipRect->right, lpClipRect->bottom); + + Rect = *lpRect; + ClipRect = *lpClipRect; + if(dxw.Windowize && dxw.IsFullScreen()){ + dxw.MapClient(&XAmount, &YAmount); + dxw.MapClient(&Rect); + dxw.MapClient(&ClipRect); + } + + res=(*pScrollWindow)(hWnd, XAmount, YAmount, (const RECT *)&Rect, (const RECT *)&ClipRect); + if(!res) OutTraceE("ScrollWindow ERROR: err=%d\n", GetLastError()); + return res; +} + +#if 0 +// avoid invalidating whole desktop!!! +BOOL InvalidateRgn( + _In_ HWND hWnd, + _In_ HRGN hRgn, + _In_ BOOL bErase +); + +#endif + +HWND WINAPI extGetParent(HWND hWnd) +{ + // Beware: can cause recursion on HOT PATCH mode + HWND ret; + + ret = (*pGetParent)(hWnd); + OutTraceB("GetParent: hwnd=%x ret=%x\n", hWnd, ret); + + if(dxw.IsFullScreen()){ + if(ret == dxw.GethWnd()) { + OutTraceB("GetParent: setting desktop reached\n"); + ret = 0; // simulate reaching the desktop + } + } + + return ret; +} + +BOOL WINAPI extInvalidateRgn(HWND hWnd, HRGN hRgn, BOOL bErase) +{ + OutTraceDW("InvalidateRgn: hwnd=%x hrgn=%x erase=%x\n", hWnd, hRgn, bErase); + + if(dxw.IsFullScreen()){ + if (dxw.IsRealDesktop(hWnd) && bErase) return true; + } + + return (*pInvalidateRgn)(hWnd, hRgn, bErase); +} + +BOOL WINAPI extDrawIcon(HDC hdc, int X, int Y, HICON hIcon) +{ + BOOL ret; + OutTraceDW("DrawIcon: hdcdest=%x pos=(%d,%d) hicon=%x\n", hdc, X, Y, hIcon); + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + dxw.MapClient(&X, &Y); + OutTraceDW("OffsetRgn: fixed STRETCHED pos=(%d,%d)\n", X, Y); + break; + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pDrawIcon)(sdc.GetHdc(), X, Y, hIcon); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + + ret = (*pDrawIcon)(hdc, X, Y, hIcon); + if(!ret) OutTraceE("DrawIcon ERROR: err=%d\n", GetLastError()); + return ret; +} + + +BOOL WINAPI extDrawIconEx( HDC hdc, int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) +{ + BOOL ret; + OutTraceDW("DrawIconEx: hdc=%x pos=(%d,%d) hicon=%x size=(%d,%d) istep=%x flags=%x\n", + hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, diFlags); + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + dxw.MapClient(&xLeft, &yTop, &cxWidth, &cyWidth); + OutTraceDW("DrawIconEx: fixed STRETCHED pos=(%d,%d) size=(%d,%d)\n", xLeft, yTop, cxWidth, cyWidth); + break; + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pDrawIconEx)(sdc.GetHdc(), xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, hbrFlickerFreeDraw, diFlags); + sdc.PutPrimaryDC(hdc, TRUE, xLeft, yTop, cxWidth, cyWidth); + return ret; + break; + default: + break; + } + } + ret = (*pDrawIconEx)(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, hbrFlickerFreeDraw, diFlags); + if(!ret) OutTraceE("DrawIconEx ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extDrawCaption(HWND hwnd, HDC hdc, LPCRECT lprc, UINT uFlags) +{ + BOOL ret; + OutTraceDW("DrawCaption: hwnd=%x hdc=%x rect=(%d,%d)-(%d,%d) flags=%x\n", hwnd, hdc, lprc->left, lprc->top, lprc->right, lprc->bottom, uFlags); + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_STRETCHED: + dxw.MapClient((LPRECT)lprc); + OutTraceDW("DrawIconEx: fixed STRETCHED rect=(%d,%d)-(%d,%d)\n", lprc->left, lprc->top, lprc->right, lprc->bottom); + break; + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pDrawCaption)(hwnd, sdc.GetHdc(), lprc, uFlags); + sdc.PutPrimaryDC(hdc, TRUE, lprc->left, lprc->top, lprc->right, lprc->bottom); + return ret; + break; + default: + break; + } + } + ret = (*pDrawCaption)(hwnd, hdc, lprc, uFlags); + if(!ret) OutTraceE("DrawCaption ERROR: err=%d\n", GetLastError()); + return ret; +} + +BOOL WINAPI extPaintDesktop(HDC hdc) +{ + BOOL ret; + OutTraceDW("PaintDesktop: hdc=%x\n", hdc); + if(dxw.IsToRemap(hdc)){ + switch(dxw.GDIEmulationMode){ + case GDIMODE_SHAREDDC: + sdc.GetPrimaryDC(hdc); + ret=(*pPaintDesktop)(sdc.GetHdc()); + sdc.PutPrimaryDC(hdc, TRUE); + return ret; + break; + default: + break; + } + } + ret = (*pPaintDesktop)(hdc); + if(!ret) OutTraceE("PaintDesktop ERROR: err=%d\n", GetLastError()); + return ret; +} \ No newline at end of file diff --git a/dll/virtualdc.cpp b/dll/virtualdc.cpp new file mode 100644 index 0000000..008b0d7 --- /dev/null +++ b/dll/virtualdc.cpp @@ -0,0 +1,219 @@ +#define _CRT_SECURE_NO_WARNINGS +#define SYSLIBNAMES_DEFINES + +#include +#include "dxwnd.h" +#include "dxwcore.hpp" +#include "syslibs.h" +#include "dxhelper.h" +#include "resource.h" +#include "hddraw.h" +extern GetDC_Type pGetDC; +extern ReleaseDC_Type pReleaseDC; +extern HandleDDThreadLock_Type pReleaseDDThreadLock; + +#define OutTraceTMP OutTrace + +HDC dxwVDC::GetPrimaryDC() +{ + HDC PrimaryDC; + LPDIRECTDRAWSURFACE lpDDSPrim; + PrimaryDC = NULL; + lpDDSPrim = dxwss.GetPrimarySurface(); + if (lpDDSPrim) { + if(pReleaseDDThreadLock)(*pReleaseDDThreadLock)(); + (*pGetDC)(lpDDSPrim, &PrimaryDC); + while((PrimaryDC == NULL) && lpDDSPrim) { + OutTraceDW("GetFlippedDC: found primary surface with no DC, unref lpdds=%x\n", lpDDSPrim); + dxwss.UnrefSurface(lpDDSPrim); + lpDDSPrim = dxwss.GetPrimarySurface(); + if (lpDDSPrim) (*pGetDC)(lpDDSPrim, &PrimaryDC); + } + } + OutTrace("GetFlippedDC: return primary surface dc=%x\n", PrimaryDC); + return PrimaryDC; +} + +HDC dxwVDC::AcquireEmulatedDC(HWND hwnd, HDC *PrimaryDC) +{ + HDC wdc; + RECT WinRect; + HDC RealHDC; + +/*--------------------------------- + extern HDC hFlippedDC; + LPDIRECTDRAWSURFACE lpDDSPrim; + hFlippedDC = GetPrimaryDC(); + +----------------------------------*/ + if(!(wdc=(*pGDIGetDC)(hwnd))){ + OutTraceE("GetDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + return NULL; + } + RealHDC=wdc; + + RECT LastVRect; + LastVRect = VirtualPicRect; + + if(!(hwnd=WindowFromDC(wdc))) + OutTraceE("WindowFromDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + (*pGetClientRect)(hwnd, &WinRect); + if(dxw.IsDesktop(hwnd)){ + // when screen resolution changes, better renew service resources + VirtualPicRect = dxw.GetScreenRect(); + if((LastVRect.right != VirtualPicRect.right) || (LastVRect.bottom != VirtualPicRect.bottom)) { + DeleteObject(VirtualHDC); + VirtualHDC = NULL; + DeleteObject(VirtualPic); + VirtualPic = NULL; + } + } + else { + VirtualPicRect = WinRect; + dxw.UnmapClient(&VirtualPicRect); + } + + + OutTraceB("AcquireEmulatedDC: hwnd=%x Desktop=%x WinRect=(%d,%d)(%d,%d) VirtRect=(%d,%d)(%d,%d)\n", + hwnd, dxw.IsDesktop(hwnd), + WinRect.left, WinRect.top, WinRect.right, WinRect.bottom, + VirtualPicRect.left, VirtualPicRect.top, VirtualPicRect.right, VirtualPicRect.bottom); + + + if (!VirtualHDC){ + OutTraceB("AcquireEmulatedDC: INITIALIZE\n"); + if(!(VirtualHDC=CreateCompatibleDC(wdc))) + OutTraceE("CreateCompatibleDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + + if(!(VirtualPic=CreateCompatibleBitmap(wdc, dxw.GetScreenWidth(), dxw.GetScreenHeight()))) + OutTraceE("CreateCompatibleBitmap: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + + if(!SelectObject(VirtualHDC, VirtualPic)) + OutTraceE("SelectObject: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + +/*---------------------------------*/ + //HRGN hRgn; + //RECT screen; + //screen = dxw.GetScreenRect(); + //hRgn = CreateRectRgnIndirect(&screen); + //SelectClipRgn (VirtualHDC, hRgn); + //screen = dxw.GetScreenRect(); + //hRgn = CreateRectRgnIndirect(&screen); + //SelectClipRgn (wdc, hRgn); +/*---------------------------------*/ +/*---------------------------------*/ + if (!(hwnd == dxw.GethWnd())) { + POINT father, child, offset; + father.x = father.y = 0; + child.x = child.y = 0; + (*pClientToScreen)(dxw.GethWnd(),&father); + (*pClientToScreen)(hwnd,&child); + offset.x = child.x - father.x; + offset.y = child.y - father.y; + dxw.UnmapClient(&offset); + OutTraceDW("AcquireEmulatedDC: child window hwnd=%x offset=(%d,%d)\n", hwnd, offset.x, offset.y); + (*pSetViewportOrgEx)(VirtualHDC, offset.x, offset.y, NULL); + } + else + (*pSetViewportOrgEx)(VirtualHDC, 0, 0, NULL); + + + if(*PrimaryDC = GetPrimaryDC()){ // better copy from virtual primary .... + OutTraceTMP("AcquireEmulatedDC: intialize from primary dc=%x\n", PrimaryDC); + if(!(*pGDIBitBlt)(VirtualHDC, 0, 0, VirtualPicRect.right, VirtualPicRect.bottom, *PrimaryDC, 0, 0, SRCCOPY)) + OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + } + else { // otherwise stretch from current windows DC + OutTraceTMP("AcquireEmulatedDC: intialize from windows dc=%x\n", wdc); + if(!(*pGDIStretchBlt)(VirtualHDC, 0, 0, VirtualPicRect.right, VirtualPicRect.bottom, wdc, 0, 0, WinRect.right, WinRect.bottom, SRCCOPY)) + OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + } + } + + return VirtualHDC; +} + +BOOL dxwVDC::ReleaseEmulatedDC(HWND hwnd) +{ + HDC wdc; + RECT WinRect; + HDC PrimaryDC; + + (*pGetClientRect)(hwnd, &WinRect); + + OutTraceB("ReleaseEmulatedDC: hwnd=%x Desktop=%x WinRect=(%d,%d)(%d,%d) VirtRect=(%d,%d)(%d,%d)\n", + hwnd, dxw.IsDesktop(hwnd), + WinRect.left, WinRect.top, WinRect.right, WinRect.bottom, + VirtualPicRect.left, VirtualPicRect.top, VirtualPicRect.right, VirtualPicRect.bottom); + + if(PrimaryDC = GetPrimaryDC()){ // better copy from virtual primary .... + OutTraceTMP("AcquireEmulatedDC: flush to from primary dc=%x\n", PrimaryDC); + if(!(*pGDIBitBlt)(PrimaryDC, VirtualPicRect.left, VirtualPicRect.top, VirtualPicRect.right, VirtualPicRect.bottom, VirtualHDC, 0, 0, SRCCOPY)) + OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + } + else + { + if(!(wdc=(*pGDIGetDC)(hwnd))) + OutTraceE("GetDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + OutTraceTMP("AcquireEmulatedDC: flush to windows dc=%x\n", wdc); + SetStretchBltMode(wdc, HALFTONE); + if(!(*pGDIStretchBlt)(wdc, 0, 0, WinRect.right, WinRect.bottom, VirtualHDC, 0, 0, VirtualPicRect.right, VirtualPicRect.bottom, SRCCOPY)) + OutTraceE("StretchBlt: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + } + (*pGDIReleaseDC)(hwnd, VirtualHDC); + + return TRUE; +} + +void dxwVDC::ResetEmulatedDC() +{ + VirtualHDC=NULL; + VirtualPic=NULL; + VirtualOffsetX=0; + VirtualOffsetY=0; +} + +BOOL dxwVDC::IsVirtual(HDC hdc) +{ + return (hdc==VirtualHDC) /* && (dwFlags3 & GDIEMULATEDC)*/; +} + +#if 0 +BOOL dxwCore::ReleaseSharedDC(HWND hwnd, HDC hDC) +{ + HRESULT ret; + LPDIRECTDRAWSURFACE lpDDSPrim; + lpDDSPrim = dxwss.GetPrimarySurface(); + if(!lpDDSPrim) return(TRUE); + OutTraceDW("GDI.ReleaseDC: releasing flipped GDI hdc=%x\n", hDC); + ret=(*pReleaseDC)(dxwss.GetPrimarySurface(), hDC); + if (!(hwnd == dxw.GethWnd())) { + POINT father, child, offset; + RECT rect; + HDC hdc; + father.x = father.y = 0; + child.x = child.y = 0; + (*pClientToScreen)(dxw.GethWnd(),&father); + (*pClientToScreen)(hwnd,&child); + offset.x = child.x - father.x; + offset.y = child.y - father.y; + if(offset.x || offset.y){ + // if the graphis was blitted to primary but below a modal child window, + // bring that up to the window surface to make it visible. + BOOL ret2; + (*pGetClientRect)(hwnd, &rect); + hdc=(*pGDIGetDC)(hwnd); + if(!hdc) OutTrace("GDI.ReleaseDC: GetDC ERROR=%d at %d\n", GetLastError(), __LINE__); + ret2=(*pGDIBitBlt)(hdc, rect.left, rect.top, rect.right, rect.bottom, hDC, offset.x, offset.y, SRCCOPY); + if(!ret2) OutTrace("GDI.ReleaseDC: BitBlt ERROR=%d at %d\n", GetLastError(), __LINE__); + ret2=(*pGDIReleaseDC)(hwnd, hdc); + if(!ret2)OutTrace("GDI.ReleaseDC: ReleaseDC ERROR=%d at %d\n", GetLastError(), __LINE__); + // this may flicker .... + (*pInvalidateRect)(hwnd, NULL, FALSE); + } + } + if (ret) OutTraceE("GDI.ReleaseDC ERROR: err=%x(%s) at %d\n", ret, ExplainDDError(ret), __LINE__); + else dxw.ScreenRefresh(); + return (ret == DD_OK); +} +#endif \ No newline at end of file diff --git a/host/TabCompat.cpp b/host/TabCompat.cpp index 5261a4d..58a2352 100644 --- a/host/TabCompat.cpp +++ b/host/TabCompat.cpp @@ -42,6 +42,7 @@ void CTabCompat::DoDataExchange(CDataExchange* pDX) DDX_Check(pDX, IDC_EASPORTSHACK, cTarget->m_EASportsHack); DDX_Check(pDX, IDC_LEGACYALLOC, cTarget->m_LegacyAlloc); DDX_Check(pDX, IDC_DISABLEMAXWINMODE, cTarget->m_DisableMaxWinMode); + DDX_Check(pDX, IDC_DISABLEDISABLEALTTAB, cTarget->m_DisableDisableAltTab); DDX_Check(pDX, IDC_NOIMAGEHLP, cTarget->m_NoImagehlp); DDX_Check(pDX, IDC_REPLACEPRIVOPS, cTarget->m_ReplacePrivOps); diff --git a/host/TabSysLibs.cpp b/host/TabSysLibs.cpp index 1f3d310..2b074d2 100644 --- a/host/TabSysLibs.cpp +++ b/host/TabSysLibs.cpp @@ -31,7 +31,6 @@ void CTabSysLibs::DoDataExchange(CDataExchange* pDX) DDX_Check(pDX, IDC_CLIENTREMAPPING, cTarget->m_ClientRemapping); DDX_Radio(pDX, IDC_GDINONE, cTarget->m_DCEmulationMode); DDX_Check(pDX, IDC_FIXTEXTOUT, cTarget->m_FixTextOut); - DDX_Check(pDX, IDC_SHAREDDC, cTarget->m_SharedDC); DDX_Check(pDX, IDC_NOFILLRECT, cTarget->m_NoFillRect); DDX_Check(pDX, IDC_REUSEEMULATEDDC, cTarget->m_ReuseEmulatedDC); DDX_Check(pDX, IDC_CREATEDESKTOP, cTarget->m_CreateDesktop); diff --git a/host/TargetDlg.cpp b/host/TargetDlg.cpp index 91239ca..9e3b627 100644 --- a/host/TargetDlg.cpp +++ b/host/TargetDlg.cpp @@ -2,6 +2,7 @@ // #include "stdafx.h" +#include "shlwapi.h" #include "dxwndhost.h" #include "TargetDlg.h" @@ -59,6 +60,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_EASportsHack = FALSE; m_LegacyAlloc = FALSE; m_DisableMaxWinMode = FALSE; + m_DisableDisableAltTab = FALSE; m_NoImagehlp = FALSE; m_ReplacePrivOps = FALSE; m_ForcesHEL = FALSE; @@ -103,8 +105,8 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_Windowize = TRUE; // default true !! m_HotPatch = FALSE; m_HookDLLs = TRUE; // default true !! - m_TerminateOnClose = FALSE; // default true !! - m_ConfirmOnClose = FALSE; // default true !! + m_TerminateOnClose = FALSE; + m_ConfirmOnClose = FALSE; m_HookEnabled = TRUE; // default true !! m_EmulateRegistry = FALSE; m_OverrideRegistry = FALSE; @@ -231,19 +233,6 @@ BOOL CTargetDlg::OnInitDialog() int i=0; AfxEnableControlContainer(); CDialog::OnInitDialog(); -#if 0 - m_tabdxTabCtrl.InsertItem(i++, _T("Main")); - m_tabdxTabCtrl.InsertItem(i++, _T("Video")); - m_tabdxTabCtrl.InsertItem(i++, _T("Input")); - m_tabdxTabCtrl.InsertItem(i++, _T("DirectX")); - m_tabdxTabCtrl.InsertItem(i++, _T("Timing")); - m_tabdxTabCtrl.InsertItem(i++, _T("Log")); - m_tabdxTabCtrl.InsertItem(i++, _T("Libs")); - m_tabdxTabCtrl.InsertItem(i++, _T("Compat")); - m_tabdxTabCtrl.InsertItem(i++, _T("Registry")); - m_tabdxTabCtrl.InsertItem(i++, _T("Notes")); - if (gbDebug) m_tabdxTabCtrl.InsertItem(i++, _T("Debug")); -#else char sCaption[48+1]; LoadString(AfxGetResourceHandle(), DXW_TAB_MAIN, sCaption, sizeof(sCaption)); m_tabdxTabCtrl.InsertItem(i++, _T(sCaption)); @@ -269,7 +258,6 @@ BOOL CTargetDlg::OnInitDialog() m_tabdxTabCtrl.InsertItem(i++, _T(sCaption)); LoadString(AfxGetResourceHandle(), DXW_TAB_DEBUG, sCaption, sizeof(sCaption)); if (gbDebug) m_tabdxTabCtrl.InsertItem(i++, _T(sCaption)); -#endif m_tabdxTabCtrl.Init(); return TRUE; } @@ -293,7 +281,94 @@ BEGIN_MESSAGE_MAP(CTargetDlg, CDialog) //{{AFX_MSG_MAP(CTargetDlg) //}}AFX_MSG_MAP + ON_BN_CLICKED(IDTRY, &CTargetDlg::OnBnClickedTry) + ON_BN_CLICKED(IDKILL, &CTargetDlg::OnBnClickedKill) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTargetDlg Message Handler + +void CTargetDlg::OnBnClickedTry() +{ +#if 0 + NMHDR nmh; + nmh.code = ID_PRUN; + nmh.idFrom = NULL; + nmh.hwndFrom = NULL; + this->GetParent()->SendMessage(WM_NOTIFY, 0, (LPARAM)&nmh); +#else + char path[MAX_PATH+1]; + char fullpath[MAX_PATH+1]; + char sMsg[81]; + int iHookStatus; + STARTUPINFO sinfo; + PROCESS_INFORMATION pinfo; + TARGETMAP RestrictedMaps[2]; + extern void SetTargetFromDlg(TARGETMAP *, CTargetDlg *); + extern BOOL CheckStatus(void); + + static BOOL IsLocked = FALSE; + if(IsLocked) return; + if (CheckStatus()) return; // don't try when status is active + IsLocked = TRUE; + m_tabdxTabCtrl.OnOK(); + SetTargetFromDlg(&RestrictedMaps[0], this); + memset(&RestrictedMaps[1], 0, sizeof(TARGETMAP)); + strcpy_s(path, sizeof(path), m_FilePath.GetBuffer()); + PathRemoveFileSpec(path); + SetTarget(RestrictedMaps); + iHookStatus=GetHookStatus(NULL); + if(iHookStatus == DXW_IDLE) StartHook(); + if(m_StartDebug){ + extern DWORD WINAPI StartDebug(void *); + TARGETMAP TargetMap; + PRIVATEMAP PrivateMap; + ThreadInfo_Type ThreadInfo; + strcpy(TargetMap.path, m_FilePath); + strcpy(PrivateMap.launchpath, m_LaunchPath); + ThreadInfo.TM=&TargetMap; + ThreadInfo.PM=&PrivateMap; + CloseHandle(CreateThread( NULL, 0, StartDebug, &ThreadInfo, 0, NULL)); + } + else{ + ZeroMemory(&sinfo, sizeof(sinfo)); + sinfo.cb = sizeof(sinfo); + strncpy(fullpath, m_LaunchPath.IsEmpty() ? m_FilePath.GetBuffer() : m_LaunchPath.GetBuffer(), MAX_PATH); + if(!CreateProcess(NULL, fullpath, + 0, 0, false, CREATE_DEFAULT_ERROR_MODE, NULL, path, &sinfo, &pinfo)){ + sprintf(sMsg, "CreateProcess ERROR %d", GetLastError()); + MessageBox(sMsg, "Error", MB_ICONEXCLAMATION); + } + CloseHandle(pinfo.hProcess); // no longer needed, avoid handle leakage + CloseHandle(pinfo.hThread); // no longer needed, avoid handle leakage + } + // wait & recover + Sleep(5000); + //SetTarget(CDxwndhostView::TargetMaps); + if(iHookStatus == DXW_IDLE) EndHook(); + IsLocked = FALSE; +#endif +} + +void CTargetDlg::OnBnClickedKill() +{ + char FilePath[MAX_PATH+1]; + char *lpProcName, *lpNext; + HRESULT res; + extern BOOL KillProcByName(char *, BOOL); + + strncpy(FilePath, m_FilePath.GetBuffer(), MAX_PATH); + lpProcName=FilePath; + while (lpNext=strchr(lpProcName,'\\')) lpProcName=lpNext+1; + + if(!KillProcByName(lpProcName, FALSE)){ + wchar_t *wcstring = new wchar_t[48+1]; + mbstowcs_s(NULL, wcstring, 48, lpProcName, _TRUNCATE); + res=MessageBoxLangArg(DXW_STRING_KILLTASK, DXW_STRING_WARNING, MB_YESNO | MB_ICONQUESTION, wcstring); + if(res!=IDYES) return; + KillProcByName(lpProcName, TRUE); + } + else{ + MessageBoxLang(DXW_STRING_NOKILLTASK, DXW_STRING_INFO, MB_ICONEXCLAMATION); + } +} \ No newline at end of file diff --git a/host/TargetDlg.h b/host/TargetDlg.h index a48428c..441aea8 100644 --- a/host/TargetDlg.h +++ b/host/TargetDlg.h @@ -199,6 +199,7 @@ public: BOOL m_EASportsHack; BOOL m_LegacyAlloc; BOOL m_DisableMaxWinMode; + BOOL m_DisableDisableAltTab; BOOL m_NoImagehlp; BOOL m_ForcesHEL; BOOL m_SetZBufferBitDepths; @@ -256,6 +257,8 @@ protected: public: virtual BOOL OnInitDialog(); + afx_msg void OnBnClickedTry(); + afx_msg void OnBnClickedKill(); }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ Will insert additional declarations immediately before the previous line. diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps index 2cda1ed..9285cee 100644 Binary files a/host/dxwndhost.aps and b/host/dxwndhost.aps differ diff --git a/host/dxwndhost.cpp b/host/dxwndhost.cpp index 30d2006..f70ece3 100644 --- a/host/dxwndhost.cpp +++ b/host/dxwndhost.cpp @@ -34,6 +34,8 @@ END_MESSAGE_MAP() UINT m_StartToTray = FALSE; UINT m_InitialState = DXW_ACTIVE; BOOL gbDebug = FALSE; +BOOL gTransientMode = FALSE; +int iProgIndex; extern char m_ConfigFileName[20+1] = "dxwnd.ini"; class CNewCommandLineInfo : public CCommandLineInfo @@ -50,6 +52,13 @@ char LangString[20+1] = {0}; void CNewCommandLineInfo::ParseParam(LPCTSTR lpszParam, BOOL bFlag, BOOL bLast) { + // syntax: + // /t -- start minimized in tray icon + // /i -- start in idle state + // /d -- start in debug mode + // /lang= -- loads the language resources in Resources_.dll extension + // /c: -- loads config file instead of default dxwnd.ini + // /e -- terminates (Ends) the active dxwnd session if(bFlag) { CString sParam(lpszParam); if (sParam.MakeLower() == "t"){ @@ -87,6 +96,13 @@ void CNewCommandLineInfo::ParseParam(LPCTSTR lpszParam, BOOL bFlag, BOOL bLast) KillProcByName("DxWnd.exe", TRUE); exit(0); } + if (sParam.Left(2).MakeLower() == "r:"){ + gTransientMode = TRUE; + m_StartToTray=TRUE; + char *p = (char *)sParam.GetString(); + iProgIndex = atoi(&p[2]); + return; + } } // Call the base class to ensure proper command line processing diff --git a/host/dxwndhost.h b/host/dxwndhost.h index 29d0071..f6cb68f 100644 --- a/host/dxwndhost.h +++ b/host/dxwndhost.h @@ -34,6 +34,12 @@ typedef struct PRIVATEMAP char *registry; }PRIVATEMAP; +typedef struct { + TARGETMAP *TM; + PRIVATEMAP *PM; +} ThreadInfo_Type; +ThreadInfo_Type; + extern char gInitPath[MAX_PATH]; ///////////////////////////////////////////////////////////////////////////// diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc index e063715..e9173e9 100644 Binary files a/host/dxwndhost.rc and b/host/dxwndhost.rc differ diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo index 7d227fc..125f4fd 100644 Binary files a/host/dxwndhost.vs2008.suo and b/host/dxwndhost.vs2008.suo differ diff --git a/host/dxwndhostView.cpp b/host/dxwndhostView.cpp index 3be5377..0fa70e1 100644 --- a/host/dxwndhostView.cpp +++ b/host/dxwndhostView.cpp @@ -31,6 +31,8 @@ extern UINT m_InitialState; extern char m_ConfigFileName[20+1]; extern BOOL Inject(DWORD, const char *); extern int KillProcByName(char *, BOOL); +extern BOOL gTransientMode; +extern int iProgIndex; PRIVATEMAP *pTitles; // global ptr: get rid of it!! TARGETMAP *pTargets; // idem. @@ -141,7 +143,7 @@ BEGIN_MESSAGE_MAP(CDxwndhostView, CListView) END_MESSAGE_MAP() // v2.1.68: dialog box for status check. -static BOOL CheckStatus() +BOOL CheckStatus() { if(GetHookStatus(NULL)==DXW_RUNNING){ MessageBoxLang(DXW_STRING_WAITTASK, DXW_STRING_WARNING, MB_OK | MB_ICONEXCLAMATION); @@ -163,7 +165,7 @@ static void RevertScreenChanges(DEVMODE *InitDevMode) } } -static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) +void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) { strcpy_s(t->path, sizeof(t->path), dlg->m_FilePath); strcpy_s(t->module, sizeof(t->module), dlg->m_Module); @@ -221,6 +223,7 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) case 0: break; case 1: t->flags2 |= GDISTRETCHED; break; case 2: t->flags3 |= GDIEMULATEDC; break; + case 3: t->flags6 |= SHAREDDC; break; //case 3: t->flags |= MAPGDITOPRIMARY; break; } @@ -300,6 +303,7 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) if(dlg->m_EASportsHack) t->flags5 |= EASPORTSHACK; if(dlg->m_LegacyAlloc) t->flags6 |= LEGACYALLOC; if(dlg->m_DisableMaxWinMode) t->flags6 |= DISABLEMAXWINMODE; + if(dlg->m_DisableDisableAltTab) t->flags7 |= DISABLEDISABLEALTTAB; if(dlg->m_NoImagehlp) t->flags5 |= NOIMAGEHLP; if(dlg->m_ForcesHEL) t->flags3 |= FORCESHEL; if(dlg->m_SetZBufferBitDepths) t->flags6 |= SETZBUFFERBITDEPTHS; @@ -335,7 +339,6 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) if(dlg->m_CursorClipping) t->flags |= CLIPCURSOR; if(dlg->m_VideoToSystemMem) t->flags |= SWITCHVIDEOMEMORY; if(dlg->m_FixTextOut) t->flags |= FIXTEXTOUT; - if(dlg->m_SharedDC) t->flags6 |= SHAREDDC; if(dlg->m_HookGlide) t->flags4 |= HOOKGLIDE; if(dlg->m_RemapMCI) t->flags5 |= REMAPMCI; if(dlg->m_NoMovies) t->flags6 |= NOMOVIES; @@ -472,6 +475,7 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_DCEmulationMode = 0; if(t->flags2 & GDISTRETCHED) dlg->m_DCEmulationMode = 1; if(t->flags3 & GDIEMULATEDC) dlg->m_DCEmulationMode = 2; + if(t->flags6 & SHAREDDC ) dlg->m_DCEmulationMode = 3; //if(t->flags & MAPGDITOPRIMARY) dlg->m_DCEmulationMode = 3; dlg->m_ResTypes = 0; @@ -525,6 +529,7 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_EASportsHack = t->flags5 & EASPORTSHACK ? 1 : 0; dlg->m_LegacyAlloc = t->flags6 & LEGACYALLOC ? 1 : 0; dlg->m_DisableMaxWinMode = t->flags6 & DISABLEMAXWINMODE ? 1 : 0; + dlg->m_DisableDisableAltTab = t->flags7 & DISABLEDISABLEALTTAB ? 1 : 0; dlg->m_NoImagehlp = t->flags5 & NOIMAGEHLP ? 1 : 0; dlg->m_ForcesHEL = t->flags3 & FORCESHEL ? 1 : 0; dlg->m_SetZBufferBitDepths = t->flags6 & SETZBUFFERBITDEPTHS ? 1 : 0; @@ -1075,6 +1080,10 @@ void CDxwndhostView::OnInitialUpdate() this->isUpdated=FALSE; pTitles = &PrivateMaps[0]; pTargets= &TargetMaps[0]; + + if(gTransientMode){ + this->OnRun(); + } } ///////////////////////////////////////////////////////////////////////////// @@ -1753,9 +1762,10 @@ DWORD WINAPI TrayIconUpdate(CSystemTray *Tray) char sMsg[1024]; char *Status; char DllVersion[21]; - int TickCount; + int TickCount, IdleCount; PrevDxStatus=-1; // a different one... TickCount=0; + IdleCount=0; while (TRUE) { // once a second ... Sleep(1000); @@ -1770,10 +1780,18 @@ DWORD WINAPI TrayIconUpdate(CSystemTray *Tray) TickCount=0; Tray->StopAnimation(); Tray->SetIcon(IconId); + if(gTransientMode) { + IdleCount++; + if(IdleCount > 2) { + delete(Tray->GetAncestor(GA_ROOTOWNER)); + exit(0); + } + } } else { // animation state machine .... TickCount++; + IdleCount=0; if (DxStatus!=PrevDxStatus) { Tray->SetIcon(IconId); } @@ -1999,12 +2017,6 @@ static char *ExceptionCaption(DWORD ec) // For thread messaging #define DEBUG_EVENT_MESSAGE WM_APP + 0x100 -typedef struct { - TARGETMAP *TM; - PRIVATEMAP *PM; -} ThreadInfo_Type; -ThreadInfo_Type ThreadInfo; - DWORD WINAPI StartDebug(void *p) { ThreadInfo_Type *ThInfo; @@ -2137,22 +2149,37 @@ DWORD WINAPI StartDebug(void *p) void CDxwndhostView::OnRun() { + static BOOL IsLocked = FALSE; + if(IsLocked) return; + IsLocked = TRUE; CListCtrl& listctrl = GetListCtrl(); POSITION pos; int i; STARTUPINFO sinfo; PROCESS_INFORMATION pinfo; char path[MAX_PATH]; + TARGETMAP RestrictedMaps[2]; //extern CString GetFileNameFromHandle(HANDLE); - if(!listctrl.GetSelectedCount()) return; - pos = listctrl.GetFirstSelectedItemPosition(); - i = listctrl.GetNextSelectedItem(pos); + if(gTransientMode){ + i=iProgIndex-1; + if(i<0) i=0; + } + else { + if(!listctrl.GetSelectedCount()) return; + pos = listctrl.GetFirstSelectedItemPosition(); + i = listctrl.GetNextSelectedItem(pos); + } ZeroMemory(&sinfo, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); + // create a virtually single entry in the targetmap array + memcpy(&RestrictedMaps[0], &TargetMaps[i], sizeof(TARGETMAP)); + memset(&RestrictedMaps[1], 0, sizeof(TARGETMAP)); strcpy_s(path, sizeof(path), TargetMaps[i].path); PathRemoveFileSpec(path); + SetTarget(RestrictedMaps); if(TargetMaps[i].flags2 & STARTDEBUG){ + ThreadInfo_Type ThreadInfo; ThreadInfo.TM=&TargetMaps[i]; ThreadInfo.PM=&PrivateMaps[i]; CloseHandle(CreateThread( NULL, 0, StartDebug, &ThreadInfo, 0, NULL)); @@ -2164,6 +2191,10 @@ void CDxwndhostView::OnRun() CloseHandle(pinfo.hProcess); // no longer needed, avoid handle leakage CloseHandle(pinfo.hThread); // no longer needed, avoid handle leakage } + // wait & recover + Sleep(5000); + SetTarget(TargetMaps); + IsLocked = FALSE; } void SwitchToColorDepth(int bpp) diff --git a/host/host.aps b/host/host.aps index 9c58adf..7948191 100644 Binary files a/host/host.aps and b/host/host.aps differ diff --git a/host/resource b/host/resource index 2d616ea..3f2648f 100644 Binary files a/host/resource and b/host/resource differ