KB5132061: DDEML server no longer receives XTYP_CONNECT when DDEMLMom is subclassed with SetWindowLongPtrA

Zhihong Chen 0 Reputation points
2026-11-13T07:28:56.49+00:00

After installing KB5132061 (Windows 11 25H2, OS build 26200.9974), our 32-bit DDEML server stopped accepting

DDE conversations. Uninstalling the KB fixes it.

We narrowed it down to one condition: the server's hidden DDEMLMom window is subclassed through the ANSI API.

That happens automatically in any MBCS (non-Unicode) MFC application that calls DdeInitialize after its first window

exists, because MFC's CBT hook subclasses new top-level windows and forwards messages with CallWindowProcA.

Is this a known issue in KB5132061, and is a fix planned?

Observed behavior with KB5132061

  • SetWindowLongPtrA(DDEMLMom, GWLP_WNDPROC, ...) returns an A/W handle (0xFFFFxxxx), as documented.
  • Our subclass procedure receives WM_DDE_INITIATE and forwards it with CallWindowProcA(previousProc, ...). The call returns 0, but the DDEML callback never receives XTYP_CONNECT.
  • The client's DdeConnect fails with DMLERR_NO_CONV_ESTABLISHED. No other error is reported.
  • With SetWindowLongPtrW / CallWindowProcW the same server works on the same machine.
  • On build 26200.9711 (without KB5132061), both variants work.

| | With KB5132061 (26200.9974) | Without KB5132061 (26200.9711) |

| server A (SetWindowLongPtrA + CallWindowProcA) | FAILED | CONNECTED |

| server W (SetWindowLongPtrW + CallWindowProcW) | CONNECTED | CONNECTED |

Server and client run as the same user, in the same session, at the same integrity level.

Minimal repro (about 80 lines, plain Win32, no MFC)

Build as 32-bit from a "x86 Native Tools Command Prompt for VS 2022":


cl /nologo /W3 DdeMinRepro.cpp user32.lib

Console 1: DdeMinRepro server A

Console 2: DdeMinRepro client

