diff --git a/Include/dxwnd.h b/Include/dxwnd.h
index db28c81..d079f95 100644
--- a/Include/dxwnd.h
+++ b/Include/dxwnd.h
@@ -195,6 +195,8 @@
#define ACTIVATEAPP 0x00000800 // sends WM_ACTIVATEAPP message after every WM_WINPOSCHANGED message
#define NOSYSMEMPRIMARY 0x00001000 // forces suppression of DDSCAPS_SYSTEMMEMORY capability on emulated primary surface
#define NOSYSMEMBACKBUF 0x00002000 // forces suppression of DDSCAPS_SYSTEMMEMORY capability on emulated backbuffer surface
+#define CONFIRMONCLOSE 0x00004000 // on close button, ask the user before closing the window / terminating the program
+#define TERMINATEONCLOSE 0x00008000 // on WM_CLOSE message, also terminates the program
// logging Tflags DWORD:
#define OUTTRACE 0x00000001 // enables tracing to dxwnd.log in general
diff --git a/build/dxwnd.dll b/build/dxwnd.dll
index 252a75e..9a39756 100644
--- a/build/dxwnd.dll
+++ b/build/dxwnd.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:549536858a03ba659d55078a89d987c435aed391c5444cfe6421f23cf4c76cc6
-size 578048
+oid sha256:801f4eac2532d06296db4f257f4b14b6d58d6e6729a7df14a5c73407cbfbb3a5
+size 578560
diff --git a/build/dxwnd.exe b/build/dxwnd.exe
index 7eaa09e..620b79a 100644
--- a/build/dxwnd.exe
+++ b/build/dxwnd.exe
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ec489528e5cb8f0bdcdd15b49650a55d6367c38520bc1724834cebef642c9d73
+oid sha256:298792319c4f1da616431a5ac3e9cbd4ae54c82335a70f27affa029e8f0b3183
size 541696
diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt
index 7abdb11..510bec6 100644
--- a/build/readme-relnotes.txt
+++ b/build/readme-relnotes.txt
@@ -861,3 +861,9 @@ fix: revised the DDSCAPS_SYSTEMMEMORY suppression, now separated for primary & b
v2.03.31:
fix: handling of "No SYSTEMMEMORY on BackBuffer" flag for no-emulation mode: necessary to run "Microsoft Motocross Madness 2" in this mode.
fix: allowing hot patching to GetCursorPos() user32.dll call. This allows correct mouse control with obfuscated exes, like the chinese RPG "Paladin 3".
+
+v2.03.32:
+add: flags "Ask confirmation on window close" and "Terminate on window close"
+fix: implemented surface stack cleanup on overflow: this should allow "European Air War" to run through several seasons.
+debug: added a few diagnostic messages to trap possible errors in DLL injection functions
+fix: recovered the menu Edit->Add command that went disabled
diff --git a/dll/Inject.cpp b/dll/Inject.cpp
index d15cb0f..a15bb83 100644
--- a/dll/Inject.cpp
+++ b/dll/Inject.cpp
@@ -22,18 +22,31 @@ BOOL Inject(DWORD pID, const char * DLL_NAME)
if(!pID) return false;
//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)
- {
+ if(!hProc){
sprintf(buf, "OpenProcess() failed: pid=%x err=%d", pID, GetLastError());
MessageBox(NULL, buf, "Loader", MB_OK);
return false;
}
hLib=GetModuleHandle("kernel32.dll");
+ if(!hLib){
+ sprintf(buf, "GetModuleHandle(\"kernel32.dll\") failed: err=%d", pID, GetLastError());
+ MessageBox(NULL, buf, "Loader", MB_OK);
+ return false;
+ }
LoadLibAddy = (LPVOID)GetProcAddress(hLib, "LoadLibraryA");
+ if(!LoadLibAddy){
+ sprintf(buf, "GetProcAddress(\"LoadLibraryA\") failed: err=%d", pID, GetLastError());
+ MessageBox(NULL, buf, "Loader", MB_OK);
+ return false;
+ }
// 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);
+ if(!WriteProcessMemory(hProc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL)){
+ sprintf(buf, "WriteProcessMemory() failed: err=%d", pID, GetLastError());
+ MessageBox(NULL, buf, "Loader", MB_OK);
+ return false;
+ }
// Load the DLL
hThread=CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, 0, NULL);
// Free/Release/Close everything
diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp
index 3fe7131..dae3f23 100644
--- a/dll/dxhook.cpp
+++ b/dll/dxhook.cpp
@@ -1060,20 +1060,17 @@ LRESULT CALLBACK extWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
if (dxw.dwFlags1 & CLIPCURSOR) dxw.EraseClipCursor();
if (dxw.dwFlags1 & ENABLECLIPPING) (*pClipCursor)(NULL);
break;
- case WM_QUIT:
- case WM_DESTROY:
case WM_CLOSE:
- if(dxw.dwFlags6 & HIDETASKBAR){
- extern void gShowHideTaskBar(BOOL);
- gShowHideTaskBar(FALSE);
- }
+ // Beware: closing main window does not always mean that the program is about to terminate!!!
+ extern void gShowHideTaskBar(BOOL);
+ if(dxw.dwFlags6 & CONFIRMONCLOSE){
+ OutTraceDW("WindowProc: WM_CLOSE - terminating process?\n");
+ if (MessageBoxA(NULL, "Do you really want to exit the game?", "DxWnd", MB_YESNO | MB_TASKMODAL) != IDYES) return FALSE;
+ }
+ if(dxw.dwFlags6 & HIDETASKBAR) gShowHideTaskBar(FALSE);
+ if(dxw.dwFlags3 & FORCE16BPP) RecoverScreenMode();
+ if(dxw.dwFlags6 & TERMINATEONCLOSE) TerminateProcess(GetCurrentProcess(),0);
break;
- // commented out: WM_CLOSE just issue a request to close the window, not the process! It should be WM_QUIT....
- //case WM_CLOSE:
- // OutTraceDW("WindowProc: WM_CLOSE - terminating process\n");
- // if(dxw.dwFlags3 & FORCE16BPP) RecoverScreenMode();
- // TerminateProcess(GetCurrentProcess(),0);
- // break;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if(!(dxw.dwFlags4 & ENABLEHOTKEYS)) break;
diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp
index 3a6005b..9e50140 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.31"
+#define VERSION "2.03.32"
#define DDTHREADLOCK 1
//#define LOCKTHREADS
diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo
index 1846877..bea27dc 100644
Binary files a/dll/dxwnd.vs2008.suo and b/dll/dxwnd.vs2008.suo differ
diff --git a/dll/dxwsstack.cpp b/dll/dxwsstack.cpp
index a80c44b..0788680 100644
--- a/dll/dxwsstack.cpp
+++ b/dll/dxwsstack.cpp
@@ -9,6 +9,7 @@
#include "dxwcore.hpp"
//#define DXW_SURFACE_STACK_TRACING
+//#define OutTraceSDB OutTrace
dxwSStack::dxwSStack()
{
@@ -126,8 +127,10 @@ void dxwSStack::PushSurface(LPDIRECTDRAWSURFACE ps, USHORT role, USHORT version)
if ((e->lpdds==ps) || (e->lpdds==(DWORD)0)) break; // got matching entry or end of the list
}
if(i == DDSQLEN) {
- MessageBox(0, "Surface stack is full", "DxWnd SurfaceList", MB_OK | MB_ICONEXCLAMATION);
- return;
+ //MessageBox(0, "Surface stack is full", "DxWnd SurfaceList", MB_OK | MB_ICONEXCLAMATION);
+ //return;
+ for(int j=0;jlpdds=ps;
e->uRole = role;
diff --git a/host/TabProgram.cpp b/host/TabProgram.cpp
index bb883ed..dfb27f1 100644
--- a/host/TabProgram.cpp
+++ b/host/TabProgram.cpp
@@ -37,14 +37,14 @@ void CTabProgram::DoDataExchange(CDataExchange* pDX)
DDX_Check(pDX, IDC_WINDOWIZE, cTarget->m_Windowize);
DDX_Check(pDX, IDC_HOTPATCH, cTarget->m_HotPatch);
DDX_Check(pDX, IDC_HOOKDLLS, cTarget->m_HookDLLs);
+ DDX_Check(pDX, IDC_CONFIRMONCLOSE, cTarget->m_ConfirmOnClose);
+ DDX_Check(pDX, IDC_TERMINATEONCLOSE, cTarget->m_TerminateOnClose);
DDX_Check(pDX, IDC_FULLSCREENONLY, cTarget->m_FullScreenOnly);
DDX_Check(pDX, IDC_HOOKCHILDWIN, cTarget->m_HookChildWin);
DDX_Check(pDX, IDC_HOOKENABLED, cTarget->m_HookEnabled);
DDX_Check(pDX, IDC_STARTDEBUG, cTarget->m_StartDebug);
- DDX_Check(pDX, IDC_CLIENTREMAPPING, cTarget->m_ClientRemapping);
DDX_Check(pDX, IDC_SAVELOAD, cTarget->m_SaveLoad);
DDX_Check(pDX, IDC_KEEPASPECTRATIO, cTarget->m_KeepAspectRatio);
- DDX_Check(pDX, IDC_HOOKOPENGL, cTarget->m_HookOpenGL); // duplicated
DDX_Check(pDX, IDC_NOBANNER, cTarget->m_NoBanner);
DDX_Text(pDX, IDC_POSX, cTarget->m_PosX);
DDX_Text(pDX, IDC_POSY, cTarget->m_PosY);
diff --git a/host/TabSysLibs.cpp b/host/TabSysLibs.cpp
index e41fa2e..0b658ba 100644
--- a/host/TabSysLibs.cpp
+++ b/host/TabSysLibs.cpp
@@ -28,10 +28,12 @@ void CTabSysLibs::DoDataExchange(CDataExchange* pDX)
CTargetDlg *cTarget = ((CTargetDlg *)(this->GetParent()->GetParent()));
// GDI
+ DDX_Check(pDX, IDC_CLIENTREMAPPING, cTarget->m_ClientRemapping);
DDX_Radio(pDX, IDC_GDINONE, cTarget->m_DCEmulationMode);
DDX_Check(pDX, IDC_FIXTEXTOUT, cTarget->m_FixTextOut);
// OpenGL
+ DDX_Check(pDX, IDC_HOOKOPENGL, cTarget->m_HookOpenGL); // duplicated
DDX_Check(pDX, IDC_FORCEHOOKOPENGL, cTarget->m_ForceHookOpenGL);
DDX_Text(pDX, IDC_OPENGLLIB, cTarget->m_OpenGLLib);
diff --git a/host/TargetDlg.cpp b/host/TargetDlg.cpp
index aae62de..00ce1d7 100644
--- a/host/TargetDlg.cpp
+++ b/host/TargetDlg.cpp
@@ -87,6 +87,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_HookEnabled = TRUE; // default true !!
m_EmulateRegistry = FALSE;
m_OverrideRegistry = FALSE;
diff --git a/host/TargetDlg.h b/host/TargetDlg.h
index 7265f25..43d4058 100644
--- a/host/TargetDlg.h
+++ b/host/TargetDlg.h
@@ -55,6 +55,8 @@ public:
BOOL m_Windowize;
BOOL m_HotPatch;
BOOL m_HookDLLs;
+ BOOL m_TerminateOnClose;
+ BOOL m_ConfirmOnClose;
BOOL m_EmulateRegistry;
BOOL m_OverrideRegistry;
BOOL m_Wow64Registry;
diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps
index 680e5fa..7790ac0 100644
Binary files a/host/dxwndhost.aps and b/host/dxwndhost.aps differ
diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc
index 1708027..6355d10 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 20d91db..e911037 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 3e1c5d9..e41c5e5 100644
--- a/host/dxwndhostView.cpp
+++ b/host/dxwndhostView.cpp
@@ -108,6 +108,7 @@ BEGIN_MESSAGE_MAP(CDxwndhostView, CListView)
ON_COMMAND(ID_TASKBAR_HIDE, OnTaskbarHide)
ON_COMMAND(ID_TASKBAR_SHOW, OnTaskbarShow)
ON_COMMAND(ID_MODIFY, OnModify)
+ ON_COMMAND(ID_ADD, OnAdd)
ON_COMMAND(ID_PEXPORT, OnExport)
ON_COMMAND(ID_PKILL, OnProcessKill)
ON_COMMAND(ID_FILE_IMPORT, OnImport)
@@ -174,6 +175,8 @@ static void SetTargetFromDlg(TARGETMAP *t, CTargetDlg *dlg)
if(dlg->m_UnNotify) t->flags |= UNNOTIFY;
if(dlg->m_Windowize) t->flags2 |= WINDOWIZE;
if(dlg->m_HookDLLs) t->flags3 |= HOOKDLLS;
+ if(dlg->m_TerminateOnClose) t->flags6 |= TERMINATEONCLOSE;
+ if(dlg->m_ConfirmOnClose) t->flags6 |= CONFIRMONCLOSE;
if(dlg->m_EmulateRegistry) t->flags3 |= EMULATEREGISTRY;
if(dlg->m_OverrideRegistry) t->flags4 |= OVERRIDEREGISTRY;
if(dlg->m_Wow64Registry) t->flags6 |= WOW64REGISTRY;
@@ -414,6 +417,8 @@ static void SetDlgFromTarget(TARGETMAP *t, CTargetDlg *dlg)
dlg->m_Windowize = t->flags2 & WINDOWIZE ? 1 : 0;
dlg->m_HotPatch = t->flags4 & HOTPATCH ? 1 : 0;
dlg->m_HookDLLs = t->flags3 & HOOKDLLS ? 1 : 0;
+ dlg->m_TerminateOnClose = t->flags6 & TERMINATEONCLOSE ? 1 : 0;
+ dlg->m_ConfirmOnClose = t->flags6 & CONFIRMONCLOSE ? 1 : 0;
dlg->m_EmulateRegistry = t->flags3 & EMULATEREGISTRY ? 1 : 0;
dlg->m_OverrideRegistry = t->flags4 & OVERRIDEREGISTRY ? 1 : 0;
dlg->m_Wow64Registry = t->flags6 & WOW64REGISTRY ? 1 : 0;
diff --git a/host/resource b/host/resource
index b7282e9..7dd19c1 100644
Binary files a/host/resource and b/host/resource differ
diff --git a/proxy/ddraw.suo b/proxy/ddraw.suo
index e8beaf6..1aeaba4 100644
Binary files a/proxy/ddraw.suo and b/proxy/ddraw.suo differ