From bb0b5128e04e4122202d8a7e8746a883fb46d516 Mon Sep 17 00:00:00 2001 From: gho tik Date: Sat, 31 Jan 2015 11:40:19 -0500 Subject: [PATCH] v2_03_09_src Former-commit-id: 412cc9877e7e53a916b5a059e5b1b5479c220e6c --- Include/dxwnd.h | 3 +- build/dxwnd.dll | 4 +- build/dxwnd.exe | 4 +- build/dxwnd.ini | 6 +- build/exports/Black & White.dxw | 9 +- build/exports/Doom 3.dxw | 4 +- build/exports/Hitchcock the Final Cut.dxw | 29 ++ build/exports/Moon Tycoon.dxw | 142 +++++++ .../Tomb Raider III (SW emulation).dxw | 11 +- build/readme-relnotes.txt | 6 + dll/Inject.cpp | 61 +-- dll/ddblit.cpp | 366 ++++++++++++++++ dll/ddraw.cpp | 390 ++---------------- dll/dxwcore.cpp | 4 + dll/dxwnd.aps | Bin 37664 -> 37664 bytes dll/dxwnd.cpp | 8 +- dll/dxwnd.def | 14 +- dll/dxwnd.vs2008.suo | Bin 77312 -> 47616 bytes dll/dxwnd.vs2008.vcproj | 4 + dll/gdiblt.cpp | 4 + dll/hd3d7.cpp | 118 ++++++ dll/kernel32.cpp | 11 + host/Inject.cpp | 72 ---- host/Resource.h | Bin 32612 -> 32704 bytes host/TabDirectX.cpp | 1 + host/TargetDlg.cpp | 1 + host/TargetDlg.h | 1 + host/dxwndhost.aps | Bin 127780 -> 154200 bytes host/dxwndhost.rc | Bin 94982 -> 95264 bytes host/dxwndhost.vs2008.suo | Bin 148992 -> 197632 bytes host/dxwndhost.vs2008.vcproj | 4 - host/dxwndhostView.cpp | 143 +++---- host/resource | Bin 32738 -> 32830 bytes 33 files changed, 837 insertions(+), 583 deletions(-) create mode 100644 build/exports/Hitchcock the Final Cut.dxw create mode 100644 build/exports/Moon Tycoon.dxw create mode 100644 dll/ddblit.cpp delete mode 100644 host/Inject.cpp diff --git a/Include/dxwnd.h b/Include/dxwnd.h index b3c834e..52918e5 100644 --- a/Include/dxwnd.h +++ b/Include/dxwnd.h @@ -122,7 +122,7 @@ #define DISABLEFOGGING 0x00000080 // Disable D3D fogging #define NOPOWER2FIX 0x00000100 // Handle textures whose size is not a power of 2 (32, 64, 128 ...) #define NOPERFCOUNTER 0x00000200 // Disables the GetPerfCounter performance metrics API,as if it was not supported.... -#define BILINEAR2XFILTER 0x00000400 // attempt to smooth low-res graphic by applying biulinear filtering in emulation mode +#define BILINEAR2XFILTER 0x00000400 // attempt to smooth low-res graphic by applying simplified bilinear filtering in emulation mode #define INTERCEPTRDTSC 0x00000800 // Intercapts RDTSC opcodes to hook at assembly level #define LIMITSCREENRES 0x00001000 // Limit available screen resolution up to defined maximum #define NOFILLRECT 0x00002000 // Suppress FillRect calls @@ -173,6 +173,7 @@ #define CENTERTOWIN 0x01000000 // do NOT stretch the image to the whole window client area, but center to it. #define STRESSRESOURCES 0x02000000 // simulates a lack of resources condition, for testing (debug opt.) #define MESSAGEPUMP 0x04000000 // inserts a "message pump" loop between repeated operation that may stop the task on Win7 and greater +#define TEXTUREFORMAT 0x08000000 // Apply virtual pixel format to texture surfaces without DDSD_PIXELFORMAT attribute // logging Tflags DWORD: #define OUTTRACE 0x00000001 // enables tracing to dxwnd.log in general diff --git a/build/dxwnd.dll b/build/dxwnd.dll index cfac4c1..7b88cf6 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c798c0cff917a4dfb846882ff9d9ffc9cc2fcd747228487da1f88b8e58c5b74 -size 563712 +oid sha256:09c3405b326eb5eff358f5713b62cd1107c84ce64625529de44283cab2b64c9a +size 564224 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index f7130d7..fcfb1b7 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a88f64a7bf93e63942698c78c94a1b57ab660eea0e6b2eaf8fdd2774c0ca0e3 -size 536576 +oid sha256:be381f4fba85d8c7dcb13682c470713728dd133b38e6d4d1ed65fc6ceb74e771 +size 536064 diff --git a/build/dxwnd.ini b/build/dxwnd.ini index 14a8117..b278890 100644 --- a/build/dxwnd.ini +++ b/build/dxwnd.ini @@ -1,11 +1,11 @@ [window] -posx=1227 -posy=471 +posx=50 +posy=50 sizx=320 sizy=200 lang=default ;lang=automatic -;debug=1 +debug=1 ;multiprocesshook=0 ;checkadmin=0 [texture] diff --git a/build/exports/Black & White.dxw b/build/exports/Black & White.dxw index 7f54bff..8cc344b 100644 --- a/build/exports/Black & White.dxw +++ b/build/exports/Black & White.dxw @@ -5,11 +5,11 @@ module0= opengllib0= ver0=0 coord0=0 -flag0=679477280 +flag0=679477282 flagg0=1207959568 flagh0=20 -flagi0=4 -tflag0=259 +flagi0=4194308 +tflag0=0 initx0=0 inity0=0 minx0=0 @@ -24,3 +24,6 @@ maxfps0=0 initts0=0 winver0=0 maxres0=0 +launchpath0= +notes0= +flagj0=128 diff --git a/build/exports/Doom 3.dxw b/build/exports/Doom 3.dxw index 9147f33..809d3ce 100644 --- a/build/exports/Doom 3.dxw +++ b/build/exports/Doom 3.dxw @@ -10,7 +10,7 @@ flag0=134217760 flagg0=1207959552 flagh0=65557 flagi0=69206020 -tflag0=6211 +tflag0=64 initx0=0 inity0=0 minx0=0 @@ -25,3 +25,5 @@ maxfps0=0 initts0=0 winver0=0 maxres0=-1 +notes0= +flagj0=0 diff --git a/build/exports/Hitchcock the Final Cut.dxw b/build/exports/Hitchcock the Final Cut.dxw new file mode 100644 index 0000000..7d0cfcb --- /dev/null +++ b/build/exports/Hitchcock the Final Cut.dxw @@ -0,0 +1,29 @@ +[target] +title0=Hitchcock the Final Cut +path0=D:\Games\Hitchcock\Hitchcock_Kyro.exe +launchpath0= +module0= +opengllib0= +notes0= +ver0=1 +coord0=0 +flag0=134217762 +flagg0=1207959552 +flagh0=20 +flagi0=138412036 +flagj0=67113088 +tflag0=0 +initx0=0 +inity0=0 +minx0=0 +miny0=0 +maxx0=0 +maxy0=0 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=-1 diff --git a/build/exports/Moon Tycoon.dxw b/build/exports/Moon Tycoon.dxw new file mode 100644 index 0000000..f0372d8 --- /dev/null +++ b/build/exports/Moon Tycoon.dxw @@ -0,0 +1,142 @@ + + + + + + + + Wikisend: free file sharing service + + + + + + +
+
+
+ + +
+
+ +
+ +
+ +
+
+
+ +
+
+
+
+ + +
+
+ + + + + + + + + +
+
Upload
+
Download
+
+ +
+ + +
+ Moon Tycoon.dxw
+ +
+
+ +
    +
  • File ID: 271650
  • +
  • File size: 512 B
  • +
  • Time to live: 28 days
+
+
+
+ +
+ + + + +
+ + +
+
+ + +
+ + + + + + + +
+

Why our site?

+ +
+

Simple & Free