Then repeat with DdeMinRepro server W.

   
// DdeMinRepro.cpp - build (x86, MBCS): cl /nologo /W3 DdeMinRepro.cpp user32.lib
//   DdeMinRepro server A   subclass DDEMLMom with SetWindowLongPtrA / CallWindowProcA
//   DdeMinRepro server W   subclass DDEMLMom with SetWindowLongPtrW / CallWindowProcW
//   DdeMinRepro client     DdeConnect to service "MinRepro", topic "System"
#include <windows.h>
#include <ddeml.h>
#include <stdio.h>
#include <string.h>
static WNDPROC g_old;
static BOOL g_w;
static HDDEDATA CALLBACK Callback(UINT type, UINT, HCONV, HSZ, HSZ, HDDEDATA, ULONG_PTR, ULONG_PTR)
{
	if (type == XTYP_CONNECT) {
		printf("  XTYP_CONNECT received\n");
		return (HDDEDATA)TRUE;
	}
	return NULL;
}
static LRESULT CALLBACK SubProc(HWND h, UINT m, WPARAM wp, LPARAM lp)
{
	if (m == WM_DDE_INITIATE)
		printf("WM_DDE_INITIATE -> CallWindowProc%c(%p)\n", g_w ? 'W' : 'A', g_old);
	return g_w ? CallWindowProcW(g_old, h, m, wp, lp) : CallWindowProcA(g_old, h, m, wp, lp);
}
static BOOL CALLBACK FindMom(HWND h, LPARAM lp)
{
	char cls[32];
	if (GetClassNameA(h, cls, sizeof(cls)) && strcmp(cls, "DDEMLMom") == 0) {
		*(HWND *)lp = h;
		return FALSE;
	}
	return TRUE;
}
int main(int argc, char **argv)
{
	DWORD inst = 0;
	setvbuf(stdout, NULL, _IONBF, 0);
	if (argc >= 3 && strcmp(argv[1], "server") == 0) {
		g_w = (argv[2][0] == 'W' || argv[2][0] == 'w');
		if (DdeInitializeA(&inst, Callback, APPCLASS_STANDARD | CBF_SKIP_ALLNOTIFICATIONS, 0) != DMLERR_NO_ERROR)
			return printf("DdeInitialize failed\n"), 1;
		HWND mom = NULL;
		EnumThreadWindows(GetCurrentThreadId(), FindMom, (LPARAM)&mom);
		if (!mom)
			return printf("DDEMLMom not found\n"), 1;
		g_old = g_w ? (WNDPROC)SetWindowLongPtrW(mom, GWLP_WNDPROC, (LONG_PTR)SubProc)
		            : (WNDPROC)SetWindowLongPtrA(mom, GWLP_WNDPROC, (LONG_PTR)SubProc);
		printf("DDEMLMom %p subclassed with SetWindowLongPtr%c, previous proc %p\n", mom, g_w ? 'W' : 'A', g_old);
		HSZ svc = DdeCreateStringHandleA(inst, "MinRepro", CP_WINANSI);
		DdeNameService(inst, svc, NULL, DNS_REGISTER);
		printf("Service \"MinRepro\" registered. Run \"DdeMinRepro client\" in another console.\n");
		MSG msg;
		while (GetMessage(&msg, NULL, 0, 0) > 0)
			DispatchMessage(&msg);
		return 0;
	}
	if (argc >= 2 && strcmp(argv[1], "client") == 0) {
		DdeInitializeA(&inst, Callback, APPCMD_CLIENTONLY, 0);
		HSZ svc = DdeCreateStringHandleA(inst, "MinRepro", CP_WINANSI);
		HSZ top = DdeCreateStringHandleA(inst, "System", CP_WINANSI);
		HCONV conv = DdeConnect(inst, svc, top, NULL);
		UINT err = DdeGetLastError(inst);
		printf(conv ? "CONNECTED\n" : "FAILED, DdeGetLastError = 0x%04X\n", err);
		if (conv)
			DdeDisconnect(conv);
		DdeUninitialize(inst);
		return conv ? 0 : 1;
	}
	printf("usage: DdeMinRepro server A | server W | client\n");
	return 2;
}


Output with KB5132061

server Aclient: FAILED, DdeGetLastError = 0x400A (DMLERR_NO_CONV_ESTABLISHED)

server Wclient: CONNECTED

Output without KB5132061 (26200.9711)

server A:


DDEMLMom 002C0972 subclassed with SetWindowLongPtrA, previous proc FFFF0C97

Service "MinRepro" registered. Run "DdeMinRepro client" in another console.

WM_DDE_INITIATE -> CallWindowProcA(FFFF0C97)

  XTYP_CONNECT received

Client: CONNECTED

Workaround we use

Right after DdeInitialize, put the class window procedure back on the DDEML windows of the thread:

SetWindowLongPtrW(hwnd, GWLP_WNDPROC, GetClassLongPtrW(hwnd, GCLP_WNDPROC)).

If the new behavior is intentional, what is the supported way for an ANSI application to subclass a window

of a Unicode class and still forward WM_DDE_INITIATE?

Windows for home | Windows 11 | Windows update
0 comments No comments

1 answer

