[PATCH v6 0/2] MR10869: atl: Implement registering ATL window messages.
The [documentation](https://source.winehq.org/WineAPI/AtlAxWinInit.html) for `AtlAxWinInit` states that it initialises ATL's control hosting code by registering window classes "_and some messages_". MSDN's documentation phrases this as "_plus a couple of custom window messages_", but Wine's implementation didn't register any custom window messages. Logging calls to `RegisterWindowMessage` showed that Visual Studio 2005, when going into Options -\> Projects and Solutions -\> VC++ Directories, calls this function to get the message IDs for custom messages name `WM_ATLGETCONTROL` and `WM_ATLGETHOST`. I've then registered those same messages in `AtlAxWinInit` and logged when they were called in `AtlAxWin_wndproc`. Since they were called with 0 for both `wParam` and `lParam`, the only sensible implementation would be routing the calls through `AtlAxGetControl` and `AtlAxGetHost` and returning the `IUnknown` pointer from the window procedure. This minor change now makes the VC++ Directories control in Visual Studio 2005 work as expected (and probably other stuff too). In that, it fixes one of the problems listed on the [Visual Studio 2005 AppDb page](https://appdb.winehq.org/objectManager.php?sClass=version&iId=4494), specifically as described in the comment "Building" posted by Dave on 2021-08-01. -- v6: Added tests for proper handling of WM_ATLGETCONTROL and WM_ATLGETHOST. https://gitlab.winehq.org/wine/wine/-/merge_requests/10869
From: Steven Don <gitlab@shdon.com> The MSDN documentation for AtlAxWinInit states that it initialises ATL's control hosting code by registering window classes *plus a couple of custom window messages* Logging calls to `RegisterWindowMessage` showed that Visual Studio 2005, when going into Options -> Projects and Solutions -> VC++ Directories, calls this function to get the message IDs for custom messages name WM_ATLGETCONTROL and WM_ATLGETHOST. I've then registered those same messages in AtlAxWinInit and logged when they were called in `AtlAxWin_wndproc`. Since they were called with 0 for both `wParam` and `lParam`, the only sensible implementation would be routing the calls through `AtlAxGetControl` and `AtlAxGetHost` and returning the `IUnknown` pointer from the window procedure. This change now makes the VC++ Directories control in Visual Studio 2005 work as expected (and probably other stuff too). --- dlls/atl/atl_ax.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/dlls/atl/atl_ax.c b/dlls/atl/atl_ax.c index 4ff0a796d3b..3bf2ce662e4 100644 --- a/dlls/atl/atl_ax.c +++ b/dlls/atl/atl_ax.c @@ -55,6 +55,9 @@ typedef struct IOCS { BOOL fActive, fInPlace, fWindowless; } IOCS; +static UINT wmAtlGetHost = 0; +static UINT wmAtlGetControl = 0; + /********************************************************************** * AtlAxWin class window procedure */ @@ -71,6 +74,18 @@ static LRESULT CALLBACK AtlAxWin_wndproc( HWND hWnd, UINT wMsg, WPARAM wParam, L free( ptr ); return 0; } + if ( wMsg == wmAtlGetControl ) + { + IUnknown *control = NULL; + AtlAxGetControl( hWnd, &control ); + return (LRESULT)control; + } + if ( wMsg == wmAtlGetHost ) + { + IUnknown *host = NULL; + AtlAxGetHost( hWnd, &host ); + return (LRESULT)host; + } return DefWindowProcW( hWnd, wMsg, wParam, lParam ); } @@ -132,6 +147,11 @@ BOOL WINAPI AtlAxWinInit(void) return FALSE; } + if (!wmAtlGetControl) + wmAtlGetControl = RegisterWindowMessageW( L"WM_ATLGETCONTROL" ); + if (!wmAtlGetHost) + wmAtlGetHost = RegisterWindowMessageW( L"WM_ATLGETHOST" ); + return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10869
From: Steven Don <gitlab@shdon.com> --- dlls/atl/tests/atl_ax.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/dlls/atl/tests/atl_ax.c b/dlls/atl/tests/atl_ax.c index 26e4ea5a54d..61bf5f62ee9 100644 --- a/dlls/atl/tests/atl_ax.c +++ b/dlls/atl/tests/atl_ax.c @@ -128,6 +128,47 @@ static void test_ax_win(void) ok(wcex.style == CS_GLOBALCLASS, "wcex.style %08x\n", wcex.style); } +static void test_atl_messages(void) +{ + UINT wmAtlGetHost = 0; + UINT wmAtlGetControl = 0; + HWND hwnd; + HRESULT ret; + IUnknown *host1 = NULL; + IUnknown *ctrl1 = NULL; + IUnknown *host2 = NULL; + IUnknown *ctrl2 = NULL; + + /* Already called by test_ax_win, but left in to allow this test to be standalone */ + AtlAxWinInit(); + + wmAtlGetHost = RegisterWindowMessageW( L"WM_ATLGETHOST" ); + wmAtlGetControl = RegisterWindowMessageW( L"WM_ATLGETCONTROL" ); + + hwnd = CreateWindowExW(0, L"AtlAxWin", L"Shell.Explorer", 0, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, NULL, NULL, NULL, NULL); + ok(hwnd != NULL, "Failed to create AtlAxWin window\n"); + + ret = AtlAxGetHost(hwnd, &host1); + ok(ret == S_OK, "AtlAxGetHost failed\n"); + ok(host1 != NULL, "AtlAxGetHost did not fill the out pointer\n"); + + ret = AtlAxGetControl(hwnd, &ctrl1); + ok(ret == S_OK, "AtlAxGetControl failed\n"); + ok(ctrl1 != NULL, "AtlAxGetControl did not fill the out pointer\n"); + + host2 = (IUnknown *)SendMessageW(hwnd, wmAtlGetHost, 0, 0); + ok(host2 != NULL, "WM_ATLGETHOST did not return a value\n"); + ctrl2 = (IUnknown *)SendMessageW(hwnd, wmAtlGetControl, 0, 0); + ok(ctrl2 != NULL, "WM_ATLGETCONTROL did not return a value\n"); + + ok(host1 == host2, "Mismatch between AtlAxGetHost and WM_ATLGETHOST\n"); + ok(ctrl1 == ctrl2, "Mismatch between AtlAxGetControl and WM_ATLGETCONTROL\n"); + + DestroyWindow(hwnd); +} + START_TEST(atl_ax) { init_function_pointers(); @@ -143,6 +184,7 @@ START_TEST(atl_ax) win_skip("AtlAxAttachControl is not available\n"); test_ax_win(); + test_atl_messages(); CoUninitialize(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10869
On Wed Jun 10 13:29:38 2026 +0000, Alexandre Julliard wrote:
Could you please add some tests? Commit 1bdf9e59 adds a test for this to `dlls/atl/tests/atl_ax.c` . Is that the kind of test you were looking for?
I've verified that this new test succeeds on real Windows, and in my development branch with the proposed patch, and that it fails on the official Wine master branch that lacks the patch from this MR. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10869#note_142633
On Wed Jun 10 13:29:38 2026 +0000, Steven Don wrote:
Commit 1bdf9e59 adds a test for this to `dlls/atl/tests/atl_ax.c` . Is that the kind of test you were looking for? I've verified that this new test succeeds on real Windows, and in my development branch with the proposed patch, and that it fails on the official Wine master branch that lacks the patch from this MR. Yes, that looks good, thanks. Please rebase your branch to get rid of the merge commit.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10869#note_142636
participants (3)
-
Alexandre Julliard (@julliard) -
Steven Don -
Steven Don (@shdon)