+Upload and download lots of  files, big files, small files, data files, +media files, archives or backups - any files. With Wikisend it`s simple and +free. + +

Share with Friends

+Share files with your friends using E-mail, MySpace page, your blog, forums +and so on. With Wikisend sharing files, photos, videos or documents is easy, +fast, and reliable. + +

Start now

+No need to register, activate, install or read manuals - use our uploading +form, you`re ready to go. + +
+ +
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/build/exports/Tomb Raider III (SW emulation).dxw b/build/exports/Tomb Raider III (SW emulation).dxw index 6e36eee..e3fd3e8 100644 --- a/build/exports/Tomb Raider III (SW emulation).dxw +++ b/build/exports/Tomb Raider III (SW emulation).dxw @@ -7,9 +7,9 @@ ver0=0 coord0=0 flag0=134217762 flagg0=1241513984 -flagh0=25165844 -flagi0=0 -tflag0=323 +flagh0=20 +flagi0=4194304 +tflag0=0 initx0=0 inity0=0 minx0=0 @@ -22,5 +22,10 @@ sizx0=800 sizy0=600 maxfps0=0 initts0=0 +launchpath0= +notes0= +flagj0=0 +winver0=0 +maxres0=0 ; remember to set SW emulated mode in game setup panel diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index 7c8e92d..e5eaa01 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -719,3 +719,9 @@ add: made check for admin rights configurable in dxwnd.ini add: "portable" capability to configure relative pathnames fix: small bug in game menu string width - now game titles should not be trunked any longer. +v2.03.09 +code reorganization & reuse +add: "Set texture pixel format" flag, makes "Jeff Gordon XS Racing" working on emulated mode and 32BPP desktop +add: "GDI mode" emulation uses HALFTONE to activate GDI bilinear stretching when "Full Bilinear" filter is activated: slower, but better quality +add: preliminary hooking for EnumZBufferFormats ddraw7 method +fix: eliminated some handle leakage when injecting launched processes diff --git a/dll/Inject.cpp b/dll/Inject.cpp index 3d018c5..d15cb0f 100644 --- a/dll/Inject.cpp +++ b/dll/Inject.cpp @@ -15,62 +15,41 @@ BOOL Inject(DWORD pID, const char * DLL_NAME) { - HANDLE Proc; + HANDLE hProc, hThread; + HMODULE hLib; char buf[50] = {0}; LPVOID RemoteString, LoadLibAddy; if(!pID) return false; - //Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); // not working on Win XP - Proc = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, FALSE, pID); - if(!Proc) + //hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); // not working on Win XP + hProc = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, FALSE, pID); + if(!hProc) { sprintf(buf, "OpenProcess() failed: pid=%x err=%d", pID, GetLastError()); MessageBox(NULL, buf, "Loader", MB_OK); - printf(buf); return false; } - LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); - // Allocate space in the process for our DLL - RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - // Write the string name of our DLL in the memory allocated - WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL); - // Load our DLL - if(!CreateRemoteThread(Proc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, 0, NULL)){ + hLib=GetModuleHandle("kernel32.dll"); + LoadLibAddy = (LPVOID)GetProcAddress(hLib, "LoadLibraryA"); + // Allocate space in the process for the DLL + RemoteString = (LPVOID)VirtualAllocEx(hProc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + // Write the string name of the DLL in the memory allocated + WriteProcessMemory(hProc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL); + // Load the DLL + hThread=CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, 0, NULL); + // Free/Release/Close everything + VirtualFreeEx(hProc, RemoteString, strlen(DLL_NAME), MEM_RELEASE); + if(!hThread){ sprintf(buf, "CreateRemoteThread() failed: pid=%x err=%d", pID, GetLastError()); MessageBox(NULL, buf, "Loader", MB_OK); - printf(buf); + CloseHandle(hProc); return false; } - CloseHandle(Proc); + CloseHandle(hThread); + CloseHandle(hProc); + CloseHandle(hLib); return true; } -#if 0 -DWORD GetTargetThreadIDFromProcName(const char * ProcName) -{ - PROCESSENTRY32 pe; - HANDLE thSnapShot; - BOOL retval, ProcFound = false; - thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if(thSnapShot == INVALID_HANDLE_VALUE) - { - MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "2MLoader", MB_OK); - //printf("Error: Unable to create toolhelp snapshot!"); - return false; - } - pe.dwSize = sizeof(PROCESSENTRY32); - retval = Process32First(thSnapShot, &pe); - while(retval) - { - if(StrStrI(pe.szExeFile, ProcName)) - { - return pe.th32ProcessID; - } - retval = Process32Next(thSnapShot, &pe); - } - return 0; -} -#endif - #define STATUS_SUCCESS ((NTSTATUS)0x000 00000L) #define ThreadQuerySetWin32StartAddress 9 diff --git a/dll/ddblit.cpp b/dll/ddblit.cpp new file mode 100644 index 0000000..a0f0234 --- /dev/null +++ b/dll/ddblit.cpp @@ -0,0 +1,366 @@ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include "dxwnd.h" +#include "dxwcore.hpp" +#include "stdio.h" +#include "hddraw.h" +#include "dxhelper.h" + +extern LPDIRECTDRAWSURFACE lpDDSBack; +extern LPDIRECTDRAWSURFACE lpDDSEmu_Prim; +extern LPDIRECTDRAWSURFACE lpDDSEmu_Back; +extern LPDIRECTDRAW lpPrimaryDD; +extern Blt_Type pBlt; +extern ReleaseS_Type pReleaseS; +extern CreateSurface1_Type pCreateSurface1; +extern CreateSurface1_Type pCreateSurface2; +extern CreateSurface1_Type pCreateSurface3; +extern CreateSurface2_Type pCreateSurface4; +extern CreateSurface2_Type pCreateSurface7; +extern Unlock4_Type pUnlockMethod(LPDIRECTDRAWSURFACE); + +extern void BlitError(HRESULT, LPRECT, LPRECT, int); +extern void BlitTrace(char *, LPRECT, LPRECT, int); +extern void DescribeSurface(LPDIRECTDRAWSURFACE, int, char *, int); +extern void TextureHandling(LPDIRECTDRAWSURFACE); + +static HRESULT sBltNoPrimary(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, + LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx) +{ + RECT srcrect; + HRESULT res; + BOOL FromScreen; + //extern PrimaryBlt_Type pPrimaryBlt; + //CkArg arg; + + FromScreen=dxw.IsAPrimarySurface(lpddssrc) && !(dxw.dwFlags1 & EMULATESURFACE) && !(dxw.dwFlags1 & EMULATEBUFFER); // v2.02.77 + + // make a working copy of srcrect if not NULL + if (lpsrcrect){ + srcrect=*lpsrcrect; + } + // when blitting from a primary surface on screen (that is in non emulated mode), correct offsets + // You should take account also for scaled primary surfaces, but that would be a hard task: + // a reduced primary surface (in not-emulated mode) would bring quality loss!!! + // v2.1.83: BLITFROMBACKBUFFER mode, let you chose to blit from backbuffer, where the surface size + // is fixed no matter how the window/primary surface is scaled. + // In "The Sims" there is no quality loss, but some scrolling artifact. + if(lpsrcrect && FromScreen){ + if(lpDDSBack && (dxw.dwFlags1 & BLITFROMBACKBUFFER)){ + lpddssrc=lpDDSBack; + srcrect=dxw.GetScreenRect(); + } + else{ + srcrect=dxw.MapWindowRect(lpsrcrect); + } + } + + if (IsDebug) BlitTrace("NOPRIM", lpsrcrect, lpdestrect, __LINE__); + res= (*pBlt)(lpdds, lpdestrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags, lpddbltfx); + // Blitting compressed data may work to screen surfaces only. In this case, it may be worth + // trying blitting directly to lpDDSEmu_Prim: it makes DK2 intro movies working. + // Wrong guess!!! The cause was not compression, but simply a pixelformat mismatch. Better + // configure things properly and avoid this branch. + switch(res){ + case DDERR_UNSUPPORTED: + if (dxw.dwFlags1 & EMULATESURFACE){ + RECT targetrect; + if (IsDebug) BlitTrace("UNSUPP", lpsrcrect ? &srcrect : NULL, lpdestrect, __LINE__); + targetrect=*lpdestrect; + dxw.MapWindowRect(&targetrect); + res=(*pBlt)(lpDDSEmu_Prim, &targetrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags, lpddbltfx); + } + break; + case DDERR_SURFACEBUSY: + (*pUnlockMethod(lpdds))(lpdds, NULL); + if (lpddssrc) (*pUnlockMethod(lpddssrc))(lpddssrc, NULL); + if (IsDebug) BlitTrace("BUSY", lpsrcrect ? &srcrect : NULL, lpdestrect, __LINE__); + res=(*pBlt)(lpdds, lpdestrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags|DDBLT_WAIT, lpddbltfx); + break; + default: + break; + } + if (res) BlitError(res, &srcrect, lpdestrect, __LINE__); + if(IsDebug) { + DescribeSurface(lpdds, 0, "[DST]" , __LINE__); + if (lpddssrc) DescribeSurface(lpddssrc, 0, "[SRC]" , __LINE__); // lpddssrc could be NULL!!! + } + if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0; + if(dxw.dwFlags5 & TEXTUREMASK) { + // Texture Handling on Blt + TextureHandling(lpdds); + } + return res; +} + +static HRESULT sBltToPrimary(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, + LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx, BOOL isFlipping) +{ + HRESULT res; + RECT destrect, emurect; + extern PrimaryBlt_Type pPrimaryBlt; + + // debug suppressions + if(isFlipping){ + if(dxw.dwFlags3 & NODDRAWFLIP) return DD_OK; + } + else { + if(dxw.dwFlags3 & NODDRAWBLT) return DD_OK; + } + +#ifdef ONEPIXELFIX + if (lpdestrect){ + if ((lpdestrect->top == 0) && (lpdestrect->bottom == dxw.GetScreenHeight() -1)) lpdestrect->bottom = dxw.GetScreenHeight(); + if ((lpdestrect->left == 0) && (lpdestrect->right == dxw.GetScreenWidth() -1)) lpdestrect->right = dxw.GetScreenWidth(); + } + if (lpsrcrect){ + if ((lpsrcrect->top == 0) && (lpsrcrect->bottom == dxw.GetScreenHeight() -1)) lpsrcrect->bottom = dxw.GetScreenHeight(); + if ((lpsrcrect->left == 0) && (lpsrcrect->right == dxw.GetScreenWidth() -1)) lpsrcrect->right = dxw.GetScreenWidth(); + } +#endif + +#define FIXBIGGERRECT 1 +#if FIXBIGGERRECT + if(lpdestrect){ + if((DWORD)lpdestrect->top < 0) lpdestrect->top = 0; + if((DWORD)lpdestrect->left < 0) lpdestrect->left = 0; + if((DWORD)lpdestrect->bottom > dxw.GetScreenHeight()) lpdestrect->bottom = dxw.GetScreenHeight(); + if((DWORD)lpdestrect->right > dxw.GetScreenWidth()) lpdestrect->right = dxw.GetScreenWidth(); + } +#endif + + if(dxw.dwFlags5 & QUARTERBLT){ + BOOL QuarterUpdate; + QuarterUpdate = lpdestrect ? + (((lpdestrect->bottom - lpdestrect->top) * (lpdestrect->right - lpdestrect->left)) > ((LONG)(dxw.GetScreenHeight() * dxw.GetScreenWidth()) >> 2)) + : + TRUE; + if(QuarterUpdate) if(dxw.HandleFPS()) return DD_OK; + } + else + if(dxw.HandleFPS()) return DD_OK; + if(dxw.dwFlags5 & NOBLT) return DD_OK; + + destrect=dxw.MapWindowRect(lpdestrect); + OutTraceB("DESTRECT=(%d,%d)-(%d,%d) Screen=(%dx%d)\n", + destrect.left, destrect.top, destrect.right, destrect.bottom, + dxw.GetScreenWidth(), dxw.GetScreenHeight()); + + if(!lpddssrc) { + if (isFlipping){ + // handle the flipping chain ... + lpddssrc=lpDDSBack; + OutTraceDW("Flip: setting flip chain to lpdds=%x\n", lpddssrc); + } + } + + // ========================= + // Blit to primary direct surface + // ========================= + + if(!(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER))){ + res=DD_OK; + + // blit only when source and dest surface are different. Should make ScreenRefresh faster. + if (lpdds != lpddssrc) { + dxw.ShowOverlay(lpddssrc); + if (IsDebug) BlitTrace("PRIM-NOEMU", lpsrcrect, &destrect, __LINE__); + res=(*pPrimaryBlt)(lpdds, &destrect, lpddssrc, lpsrcrect); + } + if(res){ + BlitError(res, lpsrcrect, &destrect, __LINE__); + if(IsDebug) { + DescribeSurface(lpdds, 0, "[DST]" , __LINE__); + if (lpddssrc) DescribeSurface(lpddssrc, 0, "[SRC]" , __LINE__); // lpddssrc could be NULL!!! + } + // Try to handle HDC lock concurrency.... + if(res==DDERR_SURFACEBUSY){ + (*pUnlockMethod(lpdds))(lpdds, NULL); + if (IsDebug) BlitTrace("BUSY", lpsrcrect, &destrect, __LINE__); + res= (*pBlt)(lpdds, &destrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); + if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); + } + // Try to handle DDBLT_KEYSRC on primary surface + if((res==DDERR_INVALIDPARAMS) && (dwflags & DDBLT_KEYSRC)){ + // to do: handle possible situations with surface 2 / 4 / 7 types + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE lpddsTmp; + if (IsDebug) BlitTrace("KEYSRC", lpsrcrect, &destrect, __LINE__); + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + lpddssrc->GetSurfaceDesc(&ddsd); + res=(*pCreateSurface1)(lpPrimaryDD, &ddsd, &lpddsTmp, NULL); + if(res) OutTraceE("CreateSurface: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); + // copy background + res= (*pBlt)(lpddsTmp, lpsrcrect, lpdds, &destrect, DDBLT_WAIT, NULL); + if(res) OutTraceE("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); + // overlay texture + res= (*pBlt)(lpddsTmp, lpsrcrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); + if(res) OutTraceE("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); + // copy back to destination + res= (*pBlt)(lpdds, &destrect, lpddsTmp, lpsrcrect, DDBLT_WAIT, lpddbltfx); + if(res) OutTraceE("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); + if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); + (*pReleaseS)(lpddsTmp); + } + if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; + } + + return res; + } + + // ... else blitting on emulated surface + + // ========================= + // Blit/Flip to emulated primary surface + // ========================= + + if(dxw.dwFlags5 & GDIMODE){ + extern void BlitToWindow(HWND, LPDIRECTDRAWSURFACE); + //if (lpdds != lpddssrc) + BlitToWindow(dxw.GethWnd(), lpddssrc); + return DD_OK; + } + + if (lpdestrect){ + emurect=*lpdestrect; + } + else{ + // emurect: emulated rect is full surface (dwWidth x dwHeight) + emurect.left = 0; + emurect.top = 0; + emurect.right = dxw.GetScreenWidth(); + emurect.bottom = dxw.GetScreenHeight(); + } + + res=0; + // blit only when source and dest surface are different. Should make ScreenRefresh faster. + if (lpdds != lpddssrc){ + if (IsDebug) BlitTrace("SRC2EMU", &emurect, &destrect, __LINE__); + if(destrect.top == -32000) return DD_OK; // happens when window is minimized & do not notify on task switch ... + res=(*pBlt)(lpdds, &emurect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); + } + + if (res) { + BlitError(res, lpsrcrect, &emurect, __LINE__); + DescribeSurface(lpdds, 0, "[DST]" , __LINE__); + if (lpddssrc) DescribeSurface(lpddssrc, 0, "[SRC]" , __LINE__); // lpddssrc could be NULL!!! + /* + Dungeon Keeper II intro movies bug .... + it seems that you can't blit from compressed or different surfaces in memory, + while the operation COULD be supported to video. As a mater of fact, it DOES + work on my PC. The error code is DDERR_UNSUPPORTED. + v2.02.98 update.... + The same thing happens with New York Racer, but with DDERR_EXCEPTION error code. + */ + if((res==DDERR_UNSUPPORTED) || (res==DDERR_EXCEPTION)){ + dxw.ShowOverlay(lpddssrc); + if (IsDebug) BlitTrace("UNSUPP", &emurect, &destrect, __LINE__); + res=(*pBlt)(lpDDSEmu_Prim, &destrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); + if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); + } + + // Try to handle HDC lock concurrency.... + if(res==DDERR_SURFACEBUSY){ + res=(*pUnlockMethod(lpddssrc))(lpddssrc, NULL); + if(res) OutTraceE("Unlock ERROR: err=%x(%s)\n", res, ExplainDDError(res)); + if (IsDebug) BlitTrace("BUSY", &emurect, &destrect, __LINE__); + res=(*pBlt)(lpdds, &emurect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); + if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); + } + + if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; + return res; + } + + LPDIRECTDRAWSURFACE lpDDSSource; + if (res=(*pColorConversion)(lpdds, emurect, &lpDDSSource)) { + OutTraceE("sBlt ERROR: Color conversion failed res=%d(%s)\n", res, ExplainDDError(res)); + if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; + return res; + } + + dxw.ShowOverlay(lpDDSSource); + if (IsDebug) BlitTrace("BACK2PRIM", &emurect, &destrect, __LINE__); + res=(*pPrimaryBlt)(lpDDSEmu_Prim, &destrect, lpDDSSource, &emurect); + + if (res) BlitError(res, &emurect, &destrect, __LINE__); + if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; + if (IsDebug) OutTrace("%s: done ret=%x at %d\n", api, res, __LINE__); + return res; +} + +HRESULT WINAPI sBlt(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, + LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx, BOOL isFlipping) +{ + POINT p = {0, 0}; + HRESULT res; + BOOL ToPrim, FromPrim, ToScreen, FromScreen; + + if(dxw.dwFlags5 & MESSAGEPUMP){ + MSG msg; + while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){ + OutTraceW("MESSAGEPUMP: msg=%x l-wParam=(%x,%x)\n", msg.message, msg.lParam, msg.wParam); + if((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST)) break; // do not consume keyboard inputs + PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + ToPrim=dxw.IsAPrimarySurface(lpdds); + FromPrim=dxw.IsAPrimarySurface(lpddssrc); + ToScreen=ToPrim && !(dxw.dwFlags1 & EMULATESURFACE); + FromScreen=FromPrim && !(dxw.dwFlags1 & EMULATESURFACE) && !(dxw.dwFlags1 & EMULATEBUFFER); // v2.02.77 + + // log + if(IsTraceDW){ + char sLog[256]; + char sInfo[128]; + sprintf(sLog, "%s: dest=%x%s src=%x%s dwFlags=%x(%s)", + api, lpdds, (ToPrim ? "(PRIM)":""), lpddssrc, (FromPrim ? "(PRIM)":""), dwflags, ExplainBltFlags(dwflags)); + if (lpdestrect) + sprintf(sInfo, " destrect=(%d,%d)-(%d,%d)", lpdestrect->left, lpdestrect->top, lpdestrect->right, lpdestrect->bottom); + else + sprintf(sInfo, " destrect=(NULL)"); + strcat(sLog, sInfo); + if (lpsrcrect) + sprintf(sInfo, " srcrect=(%d,%d)-(%d,%d)", lpsrcrect->left, lpsrcrect->top, lpsrcrect->right, lpsrcrect->bottom); + else + sprintf(sInfo, " srcrect=(NULL)"); + strcat(sLog, sInfo); + if(lpddbltfx){ + if (dwflags & DDBLT_COLORFILL){ + sprintf(sInfo, " ddbltfx.FillColor=%x", lpddbltfx->dwFillColor); + strcat(sLog, sInfo); + } + if (dwflags & DDBLT_KEYDESTOVERRIDE){ + sprintf(sInfo, " ddbltfx.DestColorkey=%x", lpddbltfx->ddckDestColorkey); + strcat(sLog, sInfo); + } + if (dwflags & DDBLT_KEYSRCOVERRIDE){ + sprintf(sInfo, " ddbltfx.SrcColorkey=%x", lpddbltfx->ddckSrcColorkey); + strcat(sLog, sInfo); + } + if (dwflags & DDBLT_ROP){ + sprintf(sInfo, " ddbltfx.ROP=%x", lpddbltfx->dwROP); + strcat(sLog, sInfo); + } + if (dwflags & DDBLT_DEPTHFILL){ + sprintf(sInfo, " ddbltfx.FillDepth=%x", lpddbltfx->dwFillDepth); + strcat(sLog, sInfo); + } + } + strcat(sLog,"\n"); + OutTrace(sLog); + } + + if(ToPrim) + res = sBltToPrimary(api, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx, isFlipping); + else + res = sBltNoPrimary(api, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); + + return res; +} \ No newline at end of file diff --git a/dll/ddraw.cpp b/dll/ddraw.cpp index 51cfd67..7114c21 100644 --- a/dll/ddraw.cpp +++ b/dll/ddraw.cpp @@ -286,6 +286,8 @@ FARPROC Remap_ddraw_ProcAddress(LPCSTR proc, HMODULE hModule) return NULL; } +extern HRESULT WINAPI sBlt(char *, LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX, BOOL); + /* ------------------------------------------------------------------------------ */ // auxiliary (static) functions /* ------------------------------------------------------------------------------ */ @@ -456,7 +458,7 @@ static void DumpSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line) LogSurfaceAttributes(lpddsd, label, line); } -static void DescribeSurface(LPDIRECTDRAWSURFACE lpdds, int dxversion, char *label, int line) +void DescribeSurface(LPDIRECTDRAWSURFACE lpdds, int dxversion, char *label, int line) { DDSURFACEDESC2 ddsd; HRESULT res; @@ -1515,7 +1517,7 @@ static void HandleCapsD(char *sLabel, LPDDCAPS c) HRESULT WINAPI extGetCapsD(LPDIRECTDRAW lpdd, LPDDCAPS c1, LPDDCAPS c2) { HRESULT res; - OutTraceDDRAW("GetCaps(D): lpdd=%x\n", lpdd); + OutTraceDDRAW("GetCaps(D): lpdd=%x %s %s\n", lpdd, c1?"c1":"NULL", c2?"c2":"NULL"); res=(*pGetCapsD)(lpdd, c1, c2); if(res) OutTraceE("GetCaps(D): ERROR res=%x(%s)\n", res, ExplainDDError(res)); @@ -1539,6 +1541,10 @@ HRESULT WINAPI extGetCapsD(LPDIRECTDRAW lpdd, LPDDCAPS c1, LPDDCAPS c2) memcpy((void *)c1, (void *)c2, size); if(c1->dwVidMemTotal == 0) c1->dwVidMemTotal=dwVidMemTotal; if(c1->dwVidMemFree == 0) c1->dwVidMemFree =dwVidMemFree; + if(c1->dwVidMemTotal == 0) c1->dwVidMemTotal=0x20000000; // 500 MB + if(c1->dwVidMemFree == 0) c1->dwVidMemFree =0x20000000; // 500 MB + if (c1) HandleCapsD("D-HW(fixed)", c1); + if (c2) HandleCapsD("D-SW(fixed)", c2); } if(dxw.dwFlags3 & CAPMASK) MaskCapsD(c1, c2); @@ -2127,6 +2133,7 @@ static void FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd, int dxversion) { // rules of thumb: // 1) textures should be left untouched (switching to SYSTEMMEMORY when forcing HEL may even fail!) + // 1.1) textures with no DDSD_PIXELFORMAT specification should have one when virtual color depth is not equal to real color depth? // 2) if a pixel format is specified, if DDSCAPS_SYSTEMMEMORY add DDSCAPS_OFFSCREENPLAY (if pixel formats are different?), otherwise do not touch anything. // 3) if the surface is used as a buffer (DDSD_WIDTH set, DDSD_HEIGHT unset) do not touch anything. // 4) zbuffer surfaces (DDSCAPS_ZBUFFER set) must have DDSCAPS_SYSTEMMEMORY @@ -2144,6 +2151,11 @@ static void FixSurfaceCaps(LPDDSURFACEDESC2 lpddsd, int dxversion) lpddsd->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; lpddsd->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; } + if((dxw.dwFlags5 & TEXTUREFORMAT) && !(lpddsd->dwFlags & DDSD_PIXELFORMAT)){ + // TEXTURE: enforce PIXELFORMAT on MEMORY + lpddsd->dwFlags |= DDSD_PIXELFORMAT; + GetPixFmt(lpddsd); + } return; } @@ -2375,7 +2387,7 @@ static HRESULT BuildBackBufferEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateS // create BackBuffer surface memcpy(&ddsd, lpddsd, lpddsd->dwSize); - ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE); + ddsd.dwFlags &= ~(DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE); ddsd.dwFlags |= (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT); ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_BACKBUFFER|DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM); // DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces @@ -2474,9 +2486,8 @@ static HRESULT BuildGenericEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurf // on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it.... if(dxw.dwFlags5 & NOSYSTEMMEMORY) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY; - DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic]" , __LINE__); res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu); - if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){ + if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res!=DD_OK)){ OutTraceDW("CreateSurface ERROR: res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__); ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; @@ -2486,6 +2497,8 @@ static HRESULT BuildGenericEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurf OutTraceE("CreateSurface: ERROR on Emu_Generic res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__); return res; } + + DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic]" , __LINE__); OutTraceDW("CreateSurface: created Emu_Generic dds=%x\n", *lplpdds); if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSEmu_Generic", __LINE__); @@ -2691,14 +2704,16 @@ static HRESULT WINAPI extCreateSurface(int dxversion, CreateSurface_Type pCreate // if nothing else, it's a generic/zbuffer surface - if(lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) { - lpDDZBuffer=*lplpdds; - DDZBufferCaps = lpddsd->ddsCaps.dwCaps; - OutTraceDW("CreateSurface: lpDDZBuffer=%x save ZBUFFER caps=%x(%s)\n", lpDDZBuffer, DDZBufferCaps, ExplainDDSCaps(DDZBufferCaps)); + res=BuildGeneric(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, pu); + if(!res) { + dxw.MarkRegularSurface(*lplpdds); + if(lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) { + lpDDZBuffer=*lplpdds; + DDZBufferCaps = lpddsd->ddsCaps.dwCaps; + OutTraceDW("CreateSurface: lpDDZBuffer=%x save ZBUFFER caps=%x(%s)\n", lpDDZBuffer, DDZBufferCaps, ExplainDDSCaps(DDZBufferCaps)); + } } - res=BuildGeneric(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, pu); - if(!res) dxw.MarkRegularSurface(*lplpdds); return res; } @@ -2814,7 +2829,7 @@ HRESULT WINAPI extGetAttachedSurface7(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpdds return extGetAttachedSurface(7, pGetAttachedSurface7, lpdds, lpddsc, lplpddas); } -static void BlitError(HRESULT res, LPRECT lps, LPRECT lpd, int line) +void BlitError(HRESULT res, LPRECT lps, LPRECT lpd, int line) { OutTrace("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), line); if (res==DDERR_INVALIDRECT){ @@ -2831,7 +2846,7 @@ static void BlitError(HRESULT res, LPRECT lps, LPRECT lpd, int line) return; } -static void BlitTrace(char *label, LPRECT lps, LPRECT lpd, int line) +void BlitTrace(char *label, LPRECT lps, LPRECT lpd, int line) { extern HANDLE hTraceMutex; WaitForSingleObject(hTraceMutex, INFINITE); @@ -3144,347 +3159,6 @@ HRESULT WINAPI ColorConversionDDRAW(LPDIRECTDRAWSURFACE lpdds, RECT emurect, LPD return DD_OK; } -static HRESULT sBltNoPrimary(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, - LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx) -{ - RECT srcrect; - HRESULT res; - BOOL FromScreen; - //extern PrimaryBlt_Type pPrimaryBlt; - //CkArg arg; - - FromScreen=dxw.IsAPrimarySurface(lpddssrc) && !(dxw.dwFlags1 & EMULATESURFACE) && !(dxw.dwFlags1 & EMULATEBUFFER); // v2.02.77 - - // make a working copy of srcrect if not NULL - if (lpsrcrect){ - srcrect=*lpsrcrect; - } - // when blitting from a primary surface on screen (that is in non emulated mode), correct offsets - // You should take account also for scaled primary surfaces, but that would be a hard task: - // a reduced primary surface (in not-emulated mode) would bring quality loss!!! - // v2.1.83: BLITFROMBACKBUFFER mode, let you chose to blit from backbuffer, where the surface size - // is fixed no matter how the window/primary surface is scaled. - // In "The Sims" there is no quality loss, but some scrolling artifact. - if(lpsrcrect && FromScreen){ - if(lpDDSBack && (dxw.dwFlags1 & BLITFROMBACKBUFFER)){ - lpddssrc=lpDDSBack; - srcrect=dxw.GetScreenRect(); - } - else{ - srcrect=dxw.MapWindowRect(lpsrcrect); - } - } - - if (IsDebug) BlitTrace("NOPRIM", lpsrcrect, lpdestrect, __LINE__); - res= (*pBlt)(lpdds, lpdestrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags, lpddbltfx); - // Blitting compressed data may work to screen surfaces only. In this case, it may be worth - // trying blitting directly to lpDDSEmu_Prim: it makes DK2 intro movies working. - // Wrong guess!!! The cause was not compression, but simply a pixelformat mismatch. Better - // configure things properly and avoid this branch. - switch(res){ - case DDERR_UNSUPPORTED: - if (dxw.dwFlags1 & EMULATESURFACE){ - RECT targetrect; - if (IsDebug) BlitTrace("UNSUPP", lpsrcrect ? &srcrect : NULL, lpdestrect, __LINE__); - targetrect=*lpdestrect; - dxw.MapWindowRect(&targetrect); - res=(*pBlt)(lpDDSEmu_Prim, &targetrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags, lpddbltfx); - } - break; - case DDERR_SURFACEBUSY: - (*pUnlockMethod(lpdds))(lpdds, NULL); - if (lpddssrc) (*pUnlockMethod(lpddssrc))(lpddssrc, NULL); - if (IsDebug) BlitTrace("BUSY", lpsrcrect ? &srcrect : NULL, lpdestrect, __LINE__); - res=(*pBlt)(lpdds, lpdestrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags|DDBLT_WAIT, lpddbltfx); - break; - default: - break; - } - if (res) BlitError(res, &srcrect, lpdestrect, __LINE__); - if(IsDebug) { - DescribeSurface(lpdds, 0, "[DST]" , __LINE__); - if (lpddssrc) DescribeSurface(lpddssrc, 0, "[SRC]" , __LINE__); // lpddssrc could be NULL!!! - } - if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0; - if(dxw.dwFlags5 & TEXTUREMASK) { - // Texture Handling on Blt - TextureHandling(lpdds); - } - return res; - } - -static HRESULT sBltToPrimary(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, - LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx, BOOL isFlipping) -{ - HRESULT res; - RECT destrect, emurect; - extern PrimaryBlt_Type pPrimaryBlt; - - // debug suppressions - if(isFlipping){ - if(dxw.dwFlags3 & NODDRAWFLIP) return DD_OK; - } - else { - if(dxw.dwFlags3 & NODDRAWBLT) return DD_OK; - } - -#ifdef ONEPIXELFIX - if (lpdestrect){ - if ((lpdestrect->top == 0) && (lpdestrect->bottom == dxw.GetScreenHeight() -1)) lpdestrect->bottom = dxw.GetScreenHeight(); - if ((lpdestrect->left == 0) && (lpdestrect->right == dxw.GetScreenWidth() -1)) lpdestrect->right = dxw.GetScreenWidth(); - } - if (lpsrcrect){ - if ((lpsrcrect->top == 0) && (lpsrcrect->bottom == dxw.GetScreenHeight() -1)) lpsrcrect->bottom = dxw.GetScreenHeight(); - if ((lpsrcrect->left == 0) && (lpsrcrect->right == dxw.GetScreenWidth() -1)) lpsrcrect->right = dxw.GetScreenWidth(); - } -#endif - -#define FIXBIGGERRECT 1 -#if FIXBIGGERRECT - if(lpdestrect){ - if((DWORD)lpdestrect->top < 0) lpdestrect->top = 0; - if((DWORD)lpdestrect->left < 0) lpdestrect->left = 0; - if((DWORD)lpdestrect->bottom > dxw.GetScreenHeight()) lpdestrect->bottom = dxw.GetScreenHeight(); - if((DWORD)lpdestrect->right > dxw.GetScreenWidth()) lpdestrect->right = dxw.GetScreenWidth(); - } -#endif - - if(dxw.dwFlags5 & QUARTERBLT){ - BOOL QuarterUpdate; - QuarterUpdate = lpdestrect ? - (((lpdestrect->bottom - lpdestrect->top) * (lpdestrect->right - lpdestrect->left)) > ((LONG)(dxw.GetScreenHeight() * dxw.GetScreenWidth()) >> 2)) - : - TRUE; - if(QuarterUpdate) if(dxw.HandleFPS()) return DD_OK; - } - else - if(dxw.HandleFPS()) return DD_OK; - if(dxw.dwFlags5 & NOBLT) return DD_OK; - - destrect=dxw.MapWindowRect(lpdestrect); - OutTraceB("DESTRECT=(%d,%d)-(%d,%d) Screen=(%dx%d)\n", - destrect.left, destrect.top, destrect.right, destrect.bottom, - dxw.GetScreenWidth(), dxw.GetScreenHeight()); - - if(!lpddssrc) { - if (isFlipping){ - // handle the flipping chain ... - lpddssrc=lpDDSBack; - OutTraceDW("Flip: setting flip chain to lpdds=%x\n", lpddssrc); - } - } - - // ========================= - // Blit to primary direct surface - // ========================= - - if(!(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER))){ - res=DD_OK; - - // blit only when source and dest surface are different. Should make ScreenRefresh faster. - if (lpdds != lpddssrc) { - dxw.ShowOverlay(lpddssrc); - if (IsDebug) BlitTrace("PRIM-NOEMU", lpsrcrect, &destrect, __LINE__); - res=(*pPrimaryBlt)(lpdds, &destrect, lpddssrc, lpsrcrect); - } - if(res){ - BlitError(res, lpsrcrect, &destrect, __LINE__); - if(IsDebug) { - DescribeSurface(lpdds, 0, "[DST]" , __LINE__); - if (lpddssrc) DescribeSurface(lpddssrc, 0, "[SRC]" , __LINE__); // lpddssrc could be NULL!!! - } - // Try to handle HDC lock concurrency.... - if(res==DDERR_SURFACEBUSY){ - (*pUnlockMethod(lpdds))(lpdds, NULL); - if (IsDebug) BlitTrace("BUSY", lpsrcrect, &destrect, __LINE__); - res= (*pBlt)(lpdds, &destrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); - if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); - } - // Try to handle DDBLT_KEYSRC on primary surface - if((res==DDERR_INVALIDPARAMS) && (dwflags & DDBLT_KEYSRC)){ - // to do: handle possible situations with surface 2 / 4 / 7 types - DDSURFACEDESC ddsd; - LPDIRECTDRAWSURFACE lpddsTmp; - if (IsDebug) BlitTrace("KEYSRC", lpsrcrect, &destrect, __LINE__); - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - lpddssrc->GetSurfaceDesc(&ddsd); - res=(*pCreateSurface1)(lpPrimaryDD, &ddsd, &lpddsTmp, NULL); - if(res) OutTraceE("CreateSurface: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); - // copy background - res= (*pBlt)(lpddsTmp, lpsrcrect, lpdds, &destrect, DDBLT_WAIT, NULL); - if(res) OutTraceE("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); - // overlay texture - res= (*pBlt)(lpddsTmp, lpsrcrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); - if(res) OutTraceE("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); - // copy back to destination - res= (*pBlt)(lpdds, &destrect, lpddsTmp, lpsrcrect, DDBLT_WAIT, lpddbltfx); - if(res) OutTraceE("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), __LINE__); - if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); - (*pReleaseS)(lpddsTmp); - } - if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; - } - - return res; - } - - // ... else blitting on emulated surface - - // ========================= - // Blit/Flip to emulated primary surface - // ========================= - - if(dxw.dwFlags5 & GDIMODE){ - extern void BlitToWindow(HWND, LPDIRECTDRAWSURFACE); - if (lpdds != lpddssrc) BlitToWindow(dxw.GethWnd(), lpddssrc); - return DD_OK; - } - - if (lpdestrect){ - emurect=*lpdestrect; - } - else{ - // emurect: emulated rect is full surface (dwWidth x dwHeight) - emurect.left = 0; - emurect.top = 0; - emurect.right = dxw.GetScreenWidth(); - emurect.bottom = dxw.GetScreenHeight(); - } - - res=0; - // blit only when source and dest surface are different. Should make ScreenRefresh faster. - if (lpdds != lpddssrc){ - if (IsDebug) BlitTrace("SRC2EMU", &emurect, &destrect, __LINE__); - if(destrect.top == -32000) return DD_OK; // happens when window is minimized & do not notify on task switch ... - res=(*pBlt)(lpdds, &emurect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); - } - - if (res) { - BlitError(res, lpsrcrect, &emurect, __LINE__); - DescribeSurface(lpdds, 0, "[DST]" , __LINE__); - if (lpddssrc) DescribeSurface(lpddssrc, 0, "[SRC]" , __LINE__); // lpddssrc could be NULL!!! - /* - Dungeon Keeper II intro movies bug .... - it seems that you can't blit from compressed or different surfaces in memory, - while the operation COULD be supported to video. As a mater of fact, it DOES - work on my PC. The error code is DDERR_UNSUPPORTED. - v2.02.98 update.... - The same thing happens with New York Racer, but with DDERR_EXCEPTION error code. - */ - if((res==DDERR_UNSUPPORTED) || (res==DDERR_EXCEPTION)){ - dxw.ShowOverlay(lpddssrc); - if (IsDebug) BlitTrace("UNSUPP", &emurect, &destrect, __LINE__); - res=(*pBlt)(lpDDSEmu_Prim, &destrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); - if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); - } - - // Try to handle HDC lock concurrency.... - if(res==DDERR_SURFACEBUSY){ - res=(*pUnlockMethod(lpddssrc))(lpddssrc, NULL); - if(res) OutTraceE("Unlock ERROR: err=%x(%s)\n", res, ExplainDDError(res)); - if (IsDebug) BlitTrace("BUSY", &emurect, &destrect, __LINE__); - res=(*pBlt)(lpdds, &emurect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); - if (res) BlitError(res, lpsrcrect, &destrect, __LINE__); - } - - if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; - return res; - } - - LPDIRECTDRAWSURFACE lpDDSSource; - if (res=(*pColorConversion)(lpdds, emurect, &lpDDSSource)) { - OutTraceE("sBlt ERROR: Color conversion failed res=%d(%s)\n", res, ExplainDDError(res)); - if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; - return res; - } - - dxw.ShowOverlay(lpDDSSource); - if (IsDebug) BlitTrace("BACK2PRIM", &emurect, &destrect, __LINE__); - res=(*pPrimaryBlt)(lpDDSEmu_Prim, &destrect, lpDDSSource, &emurect); - - if (res) BlitError(res, &emurect, &destrect, __LINE__); - if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK; - if (IsDebug) OutTrace("%s: done ret=%x at %d\n", api, res, __LINE__); - return res; -} - -HRESULT WINAPI sBlt(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, - LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx, BOOL isFlipping) -{ - POINT p = {0, 0}; - HRESULT res; - BOOL ToPrim, FromPrim, ToScreen, FromScreen; - - if(dxw.dwFlags5 & MESSAGEPUMP){ - MSG msg; - while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){ - OutTraceW("MESSAGEPUMP: msg=%x l-wParam=(%x,%x)\n", msg.message, msg.lParam, msg.wParam); - if((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST)) break; // do not consume keyboard inputs - PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - ToPrim=dxw.IsAPrimarySurface(lpdds); - FromPrim=dxw.IsAPrimarySurface(lpddssrc); - ToScreen=ToPrim && !(dxw.dwFlags1 & EMULATESURFACE); - FromScreen=FromPrim && !(dxw.dwFlags1 & EMULATESURFACE) && !(dxw.dwFlags1 & EMULATEBUFFER); // v2.02.77 - - CleanRect(&lpdestrect,__LINE__); - CleanRect(&lpsrcrect,__LINE__); - - // log - if(IsTraceDW){ - char sLog[256]; - char sInfo[128]; - sprintf(sLog, "%s: dest=%x%s src=%x%s dwFlags=%x(%s)", - api, lpdds, (ToPrim ? "(PRIM)":""), lpddssrc, (FromPrim ? "(PRIM)":""), dwflags, ExplainBltFlags(dwflags)); - if (lpdestrect) - sprintf(sInfo, " destrect=(%d,%d)-(%d,%d)", lpdestrect->left, lpdestrect->top, lpdestrect->right, lpdestrect->bottom); - else - sprintf(sInfo, " destrect=(NULL)"); - strcat(sLog, sInfo); - if (lpsrcrect) - sprintf(sInfo, " srcrect=(%d,%d)-(%d,%d)", lpsrcrect->left, lpsrcrect->top, lpsrcrect->right, lpsrcrect->bottom); - else - sprintf(sInfo, " srcrect=(NULL)"); - strcat(sLog, sInfo); - if(lpddbltfx){ - if (dwflags & DDBLT_COLORFILL){ - sprintf(sInfo, " ddbltfx.FillColor=%x", lpddbltfx->dwFillColor); - strcat(sLog, sInfo); - } - if (dwflags & DDBLT_KEYDESTOVERRIDE){ - sprintf(sInfo, " ddbltfx.DestColorkey=%x", lpddbltfx->ddckDestColorkey); - strcat(sLog, sInfo); - } - if (dwflags & DDBLT_KEYSRCOVERRIDE){ - sprintf(sInfo, " ddbltfx.SrcColorkey=%x", lpddbltfx->ddckSrcColorkey); - strcat(sLog, sInfo); - } - if (dwflags & DDBLT_ROP){ - sprintf(sInfo, " ddbltfx.ROP=%x", lpddbltfx->dwROP); - strcat(sLog, sInfo); - } - if (dwflags & DDBLT_DEPTHFILL){ - sprintf(sInfo, " ddbltfx.FillDepth=%x", lpddbltfx->dwFillDepth); - strcat(sLog, sInfo); - } - } - strcat(sLog,"\n"); - OutTrace(sLog); - } - - if(ToPrim) - res = sBltToPrimary(api, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx, isFlipping); - else - res = sBltNoPrimary(api, lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx); - - return res; -} - HRESULT WINAPI extFlip(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags) { BOOL IsPrim; @@ -4582,7 +4256,7 @@ HRESULT WINAPI extEnumAttachedSurfaces(LPDIRECTDRAWSURFACE lpdds, LPVOID lpConte HRESULT WINAPI extAddAttachedSurface(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd) { HRESULT res; - BOOL IsPrim; + BOOL IsPrim, IsBack; // You can add backbuffers to primary surfaces to join the flipping chain, but you can't do that // to an emulated primary surface, and you receive a DDERR_CANNOTATTACHSURFACE error code. @@ -4591,7 +4265,9 @@ HRESULT WINAPI extAddAttachedSurface(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURF // But beware: this holds to BACKBUFFER surfaces only, and NOT for attached ZBUFFERS or similar! IsPrim=dxw.IsAPrimarySurface(lpdds); - OutTraceDDRAW("AddAttachedSurface: lpdds=%x%s lpddsadd=%x\n", lpdds, IsPrim?"(PRIM)":"", lpddsadd); + IsBack=dxw.IsABackBufferSurface(lpdds); + OutTraceDDRAW("AddAttachedSurface: lpdds=%x%s lpddsadd=%x%s\n", lpdds, IsPrim?"(PRIM)":(IsBack?"(BACK)":""), lpddsadd, (lpddsadd==lpDDZBuffer)?"(ZBUF)":""); + //if(!lpddsadd) return DDERR_CANNOTATTACHSURFACE; // to avoid a crash... res=(*pAddAttachedSurface)(lpdds, lpddsadd); if (res) { @@ -4613,7 +4289,7 @@ HRESULT WINAPI extAddAttachedSurface(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURF if (pAddRefS) (*pAddRefS)(lpdds); res=DD_OK; } - else if (lpdds == lpDDSBack) { + else if (IsBack) { // v2.02.13: emulate ZBUFFER attach to backbuffer: do nothing and return OK // this trick makes at least "Nocturne" work also in emulated mode when hardware acceleration // is set in the game "Options" menu. diff --git a/dll/dxwcore.cpp b/dll/dxwcore.cpp index b6e6f50..1aa22da 100644 --- a/dll/dxwcore.cpp +++ b/dll/dxwcore.cpp @@ -1413,6 +1413,7 @@ void dxwCore::ShowBanner(HWND hwnd) RECT client; RECT win; POINT PrevViewPort; + int StretchMode; hClientDC=(*pGDIGetDC)(hwnd); (*pGetClientRect)(hwnd, &client); @@ -1432,6 +1433,8 @@ void dxwCore::ShowBanner(HWND hwnd) //if(!pSetViewportOrgEx) pSetViewportOrgEx=SetViewportOrgEx; (*pSetViewportOrgEx)(hClientDC, 0, 0, &PrevViewPort); + StretchMode=GetStretchBltMode(hClientDC); + SetStretchBltMode(hClientDC, HALFTONE); for (int i=1; i<=16; i++){ int w, h; w=(bm.bmWidth*i)/8; @@ -1447,6 +1450,7 @@ void dxwCore::ShowBanner(HWND hwnd) (*pGDIStretchBlt)(hClientDC, (client.right-w)/2, (client.bottom-h)/2, w, h, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); Sleep(40); } + SetStretchBltMode(hClientDC, StretchMode); (*pSetViewportOrgEx)(hClientDC, PrevViewPort.x, PrevViewPort.y, NULL); SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); diff --git a/dll/dxwnd.aps b/dll/dxwnd.aps index be1bf616a727e51e670edda5895cfca4fb0cd760..e6a97c4a5d52c874cd6def819b181398c57b0eaa 100644 GIT binary patch delta 28 icmZ3mjA_9#rU?;@mK!5Q`xz}a=l82H0jVhydl&(ip$ZWI delta 28 icmZ3mjA_9#rU?;@W*Z|#`x(tP=l82H0jVhydl&(iFA4|% diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index 14f8ed0..16e2f03 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.08" +#define VERSION "2.03.09" #define DDTHREADLOCK 1 //#define LOCKTHREADS @@ -176,7 +176,11 @@ int SetTarget(TARGETMAP *targets){ for(i = 0; targets[i].path[0]; i ++){ char *c; pMapping[i] = targets[i]; - GetFullPathName(targets[i].path, MAX_PATH, path, NULL); + c = targets[i].path; + if(*c == '*') + strcpy(path, targets[i].path); + else + GetFullPathName(targets[i].path, MAX_PATH, path, NULL); for(c = path; *c; c++) *c = tolower(*c); strcpy(pMapping[i].path, path); } diff --git a/dll/dxwnd.def b/dll/dxwnd.def index 2b4fd5a..a4d06bb 100644 --- a/dll/dxwnd.def +++ b/dll/dxwnd.def @@ -1,8 +1,10 @@ LIBRARY dxwnd EXPORTS - SetTarget @1 - StartHook @2 - EndHook @3 - GetDllVersion @4 - GetHookStatus @5 - GetHookInfo @6 + SetTarget @1 + StartHook @2 + EndHook @3 + GetDllVersion @4 + GetHookStatus @5 + GetHookInfo @6 + Inject @7 + GetThreadStartAddress @8 diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index 0154b49a0ee90a78fc19fa034b7cc82c90e2ed3d..0be041d4e2f0d09ee090114309279e2baa9b3614 100644 GIT binary patch literal 47616 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 YGHti?m*c+%x`QomLHlRpo*aMv4?)Nv_5c6? literal 77312 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 UQ=;7=^(kbbFrjR0p&RA=1>BmxT>t<8 diff --git a/dll/dxwnd.vs2008.vcproj b/dll/dxwnd.vs2008.vcproj index 6b69dfd..e0816fe 100644 --- a/dll/dxwnd.vs2008.vcproj +++ b/dll/dxwnd.vs2008.vcproj @@ -233,6 +233,10 @@ RelativePath=".\d3dtexture.cpp" > + + diff --git a/dll/gdiblt.cpp b/dll/gdiblt.cpp index 8b386f3..134994b 100644 --- a/dll/gdiblt.cpp +++ b/dll/gdiblt.cpp @@ -40,6 +40,10 @@ void BlitToWindow(HWND w, LPDIRECTDRAWSURFACE s) if(!ret) OutTrace("BitBlt error=%d\n", GetLastError()); } else{ + if(dxw.dwFlags5 & BILINEARFILTER) { + ret=SetStretchBltMode(thdc, HALFTONE); + if((!ret) || (ret==ERROR_INVALID_PARAMETER)) OutTrace("GDI SetStretchBltMode error=%d\n", GetLastError()); + } ret=(*pGDIStretchBlt)(thdc, 0, 0, client.right, client.bottom, shdc, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), SRCCOPY); if(!ret) OutTrace("GDI StretchBlt error=%d\n", GetLastError()); } diff --git a/dll/hd3d7.cpp b/dll/hd3d7.cpp index 8fa743c..a4513eb 100644 --- a/dll/hd3d7.cpp +++ b/dll/hd3d7.cpp @@ -1,5 +1,8 @@ +#define _CRT_SECURE_NO_WARNINGS + #include #include +#include #include "dxwnd.h" #include "dxwcore.hpp" #include "dxhook.h" @@ -32,6 +35,7 @@ typedef HRESULT (WINAPI *FindDevice_Type)(void *, LPD3DFINDDEVICESEARCH, LPD3DFI typedef HRESULT (WINAPI *CreateDevice2_Type)(void *, REFCLSID, LPDIRECTDRAWSURFACE, LPDIRECT3DDEVICE2 *); typedef HRESULT (WINAPI *CreateDevice3_Type)(void *, REFCLSID, LPDIRECTDRAWSURFACE4, LPDIRECT3DDEVICE3 *, LPUNKNOWN); typedef HRESULT (WINAPI *CreateDevice7_Type)(void *, REFCLSID, LPDIRECTDRAWSURFACE7, LPDIRECT3DDEVICE7 *); +typedef HRESULT (WINAPI *EnumZBufferFormats_Type)(void *, REFCLSID, LPD3DENUMPIXELFORMATSCALLBACK, LPVOID); QueryInterfaceD3_Type pQueryInterfaceD3 = NULL; Initialize_Type pInitialize = NULL; @@ -46,6 +50,9 @@ FindDevice_Type pFindDevice = NULL; CreateDevice2_Type pCreateDevice2 = NULL; CreateDevice3_Type pCreateDevice3 = NULL; CreateDevice7_Type pCreateDevice7 = NULL; +EnumZBufferFormats_Type pEnumZBufferFormats = NULL; + +HRESULT WINAPI extEnumZBufferFormats(void *, REFCLSID, LPD3DENUMPIXELFORMATSCALLBACK, LPVOID); // Direct3DDevice-n interfaces @@ -216,6 +223,89 @@ HRESULT WINAPI extTexUnload(void *); extern char *ExplainDDError(DWORD); int GD3DDeviceVersion; +static char *sFourCC(DWORD fcc) +{ + static char sRet[5]; + char c; + int i; + char *t=&sRet[0]; + for(i=0; i<4; i++){ + c = fcc & (0xFF); + *t++ = isprint(c) ? c : '.'; + c = c >> 8; + } + *t = 0; + return sRet; +} + +char *DumpPixelFormat(LPDDPIXELFORMAT ddpfPixelFormat) +{ + static char sBuf[512]; + char sItem[256]; + DWORD flags=ddpfPixelFormat->dwFlags; + sprintf(sBuf, " PixelFormat flags=%x(%s) BPP=%d", + flags, ExplainPixelFormatFlags(flags), ddpfPixelFormat->dwRGBBitCount); + if (flags & DDPF_RGB) { + if (flags & DDPF_ALPHAPIXELS) { + sprintf(sItem, " RGBA=(%x,%x,%x,%x)", + ddpfPixelFormat->dwRBitMask, + ddpfPixelFormat->dwGBitMask, + ddpfPixelFormat->dwBBitMask, + ddpfPixelFormat->dwRGBAlphaBitMask); + } + else { + sprintf(sItem, " RGB=(%x,%x,%x)", + ddpfPixelFormat->dwRBitMask, + ddpfPixelFormat->dwGBitMask, + ddpfPixelFormat->dwBBitMask); + } + strcat(sBuf, sItem); + } + if (flags & DDPF_YUV) { + sprintf(sItem, " YUVA=(%x,%x,%x,%x)", + ddpfPixelFormat->dwYBitMask, + ddpfPixelFormat->dwUBitMask, + ddpfPixelFormat->dwVBitMask, + ddpfPixelFormat->dwYUVAlphaBitMask); + strcat(sBuf, sItem); + } + if (flags & DDPF_ZBUFFER) { + sprintf(sItem, " SdZSbL=(%x,%x,%x,%x)", + ddpfPixelFormat->dwStencilBitDepth, + ddpfPixelFormat->dwZBitMask, + ddpfPixelFormat->dwStencilBitMask, + ddpfPixelFormat->dwLuminanceAlphaBitMask); + strcat(sBuf, sItem); + } + if (flags & DDPF_ALPHA) { + sprintf(sItem, " LBdBlZ=(%x,%x,%x,%x)", + ddpfPixelFormat->dwLuminanceBitMask, + ddpfPixelFormat->dwBumpDvBitMask, + ddpfPixelFormat->dwBumpLuminanceBitMask, + ddpfPixelFormat->dwRGBZBitMask); + strcat(sBuf, sItem); + } + if (flags & DDPF_LUMINANCE) { + sprintf(sItem, " BMbMF=(%x,%x,%x,%x)", + ddpfPixelFormat->dwBumpDuBitMask, + ddpfPixelFormat->MultiSampleCaps.wBltMSTypes, + ddpfPixelFormat->MultiSampleCaps.wFlipMSTypes, + ddpfPixelFormat->dwYUVZBitMask); + strcat(sBuf, sItem); + } + if (flags & DDPF_BUMPDUDV) { + sprintf(sItem, " O=(%x)", + ddpfPixelFormat->dwOperations); + strcat(sBuf, sItem); + } + if (flags & DDPF_FOURCC) { + sprintf(sItem, " FourCC=%x(%s)", + ddpfPixelFormat->dwFourCC, sFourCC(ddpfPixelFormat->dwFourCC)); + strcat(sBuf, sItem); + } + return sBuf; +} + int HookDirect3D7(HMODULE module, int version){ void *tmp; HINSTANCE hinst; @@ -305,6 +395,7 @@ void HookDirect3DSession(LPDIRECTDRAW *lplpdd, int d3dversion) SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateViewport3, (void **)&pCreateViewport3, "CreateViewport(3)"); SetHook((void *)(**(DWORD **)lplpdd + 28), extFindDevice, (void **)&pFindDevice, "FindDevice"); SetHook((void *)(**(DWORD **)lplpdd + 32), extCreateDevice3, (void **)&pCreateDevice3, "CreateDevice(D3D3)"); + SetHook((void *)(**(DWORD **)lplpdd + 40), extEnumZBufferFormats, (void **)&pEnumZBufferFormats, "EnumZBufferFormats(D3D3)"); break; case 7: SetHook((void *)(**(DWORD **)lplpdd + 0), extQueryInterfaceD3, (void **)&pQueryInterfaceD3, "QueryInterface(D3S)"); @@ -1420,3 +1511,30 @@ HRESULT WINAPI extTexUnload(void *t) if(ret) OutTraceE("Texture::Load ERROR res=%x(%s)\n", ret, ExplainDDError(ret)); return ret; } + +typedef struct { + LPD3DENUMPIXELFORMATSCALLBACK *cb; + LPVOID arg; +} CallbackZBufArg; + +HRESULT WINAPI extZBufferProxy(LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext) +{ + HRESULT res; + OutTraceD3D("EnumZBufferFormats: CALLBACK PixelFormat=%x(%s) context=%x\n", lpDDPixFmt->dwFlags, lpContext); + res = (*(((CallbackZBufArg *)lpContext)->cb))(lpDDPixFmt, ((CallbackZBufArg *)lpContext)->arg); + OutTraceD3D("EnumDevices: CALLBACK ret=%x\n", res); + return res; +} + +HRESULT WINAPI extEnumZBufferFormats(void *lpd3d, REFCLSID riidDevice, LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback, LPVOID lpContext) +{ + HRESULT ret; + CallbackZBufArg Arg; + OutTrace("Direct3D::EnumZBufferFormats d3d=%x clsid=%x context=%x\n", lpd3d, riidDevice.Data1, lpContext); + Arg.cb= &lpEnumCallback; + Arg.arg=lpContext; + ret = (*pEnumZBufferFormats)(lpd3d, riidDevice, (LPD3DENUMPIXELFORMATSCALLBACK)extZBufferProxy, (LPVOID)&Arg); + OutTraceE("Direct3D::EnumZBufferFormats res=%x(%s)\n", ret, ExplainDDError(ret)); + return ret; +} + diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index 268e46e..1247f80 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -853,6 +853,9 @@ BOOL WINAPI extCreateProcessA( } #endif OutTrace("CreateProcess: injection started\n", res); + CloseHandle(((CREATE_PROCESS_DEBUG_INFO *)&debug_event.u)->hProcess); + CloseHandle(((CREATE_PROCESS_DEBUG_INFO *)&debug_event.u)->hThread); + CloseHandle(((CREATE_PROCESS_DEBUG_INFO *)&debug_event.u)->hFile); break; case EXIT_THREAD_DEBUG_EVENT: #ifdef LOCKINJECTIONTHREADS @@ -881,8 +884,16 @@ BOOL WINAPI extCreateProcessA( debug_event.u.Exception.dwFirstChance); // exception twice in same address, then do not continue. if(LastExceptionPtr == ei->ExceptionRecord.ExceptionAddress) bContinueDebugging = FALSE; + //if(ei->dwFirstChance == 0) bContinueDebugging = FALSE; LastExceptionPtr = ei->ExceptionRecord.ExceptionAddress; } + break; + case LOAD_DLL_DEBUG_EVENT: + CloseHandle(((LOAD_DLL_DEBUG_INFO *)&debug_event.u)->hFile); + break; + case CREATE_THREAD_DEBUG_EVENT: + CloseHandle(((CREATE_THREAD_DEBUG_INFO *)&debug_event.u)->hThread); + break; default: break; } diff --git a/host/Inject.cpp b/host/Inject.cpp deleted file mode 100644 index cca0596..0000000 --- a/host/Inject.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "stdafx.h" -#include -#include -#include -#include -#include - -#include - -#define WIN32_LEAN_AND_MEAN - -#define true 1 -#define false 0 - -BOOL Inject(DWORD pID, const char * DLL_NAME) -{ - HANDLE Proc; - char buf[50] = {0}; - LPVOID RemoteString, LoadLibAddy; - if(!pID) return false; - //Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); // not working on Win XP - Proc = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, FALSE, pID); - if(!Proc) - { - sprintf(buf, "OpenProcess() failed: pid=%x err=%d", pID, GetLastError()); - MessageBox(NULL, buf, "Loader", MB_OK); - printf(buf); - return false; - } - LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); - // Allocate space in the process for our DLL - RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - // Write the string name of our DLL in the memory allocated - WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL); - // Load our DLL - CreateRemoteThread(Proc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, 0, NULL); - CloseHandle(Proc); - return true; -} - -#define STATUS_SUCCESS ((NTSTATUS)0x000 00000L) -#define ThreadQuerySetWin32StartAddress 9 - -LPVOID GetThreadStartAddress(HANDLE hThread) -{ - NTSTATUS ntStatus; - HANDLE hDupHandle; - HMODULE hLibNTHandle; - LPVOID dwStartAddress; - - typedef NTSTATUS (WINAPI *NtQueryInformationThread_Type)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); - hLibNTHandle = GetModuleHandle("ntdll.dll"); - if(!hLibNTHandle) return 0; - - NtQueryInformationThread_Type NtQueryInformationThread = - (NtQueryInformationThread_Type)GetProcAddress(hLibNTHandle, "NtQueryInformationThread"); - - if(NtQueryInformationThread == NULL) return 0; - - HANDLE hCurrentProcess = GetCurrentProcess(); - if(!DuplicateHandle(hCurrentProcess, hThread, hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)){ - SetLastError(ERROR_ACCESS_DENIED); - return 0; - } - - ntStatus = NtQueryInformationThread(hDupHandle, (THREADINFOCLASS)ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD), NULL); - CloseHandle(hDupHandle); - CloseHandle(hLibNTHandle); - //if(ntStatus != STATUS_SUCCESS) return 0; - - return dwStartAddress; -} \ No newline at end of file diff --git a/host/Resource.h b/host/Resource.h index d7d2175aa06a7aec3eafae4a4dbc02189b6202c6..f4f11c7bb121752e75f7bc3e95125447e2c8970e 100644 GIT binary patch delta 54 zcmaFzkMY2N#tjWIlO1H)gk2dT7(y6A8G;yG8Qd8Bfwb@BdT!;(2{CMwT}s3zZ-`^t J+!XUj2>|Gg5qtmu delta 14 WcmX@`pYh2*#tjWIoA1OtQ33!!V+bJt diff --git a/host/TabDirectX.cpp b/host/TabDirectX.cpp index 343ac33..f419f72 100644 --- a/host/TabDirectX.cpp +++ b/host/TabDirectX.cpp @@ -32,6 +32,7 @@ void CTabDirectX::DoDataExchange(CDataExchange* pDX) DDX_Check(pDX, IDC_SUPPRESSCLIPPING, cTarget->m_SuppressClipping); DDX_Check(pDX, IDC_BLITFROMBACKBUFFER, cTarget->m_BlitFromBackBuffer); DDX_Check(pDX, IDC_AUTOREFRESH, cTarget->m_AutoRefresh); + DDX_Check(pDX, IDC_TEXTUREFORMAT, cTarget->m_TextureFormat); DDX_Check(pDX, IDC_VIDEOTOSYSTEMMEM, cTarget->m_VideoToSystemMem); DDX_Check(pDX, IDC_SUPPRESSDXERRORS, cTarget->m_SuppressDXErrors); DDX_Check(pDX, IDC_BACKBUFATTACH, cTarget->m_BackBufAttach); diff --git a/host/TargetDlg.cpp b/host/TargetDlg.cpp index 290dc6c..8191f9f 100644 --- a/host/TargetDlg.cpp +++ b/host/TargetDlg.cpp @@ -96,6 +96,7 @@ CTargetDlg::CTargetDlg(CWnd* pParent /*=NULL*/) m_SuppressClipping = FALSE; m_DisableGammaRamp = FALSE; m_AutoRefresh = FALSE; + m_TextureFormat = FALSE; m_FixWinFrame = FALSE; m_EnableClipping = FALSE; m_CursorClipping = FALSE; diff --git a/host/TargetDlg.h b/host/TargetDlg.h index 98db7a8..d7d5024 100644 --- a/host/TargetDlg.h +++ b/host/TargetDlg.h @@ -76,6 +76,7 @@ public: BOOL m_SuppressClipping; BOOL m_DisableGammaRamp; BOOL m_AutoRefresh; + BOOL m_TextureFormat; BOOL m_FixWinFrame; BOOL m_EnableClipping; BOOL m_CursorClipping; diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps index eb7f1737aac27714ef9a0ee78ff0f99c0bce06b7..409a30b7392c865bd87b8692b7b5d22acff97af0 100644 GIT binary patch delta 19274 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 delta 26 kcmV+#0OkLn=mm!61+esilL+S?vV*87le(!?vnZ_i$GmY4SpWb4 diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo index 26961b3c318261b9bedeecc6fe3f51ddcdc60c90..c0f885500483e051b708f3ec6d55e4a83daebaf7 100644 GIT binary patch delta 44906 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 delta 2540 zcmbVOe{56N6@K5%v*Y}n6CC42CV4To6G$2v6O!O&shh2o&=3XFR?&oLU|WUKEX~qw z>M}r1_M`iQbitSAL=09Zs!~QNV{w}|0YYA>OxKnuMJUbq%Z)&*5HMPy4pk`GdCrfu zY}3%5bdq2=}BQzWsA81_hJL)-wNsby*<{D@he!; zzv}CIg?%%hkmuEPD^r_jgJ6V&WK3%~wF#egJi*Hot|9$S( z{QsVh&E@tA5m97sUa$EK=cH%IFZ1?`6H2T%zfv`z$>fMFHf6snkhZ+BS@JH|8)IJ< zcC1q8IJ?-M+9QQ9OVhS9)VN;slsu)ppnPBHQL2} z*o+jYl~?2#Ih8EV%u}BW4yN zx^pwGLTV$K1}-P}9ubXno%faPN4>O{5$knf zbc4e6DAtR&U=~9!bDZc+UU#JrUfF%Lh*~`i-hTi;S@LVa>^ce!vt#!f29X@Vdl=ec z!0E@;4A~RajJ(`*<2TH+DL2YfTg3uLx}diYgW2Gl&ZMf>IE%GW)JzN_t~Qt#)c2_& zdZj=)W;!I8;q&vai{*Avx38LyY2nfKrrwvv`rILiH0j@~>ES5CAngPK6c~qhsNVo~ z7*|cS`(gO>!EvadL*sCfbppr7MxmzppV=sLf9|J_F)mHzHXA)NhFluGh822v3_+EG zKN3NFhj0Q-)c&~0*LS>u*C0Q!70}jB5lYEBIAW)lo)=FR8t}vEr_=ro{@6)?`gLaV zq`jDC-sHl(b%Sx7Y64fe6gGY85AX>ZA7J+M&_^Dzz@FeuF6N{Tzr5Aq)xD=tgo(Ed zF14P)DXDEQlG$Z;-IstB6Mupb)OZ2ssJ()#pE|qB_hCcCqv_gNBs1hYp%-bgR+#DB z2WX_K4We8xpMeAPd4iAhwntd$Tmr=u9)Lv;y@!*a;9t?Dt2YnkGVup;3c!SJ0P5mmdts+z3n9G&W<*s{R?qR8Bv_yq+i$pE9jYg5ze3WR~pz*p~`Rnpe`U&jg`MsZZ>Rc5S09&$!-T&1e`sV$I*NCwQ@omrcPhk58u7{= z6v}AV0u;Uqij0*zRzHAJspE%>2{4si3(NkaLhj4^`g8wU=A`p2;^~mK_kf}K1>HaR z{k)L-SN+%VC%|U5QhM}Ftgtq-hjEQAxlsHE!iF}3%uTePr6muyc{!pzBQFKY^}=olmLB}z^YWkCO*I-y0lSLQGceWA#J;O zn=X`Kqd^JZeSf58aYmly=2b7QvIHYWr?|*Kd}{7cg{YIk5r;n5Ai7x=Ylg}37+R_P zFPIscMo7+dmb0JPxU5~Nljg#6yABDJh8snBByy6DUu0SS;#;Dg!VMzGR{&E%`!;`r lZCw76Fqd+jIoCgz;1Ld&Wm&o!`6FxrEn{?iZI<2Ce*#;_6Q=+G diff --git a/host/dxwndhost.vs2008.vcproj b/host/dxwndhost.vs2008.vcproj index 50c6eb3..16172cb 100644 --- a/host/dxwndhost.vs2008.vcproj +++ b/host/dxwndhost.vs2008.vcproj @@ -323,10 +323,6 @@ RelativePath=".\host.rc" > - - diff --git a/host/dxwndhostView.cpp b/host/dxwndhostView.cpp index 1c6afd9..2e689d1 100644 --- a/host/dxwndhostView.cpp +++ b/host/dxwndhostView.cpp @@ -35,7 +35,6 @@ TARGETMAP *pTargets; // idem. #define LOCKINJECTIONTHREADS - static char *Escape(char *s) { static char tmp[1024]; @@ -276,6 +275,7 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg) if(dlg->m_SuppressClipping) t->flags |= SUPPRESSCLIPPING; if(dlg->m_DisableGammaRamp) t->flags2 |= DISABLEGAMMARAMP; if(dlg->m_AutoRefresh) t->flags |= AUTOREFRESH; + if(dlg->m_TextureFormat) t->flags5 |= TEXTUREFORMAT; if(dlg->m_FixWinFrame) t->flags |= FIXWINFRAME; if(dlg->m_EnableClipping) t->flags |= ENABLECLIPPING; if(dlg->m_CursorClipping) t->flags |= CLIPCURSOR; @@ -482,6 +482,7 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg) dlg->m_SuppressClipping = t->flags & SUPPRESSCLIPPING ? 1 : 0; dlg->m_DisableGammaRamp = t->flags2 & DISABLEGAMMARAMP ? 1 : 0; dlg->m_AutoRefresh = t->flags & AUTOREFRESH ? 1 : 0; + dlg->m_TextureFormat = t->flags5 & TEXTUREFORMAT ? 1 : 0; dlg->m_FixWinFrame = t->flags & FIXWINFRAME ? 1 : 0; dlg->m_EnableClipping = t->flags & ENABLECLIPPING ? 1 : 0; dlg->m_CursorClipping = t->flags & CLIPCURSOR ? 1 : 0; @@ -1673,6 +1674,38 @@ void CDxwndhostView::OnRButtonDown(UINT nFlags, CPoint point) CListView::OnRButtonDown(nFlags, point); } +static char *ExceptionCaption(DWORD ec) +{ + char *c; + switch(ec){ + case EXCEPTION_ACCESS_VIOLATION: c="Access Violation"; break; + case EXCEPTION_DATATYPE_MISALIGNMENT: c="Datatype Misalignment"; break; + case EXCEPTION_BREAKPOINT: c="Breakpoint"; break; + case EXCEPTION_SINGLE_STEP: c="Single Step"; break; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: c="Array Bouds Exceeded"; break; + case EXCEPTION_FLT_DENORMAL_OPERAND: c="Float Denormal Operand"; break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: c="Divide by Zero"; break; + case EXCEPTION_FLT_INEXACT_RESULT: c="Inexact Result"; break; + case EXCEPTION_FLT_INVALID_OPERATION: c="Invalid Operation"; break; + case EXCEPTION_FLT_OVERFLOW: c="Float Overflow"; break; + case EXCEPTION_FLT_STACK_CHECK: c="Float Stack Check"; break; + case EXCEPTION_FLT_UNDERFLOW: c="Float Undeflow"; break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: c="Integer Divide by Zero"; break; + case EXCEPTION_INT_OVERFLOW: c="Integer Overflow"; break; + case EXCEPTION_PRIV_INSTRUCTION: c="Priviliged Instruction"; break; + case EXCEPTION_IN_PAGE_ERROR: c="In Page Error"; break; + case EXCEPTION_ILLEGAL_INSTRUCTION: c="Illegal Instruction"; break; + case EXCEPTION_NONCONTINUABLE_EXCEPTION:c="Non-continuable exception"; break; + case EXCEPTION_STACK_OVERFLOW: c="Stack Overflow"; break; + case EXCEPTION_INVALID_DISPOSITION: c="Invalid Disposition"; break; + case EXCEPTION_GUARD_PAGE: c="Guard Page Violation"; break; + case EXCEPTION_INVALID_HANDLE: c="Invalid Handle"; break; + //case EXCEPTION_POSSIBLE_DEADLOCK: c="Possible Deadlock"; break; + default: c="unknown"; break; + } + return c; +} + // For thread messaging #define DEBUG_EVENT_MESSAGE WM_APP + 0x100 @@ -1699,13 +1732,13 @@ DWORD WINAPI StartDebug(void *p) int res; BOOL step=TRUE; // initialize to TRUE to enable BOOL stepdll=FALSE; // initialize to TRUE to enable + extern char *GetFileNameFromHandle(HANDLE); #endif #ifdef LOCKINJECTIONTHREADS DWORD StartingCode; LPVOID StartAddress = 0; - DWORD TargetHandle = NULL; + HANDLE TargetHandle = NULL; #endif - extern char *GetFileNameFromHandle(HANDLE); bool bContinueDebugging; char DebugMessage[256+1]; @@ -1728,30 +1761,12 @@ DWORD WINAPI StartDebug(void *p) while(bContinueDebugging) { dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED; - if (!WaitForDebugEvent(&debug_event, INFINITE)) return TRUE; + if (!WaitForDebugEvent(&debug_event, INFINITE)) break; // must release pinfo handles switch(debug_event.dwDebugEventCode){ case EXIT_PROCESS_DEBUG_EVENT: -#ifdef DXWDEBUGSTEPPING - if(step){ - // DXW_STRING_STEPPING - xpi=(EXIT_PROCESS_DEBUG_INFO *)&debug_event.u; - sprintf(DebugMessage, "EXIT PROCESS RetCode=%x", xpi->dwExitCode); - res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL); - if(res!=IDYES) step=FALSE; - } -#endif bContinueDebugging=false; break; case CREATE_PROCESS_DEBUG_EVENT: -#ifdef DXWDEBUGSTEPPING - if(step){ - pi=(PROCESS_INFORMATION *)&debug_event.u; - sprintf(DebugMessage, "CREATE PROCESS hProcess=%x hThread=%x dwProcessId=%x dwThreadId=%x path=%s", - pi->hProcess, pi->hThread, pi->dwProcessId, pi->dwThreadId, GetFileNameFromHandle(pi->hProcess)); - res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL); - if(res!=IDYES) step=FALSE; - } -#endif GetFullPathName("dxwnd.dll", MAX_PATH, path, NULL); if(!Inject(pinfo.dwProcessId, path)){ // DXW_STRING_INJECTION @@ -1763,20 +1778,14 @@ DWORD WINAPI StartDebug(void *p) DWORD EndlessLoop; EndlessLoop=0x9090FEEB; // careful: it's BIG ENDIAN: EB FE 90 90 SIZE_T BytesCount; - TargetHandle = (DWORD)OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, FALSE, pinfo.dwProcessId); + TargetHandle = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, FALSE, pinfo.dwProcessId); if(TargetHandle){ - //sprintf(DebugMessage,"OpenProcess returns=%x", TargetHandle); - //MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); StartAddress = GetThreadStartAddress(pinfo.hThread); - //sprintf(DebugMessage,"GetThreadStartAddress returns=%x", StartAddress); - //MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); if(StartAddress){ if(!ReadProcessMemory(pinfo.hProcess, StartAddress, &StartingCode, 4, &BytesCount)){ sprintf(DebugMessage,"ReadProcessMemory error=%d", GetLastError()); MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); } - //sprintf(DebugMessage,"ReadProcessMemory got=%x", StartingCode); - //MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); if(!WriteProcessMemory(pinfo.hProcess, StartAddress, &EndlessLoop, 4, &BytesCount)){ sprintf(DebugMessage,"WriteProcessMemory error=%d", GetLastError()); MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); @@ -1784,95 +1793,55 @@ DWORD WINAPI StartDebug(void *p) } } #endif + CloseHandle(((CREATE_PROCESS_DEBUG_INFO *)&debug_event.u)->hProcess); + CloseHandle(((CREATE_PROCESS_DEBUG_INFO *)&debug_event.u)->hThread); + CloseHandle(((CREATE_PROCESS_DEBUG_INFO *)&debug_event.u)->hFile); break; case CREATE_THREAD_DEBUG_EVENT: -#ifdef DXWDEBUGSTEPPING - if(step){ - ti=(CREATE_THREAD_DEBUG_INFO *)&debug_event.u; - sprintf(DebugMessage, "CREATE THREAD hThread=%x lpThreadLocalBase=%x lpStartAddress=%x", - ti->hThread, ti->lpThreadLocalBase, ti->lpStartAddress); - res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL); - if(res!=IDYES) step=FALSE; - } -#endif + CloseHandle(((CREATE_THREAD_DEBUG_INFO *)&debug_event.u)->hThread); break; case EXIT_THREAD_DEBUG_EVENT: -#ifdef DXWDEBUGSTEPPING - if(step){ - xti=(EXIT_THREAD_DEBUG_INFO *)&debug_event.u; - sprintf(DebugMessage, "EXIT THREAD RetCode=%x", xti->dwExitCode); - res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL); - if(res!=IDYES) step=FALSE; - } -#endif #ifdef LOCKINJECTIONTHREADS if(TargetHandle && StartAddress){ - //sprintf(DebugMessage,"OpenProcess returns=%x", TargetHandle); - //MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); if(!WriteProcessMemory(pinfo.hProcess, StartAddress, &StartingCode, 4, &BytesCount)){ sprintf(DebugMessage,"WriteProcessMemory error=%d", GetLastError()); MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); } - //sprintf(DebugMessage,"WriteProcessMemory recovered=%x", StartingCode); - //MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); - CloseHandle((HANDLE)TargetHandle); } + if(TargetHandle) CloseHandle((HANDLE)TargetHandle); #endif bContinueDebugging=false; break; case LOAD_DLL_DEBUG_EVENT: -#ifdef DXWDEBUGSTEPPING - if(stepdll){ - li=(LOAD_DLL_DEBUG_INFO *)&debug_event.u; - sprintf(DebugMessage, "LOAD DLL hFile=%x path=%s", - li->hFile, GetFileNameFromHandle(li->hFile)); - res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL); - if(res!=IDYES) stepdll=FALSE; - } -#endif + CloseHandle(((LOAD_DLL_DEBUG_INFO *)&debug_event.u)->hFile); break; case UNLOAD_DLL_DEBUG_EVENT: -#ifdef DXWDEBUGSTEPPING - if(stepdll){ - ui=(UNLOAD_DLL_DEBUG_INFO *)&debug_event.u; - sprintf(DebugMessage, "UNLOAD DLL Base=%x", ui->lpBaseOfDll); - res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL); - if(res!=IDYES) stepdll=FALSE; - } -#endif break; case OUTPUT_DEBUG_STRING_EVENT: break; case EXCEPTION_DEBUG_EVENT: -#ifdef DXWDEBUGSTEPPING - if(step){ - ei=(EXCEPTION_DEBUG_INFO *)&debug_event.u; - sprintf(DebugMessage, "EXCEPTION code=%x flags=%x addr=%x firstchance=%x", - ei->ExceptionRecord.ExceptionCode, - ei->ExceptionRecord.ExceptionFlags, - ei->ExceptionRecord.ExceptionAddress, - debug_event.u.Exception.dwFirstChance); - res=MessageBoxEx(0, DebugMessage, "Continue stepping?", MB_YESNO | MB_ICONQUESTION, NULL); - if(res!=IDYES) step=FALSE; - } -#endif + //sprintf(DebugMessage, "Exception %x(%s) caught at addr=%x", + // debug_event.u.Exception.ExceptionRecord.ExceptionCode, + // ExceptionCaption(debug_event.u.Exception.ExceptionRecord.ExceptionCode), + // debug_event.u.Exception.ExceptionRecord.ExceptionAddress); + //MessageBoxEx(0, DebugMessage, "EXCEPTION", MB_ICONEXCLAMATION, NULL); break; default: + sprintf(DebugMessage,"Unknown eventcode=%x", debug_event.dwDebugEventCode); + MessageBoxEx(0, DebugMessage, "Injection", MB_ICONEXCLAMATION, NULL); break; } if(bContinueDebugging){ - ContinueDebugEvent(debug_event.dwProcessId, - debug_event.dwThreadId, - dwContinueStatus); + ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, dwContinueStatus); } else{ DebugSetProcessKillOnExit(FALSE); ContinueDebugEvent(debug_event.dwProcessId,debug_event.dwThreadId, DBG_CONTINUE); DebugActiveProcessStop(debug_event.dwProcessId); - if (pinfo.hProcess) CloseHandle(pinfo.hProcess); - if (pinfo.hThread) CloseHandle(pinfo.hThread); } } + CloseHandle(pinfo.hThread); // no longer needed, avoid handle leakage + CloseHandle(pinfo.hProcess); // no longer needed, avoid handle leakage return TRUE; } @@ -1896,12 +1865,14 @@ void CDxwndhostView::OnRun() if(TargetMaps[i].flags2 & STARTDEBUG){ ThreadInfo.TM=&TargetMaps[i]; ThreadInfo.PM=&TitleMaps[i]; - CreateThread( NULL, 0, StartDebug, &ThreadInfo, 0, NULL); + CloseHandle(CreateThread( NULL, 0, StartDebug, &ThreadInfo, 0, NULL)); } else{ CreateProcess(NULL, (strlen(TitleMaps[i].launchpath)>0) ? TitleMaps[i].launchpath: TargetMaps[i].path, 0, 0, false, CREATE_DEFAULT_ERROR_MODE, NULL, path, &sinfo, &pinfo); + CloseHandle(pinfo.hProcess); // no longer needed, avoid handle leakage + CloseHandle(pinfo.hThread); // no longer needed, avoid handle leakage } } diff --git a/host/resource b/host/resource index f9e4c1b11f6f2d90dbd83c4c4d9855bcd578f08d..d44c87c90113fb8c0b2b0c80b0c8aa04953f2ee7 100644 GIT binary patch delta 41 xcmaF#pK)IU(}qVelRxmWOwJ2qV-H~nWe8$$o&4HCm)VHHX!1iQ>BWy?lmTDf4>14$ delta 13 Ucmdnj!1U-p