Sort by: Most helpful
  1. AI answer

    2026-11-13T07:30:12.6633333+00:00

    There is no publicly documented DDEML regression or planned correction for KB5132061; because the documented Win32 contract explicitly supports SetWindowLongPtrA plus CallWindowProcA when subclassing a Unicode-class window, this behavior should be reported to Microsoft as an apparent compatibility regression rather than treated as an intentional API change.

    Documented status

    KB5132061 applies to Windows 11 25H2 build 26200.9974, but its published fixes and known issues do not mention DDEMLMom, DDE, SetWindowLongPtrA, CallWindowProcA, or missing XTYP_CONNECT callbacks.^1^ The public release-health material likewise contains no matching DDEML issue.^2^

    Consequently, the public information cannot confirm either:

    • that Microsoft has formally acknowledged this as a known issue; or
    • that a fix has been scheduled for a particular update.

    Your A/B results strongly isolate a build-dependent A/W forwarding change, but only Microsoft can confirm whether it is a servicing regression and provide a fix commitment.

    Supported subclassing behavior

    The documented ANSI path is already the path used by your application:

    1. Install the subclass with SetWindowLongPtrA.
    2. Preserve the returned previous procedure, including when it is a special internal value.
    3. Forward unprocessed messages through CallWindowProcA; do not invoke the returned value directly.

    Microsoft specifically documents that when an ANSI subclass forwards to a procedure created from a Unicode class, the system translates the message into Unicode during CallWindowProc processing.^3^ CallWindowProcA also documents that the previous-procedure value can be a special internal value meaningful only to CallWindowProc, and that the function performs Unicode-to-ANSI conversion.^4^

    Therefore, there is no separately documented “new” ANSI forwarding method for WM_DDE_INITIATE. An A/W thunk such as 0xFFFFxxxx must continue to be passed unchanged to CallWindowProcA.

    Practical mitigation

    Since your tested W/W variant works on 26200.9974, the least invasive application mitigation is to exclude DDEMLMom from the MFC ANSI subclassing path or subclass that window explicitly through the Unicode APIs:

    static WNDPROC g_prev;
    
    LRESULT CALLBACK DdeMomSubclass(
        HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
    {
        // Observe or handle messages here.
        return CallWindowProcW(g_prev, hwnd, msg, wp, lp);
    }
    
    void SubclassDdeMom(HWND hwnd)
    {
        g_prev = reinterpret_cast<WNDPROC>(
            SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
                             reinterpret_cast<LONG_PTR>(DdeMomSubclass)));
    }
    

    The WNDPROC signature itself does not contain character strings, so an MBCS build can call the explicit W APIs. Keep the A and W operations paired—SetWindowLongPtrW with CallWindowProcW—and restore the saved previous procedure when removing the subclass. Windows requires intercepted messages to be passed through CallWindowProc, and subclass chains must be removed in reverse order.^5^

    Your current class-procedure restoration workaround bypasses the failing subclass, but it can also discard other instance subclasses in the chain. Prefer preventing MFC from subclassing DDEMLMom, or removing only your own subclass using its saved previous procedure, rather than replacing GWLP_WNDPROC with GCLP_WNDPROC.

    Also keep DdeInitializeA versus DdeInitializeW deliberate: Microsoft documents that the selected variant determines whether DDEML uses ANSI or Unicode window procedures to control conversations.^6^ Changing that call is therefore broader than changing only the subclass API and should receive full interoperability testing.

    Escalation needed for acknowledgement and scheduling

    Submit the minimal x86 reproducer through Feedback Hub → Report a problem on build 26200.9974:

    1. Include both build numbers and the four-cell A/W result matrix.
    2. Attach the complete source and compiler command.
    3. Select Recreate my problem, start recording, and reproduce server A followed by server W.
    4. Include the returned previous-procedure value and DdeGetLastError result.
    5. Save a local copy of diagnostics and submit.

    Feedback Hub supports attached files and diagnostic recordings of the reproduction.^7^ If a formal acknowledgement or servicing timeline is required, open a Microsoft Support case and provide the Feedback Hub link plus the same reproducer; Feedback Hub reports product defects, while Support is the channel for direct assistance and case tracking.


    References

    1. [Windows 11, versions 25H2 and 26H2](https://support.microsoft.com/servicing/os/windows-11/2026/11/kb5132061-windows-11-24h2-25h2-26h2-security-update)
    2. Windows 11, version 26H2 known issues and notifications
    3. Subclassing and Automatic Message Translation
    4. CallWindowProcA function (winuser.h)
    5. About Window Procedures
    6. DdeInitializeW function (ddeml.h)
    7. Send feedback to Microsoft with the Feedback Hub app | Microsoft Support
    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

    1 person found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.