Module: wine Branch: master Commit: f28824eb58fed990f177bb4a9796f779154fea8f URL: https://gitlab.winehq.org/wine/wine/-/commit/f28824eb58fed990f177bb4a9796f77...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Aug 22 15:37:39 2022 +0200
user32: Support resource ID strings in CREATESTRUCT Unicode conversion.
---
dlls/user32/hook.c | 38 +++++++++++++++++++++++++++++++------- dlls/user32/tests/msg.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ dlls/user32/win.c | 20 ++++++++++++++++---- dlls/user32/winproc.c | 17 +++++++++++++++-- 4 files changed, 109 insertions(+), 13 deletions(-)
diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index 4201e2375ae..4a905eb8e5e 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -222,6 +222,7 @@ static LRESULT call_hook_AtoW( HOOKPROC proc, INT id, INT code, WPARAM wparam, L CREATESTRUCTW csW; LPWSTR nameW = NULL; LPWSTR classW = NULL; + WCHAR name_buf[3];
cbtcwW.lpcs = &csW; cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter; @@ -229,8 +230,18 @@ static LRESULT call_hook_AtoW( HOOKPROC proc, INT id, INT code, WPARAM wparam, L
if (!IS_INTRESOURCE(cbtcwA->lpcs->lpszName)) { - RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszName); - csW.lpszName = nameW = usBuffer.Buffer; + if (cbtcwA->lpcs->lpszName[0] != '\xff') + { + RtlCreateUnicodeStringFromAsciiz( &usBuffer, cbtcwA->lpcs->lpszName ); + csW.lpszName = nameW = usBuffer.Buffer; + } + else + { + name_buf[0] = 0xffff; + name_buf[1] = MAKEWORD( cbtcwA->lpcs->lpszName[1], cbtcwA->lpcs->lpszName[2] ); + name_buf[2] = 0; + csW.lpszName = name_buf; + } } if (!IS_INTRESOURCE(cbtcwA->lpcs->lpszClass)) { @@ -263,16 +274,29 @@ static LRESULT call_hook_WtoA( HOOKPROC proc, INT id, INT code, WPARAM wparam, L int len; LPSTR nameA = NULL; LPSTR classA = NULL; + char name_buf[4];
cbtcwA.lpcs = &csA; cbtcwA.hwndInsertAfter = cbtcwW->hwndInsertAfter; csA = *(CREATESTRUCTA *)cbtcwW->lpcs;
- if (!IS_INTRESOURCE(cbtcwW->lpcs->lpszName)) { - len = WideCharToMultiByte( CP_ACP, 0, cbtcwW->lpcs->lpszName, -1, NULL, 0, NULL, NULL ); - nameA = HeapAlloc( GetProcessHeap(), 0, len*sizeof(CHAR) ); - WideCharToMultiByte( CP_ACP, 0, cbtcwW->lpcs->lpszName, -1, nameA, len, NULL, NULL ); - csA.lpszName = nameA; + if (!IS_INTRESOURCE(cbtcwW->lpcs->lpszName)) + { + if (cbtcwW->lpcs->lpszName[0] != 0xffff) + { + len = WideCharToMultiByte( CP_ACP, 0, cbtcwW->lpcs->lpszName, -1, NULL, 0, NULL, NULL ); + nameA = HeapAlloc( GetProcessHeap(), 0, len*sizeof(CHAR) ); + WideCharToMultiByte( CP_ACP, 0, cbtcwW->lpcs->lpszName, -1, nameA, len, NULL, NULL ); + csA.lpszName = nameA; + } + else + { + name_buf[0] = '\xff'; + name_buf[1] = cbtcwW->lpcs->lpszName[1]; + name_buf[2] = cbtcwW->lpcs->lpszName[1] >> 8; + name_buf[3] = 0; + csA.lpszName = name_buf; + } }
if (!IS_INTRESOURCE(cbtcwW->lpcs->lpszClass)) { diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 2d43c1ad1aa..9c77bdc7c09 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -18990,6 +18990,52 @@ static void test_button_style(void) } }
+static LRESULT WINAPI test_create_name_procW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + switch (msg) + { + case WM_NCCREATE: + case WM_CREATE: + { + CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam; + memcpy( cs->lpCreateParams, cs->lpszName, 3 * sizeof(WCHAR) ); + break; + } + case WM_SETTEXT: + trace("%s\n", debugstr_w((const WCHAR *)lparam)); + break; + } + + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} + +static void test_create_name(void) +{ + WNDCLASSW clsW = { 0 }; + WCHAR name_buf[3]; + HWND hwnd; + + clsW.lpfnWndProc = test_create_name_procW; + clsW.lpszClassName = L"TestCreateNameClassW"; + RegisterClassW( &clsW ); + + hwnd = CreateWindowExW( 0, L"TestCreateNameClassW", L"\xffff\x6162", + WS_POPUP, 0,0,0,0,0,0,0, name_buf ); + ok( hwnd != NULL, "CreateWindowEx failed: %lu\n", GetLastError() ); + ok(!memcmp(name_buf, L"\xffff\x6162", 2 * sizeof(WCHAR)), + "name param = %s\n", debugstr_wn(name_buf, 2)); + DestroyWindow( hwnd ); + + hwnd = CreateWindowExA( 0, "TestCreateNameClassW", "\xff\0\x61\x60", + WS_POPUP, 0,0,0,0,0,0,0, name_buf ); + ok( hwnd != NULL, "CreateWindowEx failed: %lu\n", GetLastError() ); + ok(!memcmp(name_buf, L"\xffff\x6100", 2 * sizeof(WCHAR)), + "name param = %s\n", debugstr_wn(name_buf, 2)); + DestroyWindow( hwnd ); + + UnregisterClassW( L"TestCreateNameClassW", NULL ); +} + START_TEST(msg) { char **test_argv; @@ -19105,6 +19151,7 @@ START_TEST(msg) test_TrackPopupMenu(); test_TrackPopupMenuEmpty(); test_DoubleSetCapture(); + test_create_name(); /* keep it the last test, under Windows it tends to break the tests * which rely on active/foreground windows being correct. */ diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 9507486754b..7d873155c3b 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -304,6 +304,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, HWND hwnd, top_child = 0; MDICREATESTRUCTW mdi_cs; WNDCLASSEXW info; + WCHAR name_buf[8]; HMENU menu;
if (!get_class_info( module, className, &info, &class, FALSE )) return FALSE; @@ -398,10 +399,21 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, } }
- if (unicode || !cs->lpszName) - RtlInitUnicodeString( &window_name, cs->lpszName ); - else if (!RtlCreateUnicodeStringFromAsciiz( &window_name, (const char *)cs->lpszName )) - return 0; + if (!unicode && cs->lpszName) + { + const char *nameA = (const char *)cs->lpszName; + /* resource ID string is a special case */ + if (nameA[0] == '\xff') + { + name_buf[0] = 0xffff; + name_buf[1] = MAKEWORD( nameA[1], nameA[2] ); + name_buf[2] = 0; + RtlInitUnicodeString( &window_name, name_buf ); + } + else if (!RtlCreateUnicodeStringFromAsciiz( &window_name, (const char *)cs->lpszName )) + return 0; + } + else RtlInitUnicodeString( &window_name, cs->lpszName );
menu = cs->hMenu; if (!menu && info.lpszMenuName && (cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD) diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index 7e2be5b1be0..deae1a061f8 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -475,6 +475,7 @@ static LRESULT WINPROC_CallProcWtoA( winproc_callback_t callback, HWND hwnd, UIN CREATESTRUCTA csA = *(CREATESTRUCTA *)csW; MDICREATESTRUCTA mdi_cs; DWORD name_lenA = 0, name_lenW = 0, class_lenA = 0, class_lenW = 0; + char int_name_buf[4];
if (!IS_INTRESOURCE(csW->lpszClass)) { @@ -483,8 +484,20 @@ static LRESULT WINPROC_CallProcWtoA( winproc_callback_t callback, HWND hwnd, UIN } if (!IS_INTRESOURCE(csW->lpszName)) { - name_lenW = (lstrlenW(csW->lpszName) + 1) * sizeof(WCHAR); - RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW); + /* resource ID string is a special case */ + if (csW->lpszName[0] == 0xffff) + { + int_name_buf[0] = 0xff; + int_name_buf[1] = csW->lpszName[1]; + int_name_buf[2] = csW->lpszName[1] >> 8; + int_name_buf[3] = 0; + csA.lpszName = int_name_buf; + } + else + { + name_lenW = (lstrlenW(csW->lpszName) + 1) * sizeof(WCHAR); + RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW); + } }
if (!(cls = get_buffer( buffer, sizeof(buffer), class_lenA + name_lenA ))) break;