-
Notifications
You must be signed in to change notification settings - Fork 171
Description
Visual Basic 3 applications support DDE ( https://docs.microsoft.com/en-us/windows/win32/dataxchg/about-dynamic-data-exchange ) by setting properties on Form. Running under NTVDM this communication works fine, but the same applications fail to work under winevdm, DdeConnect on the client is failing.
DdeConnect should successfully connect to the "Dde Server" and data transferring should work.
Example files attached
- Logon.exe (DDE Server)
- Test.exe (DDE Client)
A username / password is typed in Logon.exe text box, then in Test.exe when selecting button to Get Logon receive error No foreign application responded to a DDE initiate.
Screenshots
When working correctly when you hit "Get Logon" it will display the relevant txt from logon.exe:
Environment (please complete the following information):
- Windows 11 build 21H2 and Windows 10 1903
Created a simple Win32 C++ test Dde Client and Server, with my Win32 DdeServer the VB3 exe is connecting to it OK running under winevdm, However my client could not connect to the VB3 dde server. Here is a DDE server example that the VB3 client was connecting to OK:
#define _WIN32_WINNT 0x0501
#include <iostream>
#include <Windows.h>
HDDEDATA CALLBACK DdeCallback(
UINT uType, // transaction type
UINT uFmt, // clipboard data format
HCONV hconv, // handle to conversation
HSZ hsz1, // handle to string
HSZ hsz2, // handle to string
HDDEDATA hdata, // handle to global memory object
DWORD dwData1, // transaction-specific data
DWORD dwData2) // transaction-specific data
{
switch (uType)
{
case XTYP_REGISTER:
std::cout << "DDE Callback XTYP_REGISTER" << std::endl;
return (HDDEDATA)NULL;
case XTYP_UNREGISTER:
std::cout << "DDE Callback XTYP_UNREGISTER" << std::endl;
return (HDDEDATA)NULL;
case XTYP_ADVDATA:
std::cout << "DDE Callback XTYP_ADVDATA" << std::endl;
return (HDDEDATA)DDE_FACK;
case XTYP_XACT_COMPLETE:
std::cout << "DDE Callback XTYP_XACT_COMPLETE" << std::endl;
return (HDDEDATA)NULL;
case XTYP_CONNECT:
std::cout << "DDE Callback XTYP_CONNECT" << std::endl;
return (HDDEDATA)DDE_FACK;
case XTYP_DISCONNECT:
std::cout << "DDE Callback XTYP_DISCONNECT" << std::endl;
return (HDDEDATA)NULL;
default:
return (HDDEDATA)NULL;
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
case WM_DESTROY:
case WM_QUERYENDSESSION:
default:
{
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
}
return(0L);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
AllocConsole();
FILE* new_stdout;
freopen_s(&new_stdout, "CONOUT$", "w", stdout);
DWORD pidInst = 0;
UINT uResult = 0;
uResult = DdeInitializeA(
&pidInst,
DdeCallback,
APPCMD_FILTERINITS |
CBF_FAIL_SELFCONNECTIONS |
CBF_SKIP_REGISTRATIONS |
CBF_SKIP_UNREGISTRATIONS,
0); // reserved
HSZ ddeService = DdeCreateStringHandleA(pidInst, "LOGON", CP_WINANSI);
DdeNameService(pidInst, ddeService, 0, DNS_REGISTER);
DdeFreeStringHandle(pidInst, ddeService);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
Trace files:
It looks like NTVDM, where the DDE feature works on 32-bit operating systems uses a lower level method of directly sending DDE messages instead of using the DDEML library, at least from my initial investigation.