From b3122fc5091be12c66650687bda80f07e7206d2e Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Mon, 29 Nov 2021 18:40:09 -0800
Subject: [PATCH] Add support for NTVDMx64

Yes, you can run 16-bit DOS doors on 64-bit (x64) Windows now.

Install NTVDMx64 (http://www.columbia.edu/~em36/ntvdmx64.html, it's not as onerous as it sounds) and re-enable DOS program support in SBBS (i.e. make sure "NO_DOS" is not in your sbbs.ini [bbs] Options value) and voila: DOS doors work.

This change adds an empty init routine to sbbsexec.dll since older versions of NTVDM (which NTVDMx64 is based on) required one. Also, the sbbsexec.dll should be located in your Synchronet "exec" directory when using NTVDMx64 (in addition to or instead of your Windows/System32 directory).
---
 src/sbbs3/dosxtrn/dosxtrn.c | 22 ++++++++++++++--------
 src/sbbs3/sbbsexec.c        | 11 +++++++++--
 src/sbbs3/xtrn.cpp          |  6 ++++--
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/src/sbbs3/dosxtrn/dosxtrn.c b/src/sbbs3/dosxtrn/dosxtrn.c
index ecf73c9bd7..df162b0ae1 100644
--- a/src/sbbs3/dosxtrn/dosxtrn.c
+++ b/src/sbbs3/dosxtrn/dosxtrn.c
@@ -509,6 +509,7 @@ int main(int argc, char **argv)
 	int		i,c,d,envnum=0;
 	FILE*	fp;
 	BOOL	NT=FALSE;
+	BOOL	x64=FALSE;
 	BOOL	success=FALSE;
 	WORD	buf_seg;
 	WORD	w;
@@ -519,7 +520,7 @@ int main(int argc, char **argv)
 			,"%s - Copyright %s Rob Swindell\n"
 			,id_string, __DATE__+7);
 		fprintf(stderr
-			,"usage: dosxtrn <path/dosxtrn.env> [NT|95] [node_num] [mode]\n");
+			,"usage: dosxtrn <path/dosxtrn.env> [NT|95|x64] [node_num] [mode]\n");
 		return(1);
 	}
 
@@ -529,8 +530,12 @@ int main(int argc, char **argv)
 	sprintf(dll,"%s%s",exec_dir,VDD_FILENAME);
 	DllName=dll;
 
-	if(argc>2 && !strcmp(argv[2],"NT")) 
-		NT=TRUE;
+	if(argc>2) {
+		if(strcmp(argv[2],"NT") == 0)
+			NT=TRUE;
+		else if(strcmp(argv[2],"x64") == 0)
+			NT=TRUE, x64=TRUE;
+	}
 	if(argc>3)
 		node_num=atoi(argv[3]);
 	if(argc>4)
@@ -588,12 +593,13 @@ int main(int argc, char **argv)
 				mov     si, DllName		; ds:si = dll name
 				mov     di, InitFunc    ; es:di = init routine
 				mov     bx, DispFunc    ; ds:bx = dispatch routine
-#if 1	/* Vista work-around, apparently doesn't support an InitFunc (RegisterModule fails with AX=1) */
-				xor		di,di
-				mov		es,di
-#endif
-
 			};
+			if(!x64) {	// NTVDMx64 (based on an older Windows NTVDM) requires an init routine
+				_asm {	/* Vista work-around, apparently doesn't support an InitFunc (RegisterModule fails with AX=1) */
+					xor		di,di
+					mov		es,di
+				};
+			}
 			RegisterModule();
 			_asm {
 				mov		vdd, ax
diff --git a/src/sbbs3/sbbsexec.c b/src/sbbs3/sbbsexec.c
index 7579d2f935..e16046587e 100644
--- a/src/sbbs3/sbbsexec.c
+++ b/src/sbbs3/sbbsexec.c
@@ -674,10 +674,11 @@ __declspec(dllexport) void __cdecl VDDDispatch(void)
 				status->outbuf_full=0;
 				status->outbuf_size=DEFAULT_MAX_MSG_SIZE;
 			} else
-				lprintf(LOG_DEBUG,"VDD_STATUS: MailSlot maxmsgsize=%u, nextmsgsize=%u, msgs=%u"
+				lprintf(LOG_DEBUG,"VDD_STATUS: MailSlot output: maxmsgsize=%u, nextmsgsize=%d, msgs=%u, input: %u"
 					,status->outbuf_size
 					,status->outbuf_full
-					,msgs);
+					,msgs
+					,status->inbuf_full);
 			if(status->outbuf_full==MAILSLOT_NO_MESSAGE)
 				status->outbuf_full=0;
 			status->outbuf_full*=msgs;
@@ -803,3 +804,9 @@ __declspec(dllexport) void __cdecl VDDDispatch(void)
 	}
 	setAX((WORD)retval);
 }
+
+__declspec(dllexport) BOOL __cdecl VDDInitialize(IN PVOID hVDD, IN ULONG Reason,	 
+IN PCONTEXT Context OPTIONAL)	 
+{	 
+	return TRUE;	 
+}
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index ae7deb7e61..00e196ff84 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -487,8 +487,10 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 				if(mode&EX_STDOUT)
         			i|=SBBSEXEC_MODE_DOS_OUT;
 			}
-			sprintf(str," NT %u %u"
-				,cfg.node_num,i);
+			BOOL x64 = FALSE;
+			IsWow64Process(GetCurrentProcess(), &x64);
+			sprintf(str," %s %u %u"
+				,x64 ? "x64" : "NT", cfg.node_num,i);
 			strcat(fullcmdline,str);
 
 			sprintf(str,"sbbsexec_hungup%d",cfg.node_num);
-- 
GitLab