From acffd663c11c2fa7f597b30182038a41b8a6ad5c Mon Sep 17 00:00:00 2001 From: Kamil Hornicek Date: Fri, 28 Nov 2008 12:02:57 +0000 Subject: [PATCH] - update user32 winetest svn path=/trunk/; revision=37702 --- rostests/winetests/user32/broadcast.c | 76 +- rostests/winetests/user32/class.c | 7 +- rostests/winetests/user32/combo.c | 98 ++ rostests/winetests/user32/cursoricon.c | 238 ++++- rostests/winetests/user32/dde.c | 595 +++++++++-- rostests/winetests/user32/dialog.c | 15 +- rostests/winetests/user32/edit.c | 86 +- rostests/winetests/user32/input.c | 220 +++- rostests/winetests/user32/listbox.c | 151 +-- rostests/winetests/user32/menu.c | 75 +- rostests/winetests/user32/monitor.c | 208 +++- rostests/winetests/user32/msg.c | 1335 ++++++++++++++++++++---- rostests/winetests/user32/resource.c | 68 +- rostests/winetests/user32/resource.rc | 7 +- rostests/winetests/user32/scroll.c | 72 +- rostests/winetests/user32/static.c | 12 +- rostests/winetests/user32/sysparams.c | 123 ++- rostests/winetests/user32/text.c | 454 +++++++- rostests/winetests/user32/win.c | 969 ++++++++++++++--- rostests/winetests/user32/winstation.c | 10 +- 20 files changed, 4033 insertions(+), 786 deletions(-) diff --git a/rostests/winetests/user32/broadcast.c b/rostests/winetests/user32/broadcast.c index 786df7d698a..ae9cd29ee65 100644 --- a/rostests/winetests/user32/broadcast.c +++ b/rostests/winetests/user32/broadcast.c @@ -108,14 +108,14 @@ static void test_parameters(PBROADCAST broadcast, const char *functionname) skip("%s is not implemented\n", functionname); return; } - ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); - ok(!ret, "Returned: %d\n", ret); + ok(!ret || broken(ret), "Returned: %d\n", ret); + if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); SetLastError(0xcafebabe); recips = BSM_APPLICATIONS; ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 ); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); - ok(!ret, "Returned: %d\n", ret); + ok(!ret || broken(ret), "Returned: %d\n", ret); + if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); #if 0 /* TODO: Check the hang flags */ SetLastError(0xcafebabe); @@ -150,23 +150,29 @@ static void test_parameters(PBROADCAST broadcast, const char *functionname) ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); PulseEvent(hevent); + SetLastError( 0xdeadbeef ); recips = BSM_APPLICATIONS; ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 ); - ok(ret==1, "Returned: %d\n", ret); - ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); - PulseEvent(hevent); - - recips = BSM_APPLICATIONS; - ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); - ok(ret==1, "Returned: %d\n", ret); - ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); - PulseEvent(hevent); - - recips = BSM_APPLICATIONS; - ret = broadcast( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); - ok(!ret, "Returned: %d\n", ret); - ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); - PulseEvent(hevent); + if (ret) + { + ok(ret==1, "Returned: %d\n", ret); + ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); + PulseEvent(hevent); + + recips = BSM_APPLICATIONS; + ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); + ok(ret==1, "Returned: %d\n", ret); + ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); + PulseEvent(hevent); + + recips = BSM_APPLICATIONS; + ret = broadcast( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); + ok(!ret, "Returned: %d\n", ret); + ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); + PulseEvent(hevent); + } + else /* BSF_SENDNOTIFYMESSAGE not supported on NT4 */ + ok( GetLastError() == ERROR_INVALID_PARAMETER, "failed with err %u\n", GetLastError() ); recips = BSM_APPLICATIONS; ret = broadcast( 0, &recips, WM_NULL, 100, 0 ); @@ -264,6 +270,9 @@ static void test_noprivileges(void) DWORD recips; BOOL ret; + static const DWORD BSM_ALL_RECIPS = BSM_VXDS | BSM_NETDRIVER | + BSM_INSTALLABLEDRIVERS | BSM_APPLICATIONS; + pOpenProcessToken = (void *)GetProcAddress(advapi32, "OpenProcessToken"); pAdjustTokenPrivileges = (void *)GetProcAddress(advapi32, "AdjustTokenPrivileges"); if (!pOpenProcessToken || !pAdjustTokenPrivileges || !pOpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) @@ -282,41 +291,44 @@ static void test_noprivileges(void) recips = BSM_ALLDESKTOPS; ResetEvent(hevent); ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); - todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError()); - ok(ret==1, "Returned: %d\n", ret); + ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); - ok(recips == BSM_ALLDESKTOPS, "Received by: %08x\n", recips); + ok(recips == BSM_ALLDESKTOPS || + recips == BSM_ALL_RECIPS, /* win2k3 */ + "Received by: %08x\n", recips); PulseEvent(hevent); - /* Wine sets last error to 0, so just use that one as token here so it doesn't fail */ - SetLastError(0); + SetLastError(0xcafebabe); recips = BSM_ALLCOMPONENTS; ResetEvent(hevent); ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); - ok(!GetLastError(), "Last error: %08x\n", GetLastError()); - ok(ret==1, "Returned: %d\n", ret); + ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); - ok(recips == BSM_ALLCOMPONENTS, "Received by: %08x\n", recips); + ok(recips == BSM_ALLCOMPONENTS || + recips == BSM_ALL_RECIPS, /* win2k3 */ + "Received by: %08x\n", recips); PulseEvent(hevent); SetLastError(0xcafebabe); recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS; ResetEvent(hevent); ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); - todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError()); - ok(ret==1, "Returned: %d\n", ret); + ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); - ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS), "Received by: %08x\n", recips); + ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) || + recips == BSM_APPLICATIONS, /* win2k3 */ + "Received by: %08x\n", recips); PulseEvent(hevent); SetLastError(0xcafebabe); recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS; ResetEvent(hevent); ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); - todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError()); ok(!ret, "Returned: %d\n", ret); ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); - ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS), "Received by: %08x\n", recips); + ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) || + recips == BSM_APPLICATIONS, /* win2k3 */ + "Received by: %08x\n", recips); PulseEvent(hevent); } diff --git a/rostests/winetests/user32/class.c b/rostests/winetests/user32/class.c index 486e227be1a..ce6d020533a 100755 --- a/rostests/winetests/user32/class.c +++ b/rostests/winetests/user32/class.c @@ -570,13 +570,14 @@ static void test_instances(void) static void test_builtinproc(void) { - /* Edit behaves differently. ScrollBar have currently only a Unicode winproc */ + /* Edit behaves differently */ static const CHAR NORMAL_CLASSES[][10] = { "Button", "Static", "ComboBox", "ComboLBox", "ListBox", + "ScrollBar", "#32770", /* dialog */ }; static const int NUM_NORMAL_CLASSES = (sizeof(NORMAL_CLASSES)/sizeof(NORMAL_CLASSES[0])); @@ -796,7 +797,7 @@ static BOOL RegisterTestDialog(HINSTANCE hInstance) wcx.hInstance = hInstance; wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcx.hCursor = LoadCursor(NULL, IDC_ARROW); - wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wcx.hbrBackground = GetStockObject(WHITE_BRUSH); wcx.lpszClassName = "TestDialog"; wcx.lpszMenuName = "TestDialog"; wcx.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(5), @@ -813,7 +814,7 @@ static BOOL RegisterTestDialog(HINSTANCE hInstance) /* test registering a dialog box created by using the CLASS directive in a resource file, then test creating the dialog using CreateDialogParam. */ -static void WINAPI CreateDialogParamTest(HINSTANCE hInstance) +static void CreateDialogParamTest(HINSTANCE hInstance) { HWND hWndMain; diff --git a/rostests/winetests/user32/combo.c b/rostests/winetests/user32/combo.c index 34d8c7ab304..51660072a59 100644 --- a/rostests/winetests/user32/combo.c +++ b/rostests/winetests/user32/combo.c @@ -265,6 +265,103 @@ static void test_CBN_SELCHANGE(void) test_selection(CBS_DROPDOWNLIST, text, sel_2, sel_2); } +static void test_WM_LBUTTONDOWN(void) +{ + HWND hCombo, hEdit, hList; + COMBOBOXINFO cbInfo; + UINT x, y, item_height; + LRESULT result; + int i, idx; + RECT rect; + CHAR buffer[3]; + static const UINT choices[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72}; + static const CHAR stringFormat[] = "%2d"; + BOOL ret; + BOOL (WINAPI *pGetComboBoxInfo)(HWND, PCOMBOBOXINFO); + + pGetComboBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo"); + if (!pGetComboBoxInfo){ + win_skip("GetComboBoxInfo is not available\n"); + return; + } + + hCombo = CreateWindow("ComboBox", "Combo", WS_VISIBLE|WS_CHILD|CBS_DROPDOWN, + 0, 0, 200, 150, hMainWnd, (HMENU)COMBO_ID, NULL, 0); + + for (i = 0; i < sizeof(choices)/sizeof(UINT); i++){ + sprintf(buffer, stringFormat, choices[i]); + result = SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)buffer); + ok(result == i, + "Failed to add item %d\n", i); + } + + cbInfo.cbSize = sizeof(COMBOBOXINFO); + SetLastError(0xdeadbeef); + ret = pGetComboBoxInfo(hCombo, &cbInfo); + ok(ret, "Failed to get combobox info structure. LastError=%d\n", + GetLastError()); + hEdit = cbInfo.hwndItem; + hList = cbInfo.hwndList; + + trace("hMainWnd=%x, hCombo=%x, hList=%x, hEdit=%x\n", + (UINT)hMainWnd, (UINT)hCombo, (UINT)hList, (UINT)hEdit); + ok(GetFocus() == hMainWnd, "Focus not on Main Window, instead on %x\n", + (UINT)GetFocus()); + + /* Click on the button to drop down the list */ + x = cbInfo.rcButton.left + (cbInfo.rcButton.right-cbInfo.rcButton.left)/2; + y = cbInfo.rcButton.top + (cbInfo.rcButton.bottom-cbInfo.rcButton.top)/2; + result = SendMessage(hCombo, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y)); + ok(result, "WM_LBUTTONDOWN was not processed. LastError=%d\n", + GetLastError()); + ok(SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0), + "The dropdown list should have appeared after clicking the button.\n"); + + ok(GetFocus() == hEdit, + "Focus not on ComboBox's Edit Control, instead on %x\n", + (UINT)GetFocus()); + result = SendMessage(hCombo, WM_LBUTTONUP, 0, MAKELPARAM(x, y)); + ok(result, "WM_LBUTTONUP was not processed. LastError=%d\n", + GetLastError()); + ok(GetFocus() == hEdit, + "Focus not on ComboBox's Edit Control, instead on %x\n", + (UINT)GetFocus()); + + /* Click on the 5th item in the list */ + item_height = SendMessage(hCombo, CB_GETITEMHEIGHT, 0, 0); + ok(GetClientRect(hList, &rect), "Failed to get list's client rect.\n"); + x = rect.left + (rect.right-rect.left)/2; + y = item_height/2 + item_height*4; + result = SendMessage(hList, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y)); + ok(!result, "WM_LBUTTONDOWN was not processed. LastError=%d\n", + GetLastError()); + ok(GetFocus() == hEdit, + "Focus not on ComboBox's Edit Control, instead on %x\n", + (UINT)GetFocus()); + + result = SendMessage(hList, WM_MOUSEMOVE, 0, MAKELPARAM(x, y)); + ok(!result, "WM_MOUSEMOVE was not processed. LastError=%d\n", + GetLastError()); + ok(GetFocus() == hEdit, + "Focus not on ComboBox's Edit Control, instead on %x\n", + (UINT)GetFocus()); + ok(SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0), + "The dropdown list should still be visible.\n"); + + result = SendMessage(hList, WM_LBUTTONUP, 0, MAKELPARAM(x, y)); + ok(!result, "WM_LBUTTONUP was not processed. LastError=%d\n", + GetLastError()); + ok(GetFocus() == hEdit, + "Focus not on ComboBox's Edit Control, instead on %x\n", + (UINT)GetFocus()); + ok(!SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0), + "The dropdown list should have been rolled up.\n"); + idx = SendMessage(hCombo, CB_GETCURSEL, 0, 0); + ok(idx, "Current Selection: expected %d, got %d\n", 4, idx); + + DestroyWindow(hCombo); +} + START_TEST(combo) { hMainWnd = CreateWindow("static", "Test", WS_OVERLAPPEDWINDOW, 10, 10, 300, 300, NULL, NULL, NULL, 0); @@ -275,6 +372,7 @@ START_TEST(combo) test_setitemheight(CBS_DROPDOWN); test_setitemheight(CBS_DROPDOWNLIST); test_CBN_SELCHANGE(); + test_WM_LBUTTONDOWN(); DestroyWindow(hMainWnd); } diff --git a/rostests/winetests/user32/cursoricon.c b/rostests/winetests/user32/cursoricon.c index 40f3a1413f2..5d1cf2bde1e 100644 --- a/rostests/winetests/user32/cursoricon.c +++ b/rostests/winetests/user32/cursoricon.c @@ -76,11 +76,10 @@ static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARA SetLastError(0xdeadbeef); ret = DestroyCursor((HCURSOR) lParam); error = GetLastError(); - todo_wine { - ok(!ret, "DestroyCursor on the active cursor succeeded.\n"); - ok(error == ERROR_DESTROY_OBJECT_OF_OTHER_THREAD, + todo_wine ok(!ret || broken(ret) /* win9x */, "DestroyCursor on the active cursor succeeded.\n"); + ok(error == ERROR_DESTROY_OBJECT_OF_OTHER_THREAD || + error == 0xdeadbeef, /* vista */ "Last error: %u\n", error); - } return TRUE; case WM_DESTROY: PostQuitMessage(0); @@ -132,7 +131,7 @@ static void do_child(void) PostMessage(parent, PROC_INIT, (WPARAM) child, 0); /* Receive messages. */ - while ((ret = GetMessage(&msg, child, 0, 0))) + while ((ret = GetMessage(&msg, 0, 0, 0))) { ok(ret != -1, "GetMessage failed. Error: %u\n", GetLastError()); TranslateMessage(&msg); @@ -233,7 +232,7 @@ static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT BOOL orig_is_dib; BOOL copy_is_dib; - copy = (HBITMAP) CopyImage(bitmap, IMAGE_BITMAP, copyWidth, copyHeight, flags); + copy = CopyImage(bitmap, IMAGE_BITMAP, copyWidth, copyHeight, flags); ok(copy != NULL, "CopyImage() failed\n"); if (copy != NULL) { @@ -504,13 +503,14 @@ static void test_CreateIcon(void) static const BYTE bmp_bits[1024]; HICON hIcon; HBITMAP hbmMask, hbmColor; + BITMAPINFO *bmpinfo; ICONINFO info; HDC hdc; + void *bits; UINT display_bpp; hdc = GetDC(0); display_bpp = GetDeviceCaps(hdc, BITSPIXEL); - ReleaseDC(0, hdc); /* these crash under XP hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL); @@ -581,6 +581,78 @@ static void test_CreateIcon(void) DeleteObject(hbmMask); DeleteObject(hbmColor); + + /* test creating an icon from a DIB section */ + + bmpinfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(BITMAPINFO,bmiColors[256])); + bmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmpinfo->bmiHeader.biWidth = 32; + bmpinfo->bmiHeader.biHeight = 32; + bmpinfo->bmiHeader.biPlanes = 1; + bmpinfo->bmiHeader.biBitCount = 8; + bmpinfo->bmiHeader.biCompression = BI_RGB; + hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 ); + ok(hbmColor != NULL, "Expected a handle to the DIB\n"); + if (bits) + memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 ); + bmpinfo->bmiHeader.biBitCount = 1; + hbmMask = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 ); + ok(hbmMask != NULL, "Expected a handle to the DIB\n"); + if (bits) + memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 ); + + info.fIcon = TRUE; + info.xHotspot = 8; + info.yHotspot = 8; + info.hbmMask = hbmColor; + info.hbmColor = hbmMask; + SetLastError(0xdeadbeaf); + hIcon = CreateIconIndirect(&info); + ok(hIcon != 0, "CreateIconIndirect failed\n"); + test_icon_info(hIcon, 32, 32, 8); + DestroyIcon(hIcon); + DeleteObject(hbmColor); + + bmpinfo->bmiHeader.biBitCount = 16; + hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 ); + ok(hbmColor != NULL, "Expected a handle to the DIB\n"); + if (bits) + memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 ); + + info.fIcon = TRUE; + info.xHotspot = 8; + info.yHotspot = 8; + info.hbmMask = hbmColor; + info.hbmColor = hbmMask; + SetLastError(0xdeadbeaf); + hIcon = CreateIconIndirect(&info); + ok(hIcon != 0, "CreateIconIndirect failed\n"); + test_icon_info(hIcon, 32, 32, 8); + DestroyIcon(hIcon); + DeleteObject(hbmColor); + + bmpinfo->bmiHeader.biBitCount = 32; + hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 ); + ok(hbmColor != NULL, "Expected a handle to the DIB\n"); + if (bits) + memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 ); + + info.fIcon = TRUE; + info.xHotspot = 8; + info.yHotspot = 8; + info.hbmMask = hbmColor; + info.hbmColor = hbmMask; + SetLastError(0xdeadbeaf); + hIcon = CreateIconIndirect(&info); + ok(hIcon != 0, "CreateIconIndirect failed\n"); + test_icon_info(hIcon, 32, 32, 8); + DestroyIcon(hIcon); + + DeleteObject(hbmMask); + DeleteObject(hbmColor); + HeapFree( GetProcessHeap(), 0, bmpinfo ); + + ReleaseDC(0, hdc); } /* Shamelessly ripped from dlls/oleaut32/tests/olepicture.c */ @@ -664,7 +736,10 @@ static void test_LoadImageFile(const unsigned char * image_data, handle = LoadImageA(NULL, filename, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE); ok(handle == NULL, "LoadImage(%s) as IMAGE_CURSOR succeeded incorrectly.\n", ext); error = GetLastError(); - ok(error == 0, "Last error: %u\n", error); + ok(error == 0 || + broken(error == 0xdeadbeef) || /* Win9x */ + broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */ + "Last error: %u\n", error); if (handle != NULL) DestroyCursor(handle); /* Load as icon. For all tested formats, this should fail */ @@ -672,7 +747,10 @@ static void test_LoadImageFile(const unsigned char * image_data, handle = LoadImageA(NULL, filename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); ok(handle == NULL, "LoadImage(%s) as IMAGE_ICON succeeded incorrectly.\n", ext); error = GetLastError(); - ok(error == 0, "Last error: %u\n", error); + ok(error == 0 || + broken(error == 0xdeadbeef) || /* Win9x */ + broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */ + "Last error: %u\n", error); if (handle != NULL) DestroyIcon(handle); /* Load as bitmap. Should succeed if bmp, fail for everything else */ @@ -682,7 +760,9 @@ static void test_LoadImageFile(const unsigned char * image_data, ok(handle != NULL, "LoadImage(%s) as IMAGE_BITMAP failed.\n", ext); else ok(handle == NULL, "LoadImage(%s) as IMAGE_BITMAP succeeded incorrectly.\n", ext); error = GetLastError(); - ok(error == 0, "Last error: %u\n", error); + ok(error == 0 || + error == 0xdeadbeef, /* Win9x, WinMe */ + "Last error: %u\n", error); if (handle != NULL) DeleteObject(handle); DeleteFileA(filename); @@ -741,15 +821,16 @@ static void test_LoadImage(void) /* Test loading an icon as a cursor. */ SetLastError(0xdeadbeef); handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE); - todo_wine ok(handle != NULL, "LoadImage() failed.\n"); error = GetLastError(); - ok(error == 0, "Last error: %u\n", error); + ok(error == 0 || + broken(error == 0xdeadbeef) || /* Win9x */ + broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */ + "Last error: %u\n", error); /* Test the icon information. */ SetLastError(0xdeadbeef); ret = GetIconInfo(handle, &icon_info); - todo_wine ok(ret, "GetIconInfo() failed.\n"); error = GetLastError(); ok(error == 0xdeadbeef, "Last error: %u\n", error); @@ -766,7 +847,6 @@ static void test_LoadImage(void) /* Clean up. */ SetLastError(0xdeadbeef); ret = DestroyCursor(handle); - todo_wine ok(ret, "DestroyCursor() failed.\n"); error = GetLastError(); ok(error == 0xdeadbeef, "Last error: %u\n", error); @@ -781,6 +861,99 @@ static void test_LoadImage(void) test_LoadImageFile(pngimage, sizeof(pngimage), "png", 0); } +static void test_CreateIconFromResource(void) +{ + HANDLE handle; + BOOL ret; + DWORD error; + BITMAPINFOHEADER *icon_header; + INT16 *hotspot; + ICONINFO icon_info; + +#define ICON_RES_WIDTH 32 +#define ICON_RES_HEIGHT 32 +#define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8) +#define ICON_RES_BPP 32 +#define ICON_RES_SIZE \ + (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP) +#define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE) + + /* Set icon data. */ + hotspot = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, CRSR_RES_SIZE); + + /* Cursor resources have an extra hotspot, icon resources not. */ + hotspot[0] = 3; + hotspot[1] = 3; + + icon_header = (BITMAPINFOHEADER *) (hotspot + 2); + icon_header->biSize = sizeof(BITMAPINFOHEADER); + icon_header->biWidth = ICON_WIDTH; + icon_header->biHeight = ICON_HEIGHT*2; + icon_header->biPlanes = 1; + icon_header->biBitCount = ICON_BPP; + icon_header->biSizeImage = 0; /* Uncompressed bitmap. */ + + /* Test creating a cursor. */ + SetLastError(0xdeadbeef); + handle = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000); + ok(handle != NULL, "Create cursor failed.\n"); + + /* Test the icon information. */ + SetLastError(0xdeadbeef); + ret = GetIconInfo(handle, &icon_info); + ok(ret, "GetIconInfo() failed.\n"); + error = GetLastError(); + ok(error == 0xdeadbeef, "Last error: %u\n", error); + + if (ret) + { + ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n"); + ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot); + ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot); + ok(icon_info.hbmColor != NULL, "No hbmColor!\n"); + ok(icon_info.hbmMask != NULL, "No hbmMask!\n"); + } + + /* Clean up. */ + SetLastError(0xdeadbeef); + ret = DestroyCursor(handle); + ok(ret, "DestroyCursor() failed.\n"); + error = GetLastError(); + ok(error == 0xdeadbeef, "Last error: %u\n", error); + + /* Test creating an icon. */ + SetLastError(0xdeadbeef); + handle = CreateIconFromResource((PBYTE) icon_header, ICON_RES_SIZE, TRUE, + 0x00030000); + ok(handle != NULL, "Create icon failed.\n"); + + /* Test the icon information. */ + SetLastError(0xdeadbeef); + ret = GetIconInfo(handle, &icon_info); + ok(ret, "GetIconInfo() failed.\n"); + error = GetLastError(); + ok(error == 0xdeadbeef, "Last error: %u\n", error); + + if (ret) + { + ok(icon_info.fIcon == TRUE, "fIcon != TRUE.\n"); + /* Icons always have hotspot in the middle */ + ok(icon_info.xHotspot == ICON_WIDTH/2, "xHotspot is %u.\n", icon_info.xHotspot); + ok(icon_info.yHotspot == ICON_HEIGHT/2, "yHotspot is %u.\n", icon_info.yHotspot); + ok(icon_info.hbmColor != NULL, "No hbmColor!\n"); + ok(icon_info.hbmMask != NULL, "No hbmMask!\n"); + } + + /* Clean up. */ + SetLastError(0xdeadbeef); + ret = DestroyCursor(handle); + ok(ret, "DestroyCursor() failed.\n"); + error = GetLastError(); + ok(error == 0xdeadbeef, "Last error: %u\n", error); + + HeapFree(GetProcessHeap(), 0, hotspot); +} + static void test_DestroyCursor(void) { static const BYTE bmp_bits[4096]; @@ -810,24 +983,26 @@ static void test_DestroyCursor(void) SetLastError(0xdeadbeef); ret = DestroyCursor(cursor); - ok(!ret, "DestroyCursor on the active cursor succeeded\n"); + ok(!ret || broken(ret) /* succeeds on win9x */, "DestroyCursor on the active cursor succeeded\n"); error = GetLastError(); ok(error == 0xdeadbeef, "Last error: %u\n", error); - - cursor2 = GetCursor(); - ok(cursor2 == cursor, "Active was set to %p when trying to destroy it\n", cursor2); - - SetCursor(NULL); - - /* Trying to destroy the cursor properly fails now with - * ERROR_INVALID_CURSOR_HANDLE. This happens because we called - * DestroyCursor() 2+ times after calling SetCursor(). The calls to - * GetCursor() and SetCursor(NULL) in between make no difference. */ - ret = DestroyCursor(cursor); - todo_wine { - ok(!ret, "DestroyCursor succeeded.\n"); - error = GetLastError(); - ok(error == ERROR_INVALID_CURSOR_HANDLE, "Last error: 0x%08x\n", error); + if (!ret) + { + cursor2 = GetCursor(); + ok(cursor2 == cursor, "Active was set to %p when trying to destroy it\n", cursor2); + SetCursor(NULL); + + /* Trying to destroy the cursor properly fails now with + * ERROR_INVALID_CURSOR_HANDLE. This happens because we called + * DestroyCursor() 2+ times after calling SetCursor(). The calls to + * GetCursor() and SetCursor(NULL) in between make no difference. */ + ret = DestroyCursor(cursor); + todo_wine { + ok(!ret, "DestroyCursor succeeded.\n"); + error = GetLastError(); + ok(error == ERROR_INVALID_CURSOR_HANDLE || error == 0xdeadbeef, /* vista */ + "Last error: 0x%08x\n", error); + } } DeleteObject(cursorInfo.hbmMask); @@ -838,7 +1013,7 @@ static void test_DestroyCursor(void) SetLastError(0xdeadbeef); ret = DestroyCursor(cursor); - ok(ret, "DestroyCursor on the active cursor failed.\n"); + ok(ret || broken(!ret) /* fails on win9x */, "DestroyCursor on the active cursor failed.\n"); error = GetLastError(); ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error); @@ -885,6 +1060,7 @@ START_TEST(cursoricon) test_initial_cursor(); test_CreateIcon(); test_LoadImage(); + test_CreateIconFromResource(); test_DestroyCursor(); do_parent(); test_child_process(); diff --git a/rostests/winetests/user32/dde.c b/rostests/winetests/user32/dde.c index eb875e3dc45..a3b73a53e55 100755 --- a/rostests/winetests/user32/dde.c +++ b/rostests/winetests/user32/dde.c @@ -73,6 +73,12 @@ static void create_dde_window(HWND *hwnd, LPCSTR name, WNDPROC wndproc) assert(*hwnd); } +static void destroy_dde_window(HWND *hwnd, LPCSTR name) +{ + DestroyWindow(*hwnd); + UnregisterClass(name, GetModuleHandleA(0)); +} + static LRESULT WINAPI dde_server_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { UINT_PTR lo, hi; @@ -178,8 +184,10 @@ static LRESULT WINAPI dde_server_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPA ok(poke->cfFormat == CF_TEXT, "Expected CF_TEXT, got %d\n", poke->cfFormat); if (msg_index == 5) - ok(lstrcmpA((LPSTR)poke->Value, "poke data\r\n"), - "Expected 'poke data\\r\\n', got %s\n", poke->Value); + { + size = GlobalSize((HGLOBAL)lo); + ok(size == 4, "got %d\n", size); + } else ok(!lstrcmpA((LPSTR)poke->Value, "poke data\r\n"), "Expected 'poke data\\r\\n', got %s\n", poke->Value); @@ -227,20 +235,21 @@ static LRESULT WINAPI dde_server_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPA return DefWindowProcA(hwnd, msg, wparam, lparam); } -static void test_msg_server(HANDLE hproc) +static void test_msg_server(HANDLE hproc, HANDLE hthread) { MSG msg; HWND hwnd; DWORD res; create_dde_window(&hwnd, "dde_server", dde_server_wndproc); + ResumeThread( hthread ); while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0) { while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); } - DestroyWindow(hwnd); + destroy_dde_window(&hwnd, "dde_server"); GetExitCodeProcess( hproc, &res ); ok( !res, "client failed with %u error(s)\n", res ); } @@ -288,11 +297,8 @@ static void test_ddeml_client(void) DdeGetLastError(client_pid); hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); - ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); - todo_wine - { - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08x\n", res); - } + ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %08x\n", res); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -310,11 +316,9 @@ static void test_ddeml_client(void) DdeGetLastError(client_pid); hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); - todo_wine - { - ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); - ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret); - } + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); +todo_wine + ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -333,10 +337,7 @@ static void test_ddeml_client(void) hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); - todo_wine - { - ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); - } + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -438,10 +439,7 @@ static void test_ddeml_client(void) ret = DdeGetLastError(client_pid); ok(op == NULL, "Expected NULL, got %p\n", op); ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res); - todo_wine - { - ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret); - } + ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret); DdeFreeStringHandle(client_pid, topic); DdeFreeDataHandle(hdata); @@ -454,10 +452,7 @@ static void test_ddeml_client(void) hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); - todo_wine - { - ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); - } + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -662,7 +657,6 @@ static HDDEDATA CALLBACK server_ddeml_callback(UINT uType, UINT uFmt, HCONV hcon if (msg_index == 5) { - todo_wine { ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str); ok(size == 1, "Expected 1, got %d\n", size); @@ -698,16 +692,12 @@ static HDDEDATA CALLBACK server_ddeml_callback(UINT uType, UINT uFmt, HCONV hcon ptr = (LPSTR)DdeAccessData(hdata, &size); ok(!lstrcmpA(ptr, "poke data\r\n"), "Expected 'poke data\\r\\n', got %s\n", ptr); - todo_wine - { - ok(size == 14, "Expected 14, got %d\n", size); - } + ok(size == 12, "Expected 12, got %d\n", size); DdeUnaccessData(hdata); size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI); if (msg_index == 7) { - todo_wine { ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str); ok(size == 1, "Expected 1, got %d\n", size); @@ -980,7 +970,7 @@ static HGLOBAL create_poke() DDEPOKE *poke; DWORD size; - size = sizeof(DDEPOKE) + lstrlenA("poke data\r\n") + 1; + size = FIELD_OFFSET(DDEPOKE, Value[sizeof("poke data\r\n")]); hglobal = GlobalAlloc(GMEM_DDESHARE, size); ok(hglobal != 0, "Expected non-NULL hglobal\n"); @@ -1065,9 +1055,14 @@ static void test_msg_client() /* WM_DDE_POKE, no ddepoke */ lparam = PackDDElParam(WM_DDE_POKE, 0, item); - PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam); + /* win9x returns 0 here and crashes in PostMessageA */ + if (lparam) { + PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam); + flush_events(); + } + else + win_skip("no lparam for WM_DDE_POKE\n"); - flush_events(); /* WM_DDE_POKE, no item */ lparam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)hglobal, 0); @@ -1123,7 +1118,7 @@ static void test_msg_client() flush_events(); - DestroyWindow(client_hwnd); + destroy_dde_window(&client_hwnd, "dde_client"); } static LRESULT WINAPI hook_dde_client_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) @@ -1186,7 +1181,6 @@ static LRESULT WINAPI dde_server_wndprocW(HWND hwnd, UINT msg, WPARAM wparam, LP ack.fBusy = 0; cmd = GlobalLock((HGLOBAL)hi); - if (!cmd || (lstrcmpA(cmd, exec_cmdA) && lstrcmpW((LPCWSTR)cmd, exec_cmdW))) { trace("ignoring unknown WM_DDE_EXECUTE command\n"); @@ -1388,6 +1382,53 @@ todo_wine { DestroyWindow(hwnd_server); } +static void test_initialisation(void) +{ + UINT ret; + DWORD res; + HDDEDATA hdata; + HSZ server, topic, item; + DWORD client_pid; + HCONV conversation; + + /* Initialise without a valid server window. */ + client_pid = 0; + ret = DdeInitializeA(&client_pid, client_ddeml_callback, APPCMD_CLIENTONLY, 0); + ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); + + + server = DdeCreateStringHandleA(client_pid, "TestDDEService", CP_WINANSI); + topic = DdeCreateStringHandleA(client_pid, "TestDDETopic", CP_WINANSI); + + DdeGetLastError(client_pid); + + /* There is no server window so no conversation can be extracted */ + conversation = DdeConnect(client_pid, server, topic, NULL); + ok(conversation == NULL, "Expected NULL conversation, %p\n", conversation); + ret = DdeGetLastError(client_pid); + ok(ret == DMLERR_NO_CONV_ESTABLISHED, "Expected DMLERR_NO_CONV_ESTABLISHED, got %d\n", ret); + + DdeFreeStringHandle(client_pid, server); + + item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI); + + /* There is no converstation so an invalild parameter results */ + res = 0xdeadbeef; + DdeGetLastError(client_pid); + hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); + ret = DdeGetLastError(client_pid); +todo_wine + ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret); + ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %08x\n", res); + + DdeFreeStringHandle(client_pid, server); + ret = DdeDisconnect(conversation); + ok(ret == FALSE, "Expected FALSE, got %d\n", ret); + + ret = DdeUninitialize(client_pid); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); +} + static void test_DdeCreateStringHandleW(DWORD dde_inst, int codepage) { static const WCHAR dde_string[] = {'D','D','E',' ','S','t','r','i','n','g',0}; @@ -1486,15 +1527,9 @@ static void test_DdeCreateDataHandle(void) item = DdeCreateStringHandleA(dde_inst, "item", CP_WINANSI); ok(item != NULL, "Expected non-NULL hsz\n"); - /* invalid instance id */ - DdeGetLastError(dde_inst); - hdata = DdeCreateDataHandle(0xdeadbeef, (LPBYTE)"data", MAX_PATH, 0, item, CF_TEXT, 0); - err = DdeGetLastError(dde_inst); - todo_wine - { - ok(hdata == NULL, "Expected NULL, got %p\n", hdata); - ok(err == DMLERR_INVALIDPARAMETER, - "Expected DMLERR_INVALIDPARAMETER, got %d\n", err); + if (0) { + /* do not test with an invalid instance id: that crashes on win9x */ + hdata = DdeCreateDataHandle(0xdeadbeef, (LPBYTE)"data", MAX_PATH, 0, item, CF_TEXT, 0); } /* 0 instance id */ @@ -1666,7 +1701,7 @@ static void test_DdeCreateStringHandle(void) ret = DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0); if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { - trace("Skipping the DDE test on a Win9x platform\n"); + skip("DdeInitialize is unimplemented\n"); return; } @@ -1690,7 +1725,7 @@ static void test_FreeDDElParam(void) HGLOBAL val, hglobal; BOOL ret; - ret = FreeDDElParam(WM_DDE_INITIATE, (LPARAM)NULL); + ret = FreeDDElParam(WM_DDE_INITIATE, 0); ok(ret == TRUE, "Expected TRUE, got %d\n", ret); hglobal = GlobalAlloc(GMEM_DDESHARE, 100); @@ -1790,19 +1825,24 @@ static void test_PackDDElParam(void) ok(ret == TRUE, "Expected TRUE, got %d\n", ret); lparam = PackDDElParam(WM_DDE_ADVISE, 0xcafe, 0xbeef); - ptr = GlobalLock((HGLOBAL)lparam); - ok(ptr != NULL, "Expected non-NULL ptr\n"); - ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); - ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); + /* win9x returns 0 here */ + if (lparam) { + ptr = GlobalLock((HGLOBAL)lparam); + ok(ptr != NULL, "Expected non-NULL ptr\n"); + ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); + ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); - ret = GlobalUnlock((HGLOBAL)lparam); - ok(ret == 1, "Expected 1, got %d\n", ret); + ret = GlobalUnlock((HGLOBAL)lparam); + ok(ret == 1, "Expected 1, got %d\n", ret); - lo = hi = 0; - ret = UnpackDDElParam(WM_DDE_ADVISE, lparam, &lo, &hi); - ok(ret == TRUE, "Expected TRUE, got %d\n", ret); - ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); - ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); + lo = hi = 0; + ret = UnpackDDElParam(WM_DDE_ADVISE, lparam, &lo, &hi); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); + ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); + } + else + win_skip("no lparam for WM_DDE_ADVISE\n"); ret = FreeDDElParam(WM_DDE_ADVISE, lparam); ok(ret == TRUE, "Expected TRUE, got %d\n", ret); @@ -1829,42 +1869,52 @@ static void test_PackDDElParam(void) ok(ret == TRUE, "Expected TRUE, got %d\n", ret); lparam = PackDDElParam(WM_DDE_ACK, 0xcafe, 0xbeef); - ptr = GlobalLock((HGLOBAL)lparam); - ok(ptr != NULL, "Expected non-NULL ptr\n"); - ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); - ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); + /* win9x returns the input (0xbeef<<16 | 0xcafe) here */ + if (lparam != 0xbeefcafe) { + ptr = GlobalLock((HGLOBAL)lparam); + ok(ptr != NULL, "Expected non-NULL ptr\n"); + ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); + ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); - ret = GlobalUnlock((HGLOBAL)lparam); - ok(ret == 1, "Expected 1, got %d\n", ret); + ret = GlobalUnlock((HGLOBAL)lparam); + ok(ret == 1, "Expected 1, got %d\n", ret); - lo = hi = 0; - ret = UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi); - ok(ret == TRUE, "Expected TRUE, got %d\n", ret); - ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); - ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); + lo = hi = 0; + ret = UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); + ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); - ret = FreeDDElParam(WM_DDE_ACK, lparam); - ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ret = FreeDDElParam(WM_DDE_ACK, lparam); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); - hglobal = GlobalFree((HGLOBAL)lparam); - ok(hglobal == (HGLOBAL)lparam, "Expected lparam, got %d\n", ret); - ok(GetLastError() == ERROR_INVALID_HANDLE, - "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + hglobal = GlobalFree((HGLOBAL)lparam); + ok(hglobal == (HGLOBAL)lparam, "Expected lparam, got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_HANDLE, + "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + } + else + win_skip("got lparam 0x%lx for WM_DDE_ACK\n", lparam); lparam = PackDDElParam(WM_DDE_DATA, 0xcafe, 0xbeef); - ptr = GlobalLock((HGLOBAL)lparam); - ok(ptr != NULL, "Expected non-NULL ptr\n"); - ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); - ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); + /* win9x returns 0 here */ + if (lparam) { + ptr = GlobalLock((HGLOBAL)lparam); + ok(ptr != NULL, "Expected non-NULL ptr\n"); + ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); + ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); - ret = GlobalUnlock((HGLOBAL)lparam); - ok(ret == 1, "Expected 1, got %d\n", ret); + ret = GlobalUnlock((HGLOBAL)lparam); + ok(ret == 1, "Expected 1, got %d\n", ret); - lo = hi = 0; - ret = UnpackDDElParam(WM_DDE_DATA, lparam, &lo, &hi); - ok(ret == TRUE, "Expected TRUE, got %d\n", ret); - ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); - ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); + lo = hi = 0; + ret = UnpackDDElParam(WM_DDE_DATA, lparam, &lo, &hi); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); + ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); + } + else + win_skip("no lparam for WM_DDE_DATA\n"); ret = FreeDDElParam(WM_DDE_DATA, lparam); ok(ret == TRUE, "Expected TRUE, got %d\n", ret); @@ -1891,19 +1941,24 @@ static void test_PackDDElParam(void) ok(ret == TRUE, "Expected TRUE, got %d\n", ret); lparam = PackDDElParam(WM_DDE_POKE, 0xcafe, 0xbeef); - ptr = GlobalLock((HGLOBAL)lparam); - ok(ptr != NULL, "Expected non-NULL ptr\n"); - ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); - ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); + /* win9x returns 0 here */ + if (lparam) { + ptr = GlobalLock((HGLOBAL)lparam); + ok(ptr != NULL, "Expected non-NULL ptr\n"); + ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]); + ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]); - ret = GlobalUnlock((HGLOBAL)lparam); - ok(ret == 1, "Expected 1, got %d\n", ret); + ret = GlobalUnlock((HGLOBAL)lparam); + ok(ret == 1, "Expected 1, got %d\n", ret); - lo = hi = 0; - ret = UnpackDDElParam(WM_DDE_POKE, lparam, &lo, &hi); - ok(ret == TRUE, "Expected TRUE, got %d\n", ret); - ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); - ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); + lo = hi = 0; + ret = UnpackDDElParam(WM_DDE_POKE, lparam, &lo, &hi); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo); + ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi); + } + else + win_skip("no lparam for WM_DDE_POKE\n"); ret = FreeDDElParam(WM_DDE_POKE, lparam); ok(ret == TRUE, "Expected TRUE, got %d\n", ret); @@ -1939,7 +1994,7 @@ static void test_UnpackDDElParam(void) /* NULL lParam */ lo = 0xdead; hi = 0xbeef; - ret = UnpackDDElParam(WM_DDE_INITIATE, (LPARAM)NULL, &lo, &hi); + ret = UnpackDDElParam(WM_DDE_INITIATE, 0, &lo, &hi); ok(ret == TRUE, "Expected TRUE, got %d\n", ret); ok(lo == 0, "Expected 0, got %08lx\n", lo); ok(hi == 0, "Expected 0, got %08lx\n", hi); @@ -1976,17 +2031,25 @@ static void test_UnpackDDElParam(void) lo = 0xdead; hi = 0xbeef; - ret = UnpackDDElParam(WM_DDE_ADVISE, (LPARAM)NULL, &lo, &hi); + ret = UnpackDDElParam(WM_DDE_ADVISE, 0, &lo, &hi); ok(ret == FALSE, "Expected FALSE, got %d\n", ret); - ok(lo == 0, "Expected 0, got %08lx\n", lo); - ok(hi == 0, "Expected 0, got %08lx\n", hi); + ok(lo == 0 || + broken(lo == 0xdead), /* win2k */ + "Expected 0, got %08lx\n", lo); + ok(hi == 0 || + broken(hi == 0xbeef), /* win2k */ + "Expected 0, got %08lx\n", hi); lo = 0xdead; hi = 0xbeef; ret = UnpackDDElParam(WM_DDE_ADVISE, 0xcafebabe, &lo, &hi); ok(ret == FALSE, "Expected FALSE, got %d\n", ret); - ok(lo == 0, "Expected 0, got %08lx\n", lo); - ok(hi == 0, "Expected 0, got %08lx\n", hi); + ok(lo == 0 || + broken(lo == 0xdead), /* win2k */ + "Expected 0, got %08lx\n", lo); + ok(hi == 0 || + broken(hi == 0xbeef), /* win2k */ + "Expected 0, got %08lx\n", hi); hglobal = GlobalAlloc(GMEM_DDESHARE, 2); ptr = GlobalLock(hglobal); @@ -2012,8 +2075,12 @@ static void test_UnpackDDElParam(void) hi = 0xbeef; ret = UnpackDDElParam(WM_DDE_ACK, 0xcafebabe, &lo, &hi); ok(ret == FALSE, "Expected FALSE, got %d\n", ret); - ok(lo == 0, "Expected 0, got %08lx\n", lo); - ok(hi == 0, "Expected 0, got %08lx\n", hi); + ok(lo == 0 || + broken(lo == 0xdead), /* win2k */ + "Expected 0, got %08lx\n", lo); + ok(hi == 0 || + broken(hi == 0xbeef), /* win2k */ + "Expected 0, got %08lx\n", hi); lo = 0xdead; hi = 0xbeef; @@ -2026,8 +2093,12 @@ static void test_UnpackDDElParam(void) hi = 0xbeef; ret = UnpackDDElParam(WM_DDE_DATA, 0xcafebabe, &lo, &hi); ok(ret == FALSE, "Expected FALSE, got %d\n", ret); - ok(lo == 0, "Expected 0, got %08lx\n", lo); - ok(hi == 0, "Expected 0, got %08lx\n", hi); + ok(lo == 0 || + broken(lo == 0xdead), /* win2k */ + "Expected 0, got %08lx\n", lo); + ok(hi == 0 || + broken(hi == 0xbeef), /* win2k */ + "Expected 0, got %08lx\n", hi); lo = 0xdead; hi = 0xbeef; @@ -2047,8 +2118,12 @@ static void test_UnpackDDElParam(void) hi = 0xbeef; ret = UnpackDDElParam(WM_DDE_POKE, 0xcafebabe, &lo, &hi); ok(ret == FALSE, "Expected FALSE, got %d\n", ret); - ok(lo == 0, "Expected 0, got %08lx\n", lo); - ok(hi == 0, "Expected 0, got %08lx\n", hi); + ok(lo == 0 || + broken(lo == 0xdead), /* win2k */ + "Expected 0, got %08lx\n", lo); + ok(hi == 0 || + broken(hi == 0xbeef), /* win2k */ + "Expected 0, got %08lx\n", hi); lo = 0xdead; hi = 0xbeef; @@ -2065,6 +2140,270 @@ static void test_UnpackDDElParam(void) ok(hi == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", hi); } +static HDDEDATA CALLBACK server_end_to_end_callback(UINT uType, UINT uFmt, HCONV hconv, + HSZ hsz1, HSZ hsz2, HDDEDATA hdata, + ULONG_PTR dwData1, ULONG_PTR dwData2) +{ + DWORD size, rsize; + char str[MAX_PATH]; + static int msg_index = 0; + static HCONV conversation = 0; + static char test_cmd[] = "test dde command"; + static WCHAR test_cmd_w[] = {'t','e','s','t',' ','d','d','e',' ','c','o','m','m','a','n','d',0}; + static char test_service [] = "TestDDEService"; + static char test_topic [] = "TestDDETopic"; + + msg_index++; + + switch (uType) + { + case XTYP_REGISTER: + { + ok(msg_index == 1 || msg_index == 7 || msg_index == 13 || msg_index == 19, + "Expected 1, 7, 13 or 19, got %d\n", msg_index); + return (HDDEDATA)TRUE; + } + + case XTYP_CONNECT: + { + ok(msg_index == 2 || msg_index == 8 || msg_index == 14 || msg_index == 20, + "Expected 2, 8, 14 or 20, got %d\n", msg_index); + ok(uFmt == 0, "Expected 0, got %d, msg_index=%d\n", uFmt, msg_index); + ok(hconv == 0, "Expected 0, got %p, msg_index=%d\n", hconv, msg_index); + ok(hdata == 0, "Expected 0, got %p, msg_index=%d\n", hdata, msg_index); + ok(dwData1 != 0, "Expected not 0, got %08lx, msg_index=%d\n", dwData1, msg_index); + ok(dwData2 == FALSE, "Expected FALSE, got %08lx, msg_index=%d\n", dwData2, msg_index); + + size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI); + ok(!lstrcmpA(str, test_topic), "Expected %s, got %s, msg_index=%d\n", + test_topic, str, msg_index); + ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index); + + size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI); + ok(!lstrcmpA(str, test_service), "Expected %s, got %s, msg_index=%d\n", + test_service, str, msg_index); + ok(size == 14, "Expected 14, got %d, msg_index=%d\n", size, msg_index); + + return (HDDEDATA) TRUE; + } + case XTYP_CONNECT_CONFIRM: + { + ok(msg_index == 3 || msg_index == 9 || msg_index == 15 || msg_index == 21, + "Expected 3, 9, 15 or 21 got %d\n", msg_index); + conversation = hconv; + return (HDDEDATA) TRUE; + } + case XTYP_EXECUTE: + { + BYTE *buffer = NULL; + + ok(msg_index == 4 || msg_index == 5 || msg_index == 10 || msg_index == 11 || + msg_index == 16 || msg_index == 17 || msg_index == 22 || msg_index == 23, + "Expected 4, 5, 10, 11, 16, 17, 22 or 23, got %d\n", msg_index); + ok(uFmt == 0, "Expected 0, got %d\n", uFmt); + ok(hconv == conversation, "Expected conversation handle, got %p, msg_index=%d\n", + hconv, msg_index); + ok(dwData1 == 0, "Expected 0, got %08lx, msg_index=%d\n", dwData1, msg_index); + ok(dwData2 == 0, "Expected 0, got %08lx, msg_index=%d\n", dwData2, msg_index); + ok(hsz2 == 0, "Expected 0, got %p, msg_index=%d\n", hsz2, msg_index); + size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI); + ok(!lstrcmpA(str, test_topic), "Expected %s, got %s, msg_index=%d\n", + test_topic, str, msg_index); + ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index); + ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index); + + size = DdeGetData(hdata, NULL, 0, 0); + if (msg_index == 10 || msg_index ==11 || msg_index == 16 || msg_index ==17) + if (msg_index == 10 || msg_index == 16) + todo_wine + ok(size == 34, "Expected that size should be 34 not %d, msg_index=%d\n", + size, msg_index); + else + ok(size == 34, "Expected that size should be 34 not %d, msg_index=%d\n", + size, msg_index); + else + if (msg_index ==22) + todo_wine + ok(size == 9, "Expected that size should be 9 not %d, msg_index=%d\n", + size, msg_index); + else + if (msg_index == 5) + todo_wine + ok(size == 17, "Expected that size should be 17 not %d, msg_index=%d\n", + size, msg_index); + else + ok(size == 17, "Expected that size should be 17 not %d, msg_index=%d\n", + size, msg_index); + ok((buffer = HeapAlloc(GetProcessHeap(), 0, size)) != NULL, "should not be null\n"); + rsize = DdeGetData(hdata, buffer, size, 0); + if (msg_index == 10 || msg_index == 11 || msg_index == 16 || msg_index ==17) + { + ok(rsize == size, "Incorrect size returned, expected %d got %d, msg_index=%d\n", + size, rsize, msg_index); + if (msg_index == 10 || msg_index == 16) + todo_wine { + ok(!lstrcmpW((WCHAR*)buffer, test_cmd_w), + "Expected \"Test dde command\", msg_index=%d\n", + msg_index); + ok(size == 34, "Expected 34, got %d, msg_index=%d\n", size, msg_index); + } else + { + ok(!lstrcmpW((WCHAR*)buffer, test_cmd_w), + "Expected \"Test dde command\", msg_index=%d\n", + msg_index); + ok(size == 34, "Expected 34, got %d, msg_index=%d\n", size, msg_index); + } + }else if (msg_index == 22) + { + ok(rsize == size, "Incorrect size returned, expected %d got %d, msg_index=%d\n", + size, rsize, msg_index); + } else + { + ok(rsize == size, "Incorrect size returned, expected %d got %d, msg_index=%d\n", + size, rsize, msg_index); + if (msg_index == 5) + todo_wine { + ok(!lstrcmpA((CHAR*)buffer, test_cmd), "Expected %s, got %s, msg_index=%d\n", + test_cmd, buffer, msg_index); + ok(size == 17, "Expected size should be 17, got %d, msg_index=%d\n", size, msg_index); + } + else + { + ok(!lstrcmpA((CHAR*)buffer, test_cmd), "Expected %s, got %s, msg_index=%d\n", + test_cmd, buffer, msg_index); + ok(size == 17, "Expected size should be 17, got %d, msg_index=%d\n", size, msg_index); + } + + } + + return (HDDEDATA) DDE_FACK; + } + case XTYP_DISCONNECT: + return (HDDEDATA) TRUE; + + default: + ok(FALSE, "Unhandled msg: %08x, msg_index=%d\n", uType, msg_index); + } + + return NULL; +} + +static HDDEDATA CALLBACK client_end_to_end_callback(UINT uType, UINT uFmt, HCONV hconv, + HSZ hsz1, HSZ hsz2, HDDEDATA hdata, + ULONG_PTR dwData1, ULONG_PTR dwData2) +{ + switch (uType) + { + case XTYP_DISCONNECT: + return (HDDEDATA) TRUE; + + default: + ok(FALSE, "Unhandled msg: %08x\n", uType); + } + + return NULL; +} + +static void test_end_to_end_client(BOOL type_a) +{ + DWORD ret, err; + DWORD client_pid = 0; + HSZ server, topic; + HCONV hconv; + HDDEDATA hdata; + static char test_cmd[] = "test dde command"; + static WCHAR test_cmd_w[] = {'t','e','s','t',' ','d','d','e',' ','c','o','m','m','a','n','d',0}; + static char test_service[] = "TestDDEService"; + static WCHAR test_service_w[] = {'T','e','s','t','D','D','E','S','e','r','v','i','c','e',0}; + static char test_topic[] = "TestDDETopic"; + static WCHAR test_topic_w[] = {'T','e','s','t','D','D','E','T','o','p','i','c',0}; + + trace("Start end to end client %d\n", type_a); + + if (type_a) + ret = DdeInitializeA(&client_pid, client_end_to_end_callback, APPCMD_CLIENTONLY, 0); + else + ret = DdeInitializeW(&client_pid, client_end_to_end_callback, APPCMD_CLIENTONLY, 0); + ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %x\n", ret); + + if (type_a) + { + server = DdeCreateStringHandleA(client_pid, test_service, CP_WINANSI); + topic = DdeCreateStringHandleA(client_pid, test_topic, CP_WINANSI); + } + else { + server = DdeCreateStringHandleW(client_pid, test_service_w, CP_WINUNICODE); + topic = DdeCreateStringHandleW(client_pid, test_topic_w, CP_WINUNICODE); + } + + DdeGetLastError(client_pid); + hconv = DdeConnect(client_pid, server, topic, NULL); + ok(hconv != NULL, "Expected non-NULL conversation\n"); + ret = DdeGetLastError(client_pid); + ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %x\n", ret); + DdeFreeStringHandle(client_pid, server); + + /* Test both A and W data being passed to DdeClientTransaction */ + hdata = DdeClientTransaction((LPBYTE)test_cmd, strlen(test_cmd) + 1, + hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret); + ok(hdata != NULL, "DdeClientTransaction failed\n"); + ok(ret == DDE_FACK, "wrong status code %x\n", ret); + err = DdeGetLastError(client_pid); + ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err); + + hdata = DdeClientTransaction((LPBYTE)test_cmd_w, lstrlenW(test_cmd_w) * sizeof(WCHAR) + 2, + hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret); + ok(hdata != NULL, "DdeClientTransaction failed\n"); + ok(ret == DDE_FACK, "wrong status code %x\n", ret); + err = DdeGetLastError(client_pid); + ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err); + + DdeFreeStringHandle(client_pid, topic); + ret = DdeDisconnect(hconv); + ok(ret == TRUE, "Expected TRUE, got %x\n", ret); + + ret = DdeUninitialize(client_pid); + ok(ret == TRUE, "Expected TRUE, got %x\n", ret); + +} + +static void test_end_to_end_server(HANDLE hproc, HANDLE hthread, BOOL type_a) +{ + MSG msg; + HSZ server; + BOOL ret; + DWORD res; + HDDEDATA hdata; + static CHAR test_service[] = "TestDDEService"; + + trace("start end to end server %d\n", type_a); + server_pid = 0; + + if (type_a) + res = DdeInitializeA(&server_pid, server_end_to_end_callback, APPCLASS_STANDARD, 0); + else + res = DdeInitializeW(&server_pid, server_end_to_end_callback, APPCLASS_STANDARD, 0); + ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res); + + server = DdeCreateStringHandleA(server_pid, test_service, CP_WINANSI); + ok(server != NULL, "Expected non-NULL string handle\n"); + + hdata = DdeNameService(server_pid, server, 0, DNS_REGISTER); + ok(hdata == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", hdata); + ResumeThread( hthread ); + + + while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0) + { + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); + } + + ret = DdeUninitialize(server_pid); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); + GetExitCodeProcess( hproc, &res ); + ok( !res, "client failed with %u error(s)\n", res ); +} + START_TEST(dde) { int argc; @@ -2080,10 +2419,16 @@ START_TEST(dde) test_ddeml_client(); else if (!lstrcmpA(argv[2], "msg")) test_msg_client(); + else if (!lstrcmpA(argv[2], "enda")) + test_end_to_end_client(TRUE); + else if (!lstrcmpA(argv[2], "endw")) + test_end_to_end_client(FALSE); return; } + test_initialisation(); + ZeroMemory(&startup, sizeof(STARTUPINFO)); sprintf(buffer, "%s dde ddeml", argv[0]); startup.cb = sizeof(startup); @@ -2091,9 +2436,9 @@ START_TEST(dde) startup.wShowWindow = SW_SHOWNORMAL; CreateProcessA(NULL, buffer, NULL, NULL, FALSE, - 0, NULL, NULL, &startup, &proc); + CREATE_SUSPENDED, NULL, NULL, &startup, &proc); - test_msg_server(proc.hProcess); + test_msg_server(proc.hProcess, proc.hThread); sprintf(buffer, "%s dde msg", argv[0]); CreateProcessA(NULL, buffer, NULL, NULL, FALSE, @@ -2101,6 +2446,32 @@ START_TEST(dde) test_ddeml_server(proc.hProcess); + /* Test the combinations of A and W interfaces with A and W data + end to end to ensure that data conversions are accurate */ + sprintf(buffer, "%s dde enda", argv[0]); + CreateProcessA(NULL, buffer, NULL, NULL, FALSE, + CREATE_SUSPENDED, NULL, NULL, &startup, &proc); + + test_end_to_end_server(proc.hProcess, proc.hThread, TRUE); + + sprintf(buffer, "%s dde endw", argv[0]); + CreateProcessA(NULL, buffer, NULL, NULL, FALSE, + CREATE_SUSPENDED, NULL, NULL, &startup, &proc); + + test_end_to_end_server(proc.hProcess, proc.hThread, FALSE); + + sprintf(buffer, "%s dde enda", argv[0]); + CreateProcessA(NULL, buffer, NULL, NULL, FALSE, + CREATE_SUSPENDED, NULL, NULL, &startup, &proc); + + test_end_to_end_server(proc.hProcess, proc.hThread, FALSE); + + sprintf(buffer, "%s dde endw", argv[0]); + CreateProcessA(NULL, buffer, NULL, NULL, FALSE, + CREATE_SUSPENDED, NULL, NULL, &startup, &proc); + + test_end_to_end_server(proc.hProcess, proc.hThread, TRUE); + test_dde_aw_transaction(); test_DdeCreateDataHandle(); diff --git a/rostests/winetests/user32/dialog.c b/rostests/winetests/user32/dialog.c index 8bf3c290b95..f92566c16b4 100755 --- a/rostests/winetests/user32/dialog.c +++ b/rostests/winetests/user32/dialog.c @@ -874,7 +874,7 @@ static void InitialFocusTest (void) hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG", (LPSTR)RT_DIALOG); hTemplate = LoadResource(g_hinst, hResource); - pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate); + pTemplate = LockResource(hTemplate); g_hwndInitialFocusT1 = 0; hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0); @@ -896,7 +896,8 @@ static void test_GetDlgItemText(void) ret = GetDlgItemTextA(NULL, 0, string, sizeof(string)/sizeof(string[0])); ok(!ret, "GetDlgItemText(NULL) shouldn't have succeeded\n"); - ok(string[0] == '\0', "string retrieved using GetDlgItemText should have been NULL terminated\n"); + ok(string[0] == '\0' || broken(!strcmp(string, "Overwrite Me")), + "string retrieved using GetDlgItemText should have been NULL terminated\n"); } static void test_DialogBoxParamA(void) @@ -906,12 +907,16 @@ static void test_DialogBoxParamA(void) SetLastError(0xdeadbeef); ret = DialogBoxParamA(GetModuleHandle(NULL), "IDD_DIALOG" , hwnd_invalid, 0 , 0); - ok(0 == ret, "DialogBoxParamA returned %d, expected 0\n", ret); - ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError(),"got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError()); + ok(0 == ret || broken(ret == -1), "DialogBoxParamA returned %d, expected 0\n", ret); + ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() || + broken(GetLastError() == 0xdeadbeef), + "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError()); SetLastError(0xdeadbeef); ret = DialogBoxParamA(GetModuleHandle(NULL), "RESOURCE_INVALID" , 0, 0, 0); ok(-1 == ret, "DialogBoxParamA returned %d, expected -1\n", ret); - ok(ERROR_RESOURCE_NAME_NOT_FOUND == GetLastError(),"got %d, expected ERROR_RESOURCE_NAME_NOT_FOUND\n",GetLastError()); + ok(ERROR_RESOURCE_NAME_NOT_FOUND == GetLastError() || + broken(GetLastError() == 0xdeadbeef), + "got %d, expected ERROR_RESOURCE_NAME_NOT_FOUND\n",GetLastError()); } static void test_DisabledDialogTest(void) diff --git a/rostests/winetests/user32/edit.c b/rostests/winetests/user32/edit.c index 0c5a6786188..f6dc918240f 100755 --- a/rostests/winetests/user32/edit.c +++ b/rostests/winetests/user32/edit.c @@ -1336,30 +1336,41 @@ static void test_margins_font_change(void) SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0)); SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0); margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0); - ok(LOWORD(margins) == 0, "got %d\n", LOWORD(margins)); - ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins)); - + ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */ + "got %d\n", LOWORD(margins)); + ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */ + "got %d\n", HIWORD(margins)); + SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0)); SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0); margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0); - ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins)); - ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins)); + ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */ + "got %d\n", LOWORD(margins)); + ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */ + "got %d\n", HIWORD(margins)); SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1)); SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0); margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0); - ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins)); - ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); + ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */ + "got %d\n", LOWORD(margins)); + ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */ + "got %d\n", HIWORD(margins)); SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO)); margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0); - ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins)); - ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); + ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */ + "got %d\n", LOWORD(margins)); + ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */ + "got %d\n", HIWORD(margins)); + SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0); margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0); - ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins)); - ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); - + ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */ + "got %d\n", LOWORD(margins)); + ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */ + "got %d\n", HIWORD(margins)); + /* Above a certain size threshold then the margin is updated */ SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE); SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0)); @@ -1380,7 +1391,8 @@ static void test_margins_font_change(void) ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0); margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0); - ok(LOWORD(margins) != LOWORD(font_margins), "got %d\n", LOWORD(margins)); + ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */ + "got %d\n", LOWORD(margins)); ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins)); SendMessageA(hwEdit, WM_SETFONT, 0, 0); @@ -1989,6 +2001,53 @@ static void UnregisterWindowClasses (void) UnregisterClassA(szEditTextPositionClass, hinst); } +void test_fontsize(void) +{ + HWND hwEdit; + HFONT hfont; + LOGFONT lf; + LONG r; + char szLocalString[MAXLEN]; + + memset(&lf,0,sizeof(LOGFONTA)); + strcpy(lf.lfFaceName,"Arial"); + lf.lfHeight = -300; /* taller than the edit box */ + lf.lfWeight = 500; + hfont = CreateFontIndirect(&lf); + + trace("EDIT: Oversized font (Multi line)\n"); + hwEdit= CreateWindow("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL, + 0, 0, 150, 50, NULL, NULL, hinst, NULL); + + SendMessage(hwEdit,WM_SETFONT,(WPARAM)hfont,0); + + if (winetest_interactive) + ShowWindow (hwEdit, SW_SHOW); + + r = SendMessage(hwEdit, WM_CHAR, 'A', 1); + ok(1 == r, "Expected: %d, got: %d\n", 1, r); + r = SendMessage(hwEdit, WM_CHAR, 'B', 1); + ok(1 == r, "Expected: %d, got: %d\n", 1, r); + r = SendMessage(hwEdit, WM_CHAR, 'C', 1); + ok(1 == r, "Expected: %d, got: %d\n", 1, r); + + GetWindowText(hwEdit, szLocalString, MAXLEN); + ok(lstrcmp(szLocalString, "ABC")==0, + "Wrong contents of edit: %s\n", szLocalString); + + r = SendMessage(hwEdit, EM_POSFROMCHAR,0,0); + ok(r != -1,"EM_POSFROMCHAR failed index 0\n"); + r = SendMessage(hwEdit, EM_POSFROMCHAR,1,0); + ok(r != -1,"EM_POSFROMCHAR failed index 1\n"); + r = SendMessage(hwEdit, EM_POSFROMCHAR,2,0); + ok(r != -1,"EM_POSFROMCHAR failed index 2\n"); + r = SendMessage(hwEdit, EM_POSFROMCHAR,3,0); + ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n"); + + DestroyWindow (hwEdit); + DeleteObject(hfont); +} + START_TEST(edit) { hinst = GetModuleHandleA(NULL); @@ -2012,6 +2071,7 @@ START_TEST(edit) test_wantreturn_edit_dialog(); test_singleline_wantreturn_edit_dialog(); test_child_edit_wmkeydown(); + test_fontsize(); UnregisterWindowClasses(); } diff --git a/rostests/winetests/user32/input.c b/rostests/winetests/user32/input.c index 0876709f77a..4297fe21877 100755 --- a/rostests/winetests/user32/input.c +++ b/rostests/winetests/user32/input.c @@ -357,17 +357,31 @@ static void test_Input_whitebox(void) DestroyWindow(hWndTest); } -static void empty_message_queue(void) { +/* try to make sure pending X events have been processed before continuing */ +static void empty_message_queue(void) +{ MSG msg; - while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + int diff = 200; + int min_timeout = 50; + DWORD time = GetTickCount() + diff; + + while (diff > 0) + { + if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break; + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + diff = time - GetTickCount(); + min_timeout = 20; } } struct transition_s { WORD wVk; BYTE before_state; + BYTE optional; }; typedef enum { @@ -398,6 +412,7 @@ struct sendinput_test_s { struct message expected_messages[MAXKEYMESSAGES+1]; } sendinput_test[] = { /* test ALT+F */ + /* 0 */ {VK_LMENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}}, {{WM_SYSKEYDOWN, hook|wparam, VK_LMENU}, {WM_SYSKEYDOWN}, {0}}}, {'F', 0, 0, {{'F', 0x00}, {0}}, @@ -410,6 +425,7 @@ struct sendinput_test_s { {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, /* test CTRL+O */ + /* 4 */ {VK_LCONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}}, {'O', 0, 0, {{'O', 0x00}, {0}}, @@ -420,6 +436,7 @@ struct sendinput_test_s { {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, /* test ALT+CTRL+X */ + /* 8 */ {VK_LMENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}}, {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN}, {0}}}, {VK_LCONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, @@ -434,6 +451,7 @@ struct sendinput_test_s { {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, /* test SHIFT+A */ + /* 14 */ {VK_LSHIFT, 0, 0, {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}}, {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}}, {'A', 0, 0, {{'A', 0x00}, {0}}, @@ -444,16 +462,19 @@ struct sendinput_test_s { {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, /* test L-SHIFT & R-SHIFT: */ /* RSHIFT == LSHIFT */ + /* 18 */ {VK_RSHIFT, 0, 0, - {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}}, + /* recent windows versions (>= w2k3) correctly report an RSHIFT transition */ + {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00, TRUE}, {VK_RSHIFT, 0x00, TRUE}, {0}}, {{WM_KEYDOWN, hook|wparam, VK_RSHIFT}, {WM_KEYDOWN}, {0}}}, {VK_RSHIFT, KEYEVENTF_KEYUP, 0, - {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}}, + {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80, TRUE}, {VK_RSHIFT, 0x80, TRUE}, {0}}, {{WM_KEYUP, hook, hook|wparam, VK_RSHIFT}, {WM_KEYUP}, {0}}}, /* LSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */ + /* 20 */ {VK_LSHIFT, KEYEVENTF_EXTENDEDKEY, 0, {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}}, {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, LLKHF_EXTENDED}, @@ -463,6 +484,7 @@ struct sendinput_test_s { {{WM_KEYUP, hook|wparam|lparam, VK_LSHIFT, LLKHF_UP|LLKHF_EXTENDED}, {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, /* RSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */ + /* 22 */ {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, 0, {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}}, {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED}, @@ -471,27 +493,35 @@ struct sendinput_test_s { {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}}, {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED}, {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, + + /* Note about wparam for hook with generic key (VK_SHIFT, VK_CONTROL, VK_MENU): + win2k - sends to hook whatever we generated here + winXP+ - Attempts to convert key to L/R key but not always correct + */ /* SHIFT == LSHIFT */ + /* 24 */ {VK_SHIFT, 0, 0, {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_SHIFT, 0}, + {{WM_KEYDOWN, hook/* |wparam */|lparam, VK_SHIFT, 0}, {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, {VK_SHIFT, KEYEVENTF_KEYUP, 0, {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_SHIFT, LLKHF_UP}, + {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP}, {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, /* SHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */ + /* 26 */ {VK_SHIFT, KEYEVENTF_EXTENDEDKEY, 0, {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_SHIFT, LLKHF_EXTENDED}, + {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_EXTENDED}, {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, {VK_SHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0, {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_SHIFT, LLKHF_UP|LLKHF_EXTENDED}, + {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP|LLKHF_EXTENDED}, {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, /* test L-CONTROL & R-CONTROL: */ /* RCONTROL == LCONTROL */ + /* 28 */ {VK_RCONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, {{WM_KEYDOWN, hook|wparam, VK_RCONTROL}, @@ -501,6 +531,7 @@ struct sendinput_test_s { {{WM_KEYUP, hook|wparam, VK_RCONTROL}, {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}}, /* LCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */ + /* 30 */ {VK_LCONTROL, KEYEVENTF_EXTENDEDKEY, 0, {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}}, {{WM_KEYDOWN, hook|wparam|lparam, VK_LCONTROL, LLKHF_EXTENDED}, @@ -510,6 +541,7 @@ struct sendinput_test_s { {{WM_KEYUP, hook|wparam|lparam, VK_LCONTROL, LLKHF_UP|LLKHF_EXTENDED}, {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}}, /* RCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */ + /* 32 */ {VK_RCONTROL, KEYEVENTF_EXTENDEDKEY, 0, {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}}, {{WM_KEYDOWN, hook|wparam|lparam, VK_RCONTROL, LLKHF_EXTENDED}, @@ -519,26 +551,29 @@ struct sendinput_test_s { {{WM_KEYUP, hook|wparam|lparam, VK_RCONTROL, LLKHF_UP|LLKHF_EXTENDED}, {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}}, /* CONTROL == LCONTROL */ + /* 34 */ {VK_CONTROL, 0, 0, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam, VK_CONTROL}, + {{WM_KEYDOWN, hook/*|wparam, VK_CONTROL*/}, {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}}, {VK_CONTROL, KEYEVENTF_KEYUP, 0, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam, VK_CONTROL}, + {{WM_KEYUP, hook/*|wparam, VK_CONTROL*/}, {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}}, /* CONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */ + /* 36 */ {VK_CONTROL, KEYEVENTF_EXTENDEDKEY, 0, {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_CONTROL, LLKHF_EXTENDED}, + {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_EXTENDED}, {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}}, {VK_CONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0, {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_CONTROL, LLKHF_UP|LLKHF_EXTENDED}, + {{WM_KEYUP, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_UP|LLKHF_EXTENDED}, {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}}, /* test L-MENU & R-MENU: */ /* RMENU == LMENU */ + /* 38 */ {VK_RMENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}}, {{WM_SYSKEYDOWN, hook|wparam, VK_RMENU}, @@ -549,6 +584,7 @@ struct sendinput_test_s { {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP}, {WM_SYSCOMMAND}, {0}}}, /* LMENU | KEYEVENTF_EXTENDEDKEY == RMENU */ + /* 40 */ {VK_LMENU, KEYEVENTF_EXTENDEDKEY, 0, {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}}, {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_LMENU, LLKHF_EXTENDED}, @@ -559,6 +595,7 @@ struct sendinput_test_s { {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED}, {WM_SYSCOMMAND}, {0}}}, /* RMENU | KEYEVENTF_EXTENDEDKEY == RMENU */ + /* 42 */ {VK_RMENU, KEYEVENTF_EXTENDEDKEY, 0, {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}}, {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_RMENU, LLKHF_EXTENDED}, @@ -569,27 +606,30 @@ struct sendinput_test_s { {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED}, {WM_SYSCOMMAND}, {0}}}, /* MENU == LMENU */ + /* 44 */ {VK_MENU, 0, 0, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}}, - {{WM_SYSKEYDOWN, hook|wparam, VK_MENU}, + {{WM_SYSKEYDOWN, hook/*|wparam, VK_MENU*/}, {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}}, {VK_MENU, KEYEVENTF_KEYUP, 1, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam, VK_MENU}, + {{WM_KEYUP, hook/*|wparam, VK_MENU*/}, {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP}, {WM_SYSCOMMAND}, {0}}}, /* MENU | KEYEVENTF_EXTENDEDKEY == RMENU */ + /* 46 */ {VK_MENU, KEYEVENTF_EXTENDEDKEY, 0, {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}}, - {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_MENU, LLKHF_EXTENDED}, + {{WM_SYSKEYDOWN, hook/*|wparam*/|lparam, VK_MENU, LLKHF_EXTENDED}, {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}}, {VK_MENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 1, {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_MENU, LLKHF_UP|LLKHF_EXTENDED}, + {{WM_KEYUP, hook/*|wparam*/|lparam, VK_MENU, LLKHF_UP|LLKHF_EXTENDED}, {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED}, {WM_SYSCOMMAND}, {0}}}, /* test LSHIFT & RSHIFT */ + /* 48 */ {VK_LSHIFT, 0, 0, {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}}, {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, 0}, @@ -629,15 +669,15 @@ static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_tes { failcount++; todo_wine { - ok(matched, "%02d: %02x from %02x -> %02x " - "instead of %02x -> %02x\n", id, t->wVk, - ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state, + ok(matched, "%2d (%x/%x): %02x from %02x -> %02x " + "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags, + t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state, ~t->before_state&0x80); } } else { - ok(matched, "%02d: %02x from %02x -> %02x " - "instead of %02x -> %02x\n", id, t->wVk, - ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state, + ok(matched || t->optional, "%2d (%x/%x): %02x from %02x -> %02x " + "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags, + t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state, ~t->before_state&0x80); } ks2[t->wVk] = ks1[t->wVk]; /* clear the match */ @@ -648,11 +688,12 @@ static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_tes { failcount++; todo_wine - ok(FALSE, "%02d: %02x from %02x -> %02x unexpected\n", id, i, ks1[i], ks2[i]); + ok(FALSE, "%2d (%x/%x): %02x from %02x -> %02x unexpected\n", + id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]); } else - ok(ks2[i] == ks1[i], "%02d: %02x from %02x -> %02x unexpected\n", - id, i, ks1[i], ks2[i]); + ok(ks2[i] == ks1[i], "%2d (%x/%x): %02x from %02x -> %02x unexpected\n", + id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]); while (expected->message && actual_cnt < sent_messages_cnt) { @@ -661,8 +702,8 @@ static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_tes if (expected->message == actual->message) { ok((expected->flags & hook) == (actual->flags & hook), - "%x/%x: the msg 0x%04x should have been sent by a hook\n", - test->wVk, test->dwFlags, expected->message); + "%2d (%x/%x): the msg 0x%04x should have been sent by a hook\n", + id, test->wVk, test->dwFlags, expected->message); if (expected->flags & wparam) { @@ -670,13 +711,13 @@ static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_tes { failcount++; todo_wine - ok(FALSE, "%x/%x: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", - test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam); + ok(FALSE, "%2d (%x/%x): in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", + id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam); } else ok(expected->wParam == actual->wParam, - "%x/%x: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", - test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam); + "%2d (%x/%x): in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", + id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam); } if (expected->flags & lparam) { @@ -684,13 +725,13 @@ static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_tes { failcount++; todo_wine - ok(FALSE, "%x/%x: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", - test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam); + ok(FALSE, "%2d (%x/%x): in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", + id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam); } else ok(expected->lParam == actual->lParam, - "%x/%x: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", - test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam); + "%2d (%x/%x): in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", + id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam); } } else if (expected->flags & optional) @@ -703,13 +744,13 @@ static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_tes failcount++; todo_wine ok(FALSE, - "%x/%x: the msg 0x%04x was expected, but got msg 0x%04x instead\n", - test->wVk, test->dwFlags, expected->message, actual->message); + "%2d (%x/%x): the msg 0x%04x was expected, but got msg 0x%04x instead\n", + id, test->wVk, test->dwFlags, expected->message, actual->message); } else ok(FALSE, - "%x/%x: the msg 0x%04x was expected, but got msg 0x%04x instead\n", - test->wVk, test->dwFlags, expected->message, actual->message); + "%2d (%x/%x): the msg 0x%04x was expected, but got msg 0x%04x instead\n", + id, test->wVk, test->dwFlags, expected->message, actual->message); actual_cnt++; expected++; @@ -725,17 +766,17 @@ static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_tes { failcount++; todo_wine - ok(FALSE, "%x/%x: the msg sequence is not complete: expected %04x - actual %04x\n", - test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message); + ok(FALSE, "%2d (%x/%x): the msg sequence is not complete: expected %04x - actual %04x\n", + id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message); } else - ok(FALSE, "%x/%x: the msg sequence is not complete: expected %04x - actual %04x\n", - test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message); + ok(FALSE, "%2d (%x/%x): the msg sequence is not complete: expected %04x - actual %04x\n", + id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message); } if( test->_todo_wine && !failcount) /* succeeded yet marked todo */ todo_wine - ok(TRUE, "%x/%x: marked \"todo_wine\" but succeeds\n", test->wVk, test->dwFlags); + ok(TRUE, "%2d (%x/%x): marked \"todo_wine\" but succeeds\n", id, test->wVk, test->dwFlags); sent_messages_cnt = 0; } @@ -1000,19 +1041,19 @@ static void test_GetMouseMovePointsEx(void) SetLastError(MYERROR); retval = pGetMouseMovePointsEx(0, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)+1, &in, out, BUFLIM, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); /* test second and third parameter @@ -1020,7 +1061,7 @@ static void test_GetMouseMovePointsEx(void) SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_NOACCESS == GetLastError(), + ok(GetLastError() == ERROR_NOACCESS || GetLastError() == MYERROR, "expected error ERROR_NOACCESS, got %u\n", GetLastError()); SetLastError(MYERROR); @@ -1051,7 +1092,7 @@ static void test_GetMouseMovePointsEx(void) count = -1; retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, count, GMMP_USE_DISPLAY_POINTS); ok(retval == count, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); SetLastError(MYERROR); @@ -1075,7 +1116,7 @@ static void test_GetMouseMovePointsEx(void) SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); /* it was not possible to force an error with the fifth parameter on win2k */ @@ -1084,25 +1125,25 @@ static void test_GetMouseMovePointsEx(void) SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, NULL, out, BUFLIM, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT)-1, &in, NULL, BUFLIM, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), NULL, out, BUFLIM+1, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); SetLastError(MYERROR); retval = pGetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &in, NULL, BUFLIM+1, GMMP_USE_DISPLAY_POINTS); ok(retval == -1, "expected GetMouseMovePointsEx to fail, got %d\n", retval); - ok(ERROR_INVALID_PARAMETER == GetLastError(), + ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == MYERROR, "expected error ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); #undef BUFLIM @@ -1113,6 +1154,18 @@ static void test_key_map(void) { HKL kl = GetKeyboardLayout(0); UINT kL, kR, s, sL; + int i; + static const UINT numpad_collisions[][2] = { + { VK_NUMPAD0, VK_INSERT }, + { VK_NUMPAD1, VK_END }, + { VK_NUMPAD2, VK_DOWN }, + { VK_NUMPAD3, VK_NEXT }, + { VK_NUMPAD4, VK_LEFT }, + { VK_NUMPAD6, VK_RIGHT }, + { VK_NUMPAD7, VK_HOME }, + { VK_NUMPAD8, VK_UP }, + { VK_NUMPAD9, VK_PRIOR }, + }; s = MapVirtualKeyEx(VK_SHIFT, MAPVK_VK_TO_VSC, kl); ok(s != 0, "MapVirtualKeyEx(VK_SHIFT) should return non-zero\n"); @@ -1128,6 +1181,60 @@ static void test_key_map(void) ok(kL == VK_LSHIFT, "Scan code -> vKey = %x (not VK_LSHIFT)\n", kL); kR = MapVirtualKeyEx(0x36, MAPVK_VSC_TO_VK_EX, kl); ok(kR == VK_RSHIFT, "Scan code -> vKey = %x (not VK_RSHIFT)\n", kR); + + /* test that MAPVK_VSC_TO_VK prefers the non-numpad vkey if there's ambiguity */ + for (i = 0; i < sizeof(numpad_collisions)/sizeof(numpad_collisions[0]); i++) + { + UINT numpad_scan = MapVirtualKeyEx(numpad_collisions[i][0], MAPVK_VK_TO_VSC, kl); + UINT other_scan = MapVirtualKeyEx(numpad_collisions[i][1], MAPVK_VK_TO_VSC, kl); + + /* do they really collide for this layout? */ + if (numpad_scan && other_scan == numpad_scan) + { + UINT vkey = MapVirtualKeyEx(numpad_scan, MAPVK_VSC_TO_VK, kl); + ok(vkey != numpad_collisions[i][0], + "Got numpad vKey %x for scan code %x when there was another choice\n", + vkey, numpad_scan); + } + } +} + +static void test_ToUnicode(void) +{ + WCHAR wStr[2]; + BYTE state[256]; + const BYTE SC_RETURN = 0x1c, SC_TAB = 0x0f; + const BYTE HIGHEST_BIT = 0x80; + int i, ret; + for(i=0; i<256; i++) + state[i]=0; + + SetLastError(0xdeadbeef); + ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0); + if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + skip("ToUnicode is not implemented\n"); + return; + } + + ok(ret == 1, "ToUnicode for Return key didn't return 1 (was %i)\n", ret); + if(ret == 1) + ok(wStr[0]=='\r', "ToUnicode for CTRL + Return was %i (expected 13)\n", wStr[0]); + state[VK_CONTROL] |= HIGHEST_BIT; + state[VK_LCONTROL] |= HIGHEST_BIT; + + ret = ToUnicode(VK_TAB, SC_TAB, state, wStr, 2, 0); + todo_wine ok(ret == 0, "ToUnicode for CTRL + Tab didn't return 0 (was %i)\n", ret); + + ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0); + ok(ret == 1, "ToUnicode for CTRL + Return didn't return 1 (was %i)\n", ret); + if(ret == 1) + ok(wStr[0]=='\n', "ToUnicode for CTRL + Return was %i (expected 10)\n", wStr[0]); + + state[VK_SHIFT] |= HIGHEST_BIT; + state[VK_LSHIFT] |= HIGHEST_BIT; + ret = ToUnicode(VK_RETURN, SC_RETURN, state, wStr, 2, 0); + todo_wine ok(ret == 0, "ToUnicode for CTRL + SHIFT + Return didn't return 0 (was %i)\n", ret); } START_TEST(input) @@ -1143,6 +1250,7 @@ START_TEST(input) test_keynames(); test_mouse_ll_hook(); test_key_map(); + test_ToUnicode(); if(pGetMouseMovePointsEx) test_GetMouseMovePointsEx(); diff --git a/rostests/winetests/user32/listbox.c b/rostests/winetests/user32/listbox.c index 5e650e089bc..c8723576335 100644 --- a/rostests/winetests/user32/listbox.c +++ b/rostests/winetests/user32/listbox.c @@ -44,7 +44,7 @@ static const char * const strings[4] = { "Fourth added which is very long because at some time we only had a 256 byte character buffer and that was overflowing in one of those applications that had a common dialog file open box and tried to add a 300 characters long custom filter string which of course the code did not like and crashed. Just make sure this string is longer than 256 characters." }; -static const char BAD_EXTENSION[] = "*.txtbad"; +static const char BAD_EXTENSION[] = "*.badtxt"; static HWND create_listbox (DWORD add_style, HWND parent) @@ -103,8 +103,8 @@ buttonpress (HWND handle, WORD x, WORD y) LPARAM lp=x+(y<<16); WAIT; - SendMessage (handle, WM_LBUTTONDOWN, (WPARAM) MK_LBUTTON, lp); - SendMessage (handle, WM_LBUTTONUP , (WPARAM) 0 , lp); + SendMessage (handle, WM_LBUTTONDOWN, MK_LBUTTON, lp); + SendMessage (handle, WM_LBUTTONUP, 0, lp); REDRAW; } @@ -254,7 +254,9 @@ static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARA rc_client.left, rc_client.top, rc_client.right, rc_client.bottom); GetClipBox(dis->hDC, &rc_clip); trace("clip rect (%d,%d-%d,%d)\n", rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); - ok(EqualRect(&rc_client, &rc_clip), "client rect of the listbox should be equal to the clip box\n"); + ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip), + "client rect of the listbox should be equal to the clip box," + "or the clip box should be empty\n"); trace("rcItem (%d,%d-%d,%d)\n", dis->rcItem.left, dis->rcItem.top, dis->rcItem.right, dis->rcItem.bottom); @@ -456,18 +458,18 @@ static void test_itemfrompoint(void) HWND hList = CreateWindow( "ListBox", "list test", WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT, 1, 1, 600, 100, NULL, NULL, NULL, NULL ); - LONG r, id; + ULONG r, id; RECT rc; - /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000 */ + /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */ r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 )); - ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r ); + ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r ); r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 )); - ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r ); + ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r ); r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 )); - ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r ); + ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r ); id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi"); ok( id == 0, "item id wrong\n"); @@ -478,7 +480,8 @@ static void test_itemfrompoint(void) ok( r == 0x1, "ret %x\n", r ); r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 )); - ok( r == 0x10001, "ret %x\n", r ); + ok( r == 0x10001 || broken(r == 1), /* nt4 */ + "ret %x\n", r ); /* Resize control so that below assertions about sizes are valid */ r = SendMessage( hList, LB_GETITEMRECT, 0, (LPARAM)&rc); @@ -515,16 +518,20 @@ static void test_itemfrompoint(void) ok( r == 1, "ret %x\n", r); r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) ); - ok( r == 0x10001, "ret %x\n", r ); + ok( r == 0x10001 || broken(r == 1), /* nt4 */ + "ret %x\n", r ); r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) ); - ok( r == 0x10001, "ret %x\n", r ); + ok( r == 0x10001 || broken(r == 1), /* nt4 */ + "ret %x\n", r ); r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) ); - ok( r == 0x10005, "item %x\n", r ); + ok( r == 0x10005 || broken(r == 5), /* nt4 */ + "item %x\n", r ); r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) ); - ok( r == 0x10005, "item %x\n", r ); + ok( r == 0x10005 || broken(r == 5), /* nt4 */ + "item %x\n", r ); DestroyWindow( hList ); } @@ -550,13 +557,14 @@ static void test_listbox_item_data(void) DestroyWindow( hList ); } -static void test_listbox_LB_DIR() +static void test_listbox_LB_DIR(void) { HWND hList; int res, itemCount; int itemCount_justFiles; int itemCount_justDrives; int itemCount_allFiles; + int itemCount_allDirs; int i; char pathBuffer[MAX_PATH]; char * p; @@ -582,6 +590,11 @@ static void test_listbox_LB_DIR() strcpy(pathBuffer, "*"); SendMessage(hList, LB_RESETCONTENT, 0, 0); res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer); + if (res == -1) /* "*" wildcard doesn't work on win9x */ + { + strcpy(pathBuffer, "*.*"); + res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer); + } ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError()); /* There should be some content in the listbox */ @@ -637,15 +650,22 @@ static void test_listbox_LB_DIR() strcpy(pathBuffer, "*"); SendMessage(hList, LB_RESETCONTENT, 0, 0); res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); + if (res == -1 || res <= itemCount_allFiles) /* "*" wildcard doesn't work on win9x */ + { + strcpy(pathBuffer, "*.*"); + SendMessage(hList, LB_RESETCONTENT, 0, 0); + res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); + } ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError()); /* There should be some content in the listbox. * All files plus "[..]" */ itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_allFiles + 1, - "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected %d\n", - itemCount, itemCount_allFiles + 1); + itemCount_allDirs = itemCount - itemCount_allFiles; + ok (itemCount > itemCount_allFiles, + "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n", + itemCount, itemCount_allFiles); ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n", itemCount - 1, res); @@ -694,7 +714,7 @@ static void test_listbox_LB_DIR() strcpy(pathBuffer, "*"); SendMessage(hList, LB_RESETCONTENT, 0, 0); res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); - ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError()); + ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError()); /* There should be some content in the listbox. In particular, there should * be at least one element before, since the string "[-c-]" should @@ -749,10 +769,11 @@ static void test_listbox_LB_DIR() * been added. */ itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_justDrives + itemCount_allFiles, - "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n", + ok (itemCount == itemCount_justDrives + itemCount_allFiles || + broken(itemCount == itemCount_justDrives), /* "*" wildcard broken on win9x */ + "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n", itemCount, itemCount_justDrives + itemCount_allFiles); - ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n"); + ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n"); /* This tests behavior when no files match the wildcard */ strcpy(pathBuffer, BAD_EXTENSION); @@ -810,9 +831,10 @@ static void test_listbox_LB_DIR() * be exactly the number of plain files, plus the number of mapped drives. */ itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_allFiles + itemCount_justDrives + 1, + ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs || + broken(itemCount == itemCount_justDrives + itemCount_allDirs), /* "*" wildcard broken on win9x */ "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", - itemCount, itemCount_allFiles + itemCount_justDrives + 1); + itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs); ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n"); /* Every single item in the control should start with a w and end in .c, @@ -879,18 +901,20 @@ static void test_listbox_LB_DIR() strcpy(pathBuffer, "*"); SendMessage(hList, LB_RESETCONTENT, 0, 0); res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer); - ok (res == 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError()); + ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError()); - /* There should be exactly one element: "[..]" */ itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0); - ok (itemCount == 1, + ok (itemCount == itemCount_allDirs, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", - itemCount, 1); + itemCount, itemCount_allDirs); ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n"); - memset(pathBuffer, 0, MAX_PATH); - SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer); - ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n"); + if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */ + { + memset(pathBuffer, 0, MAX_PATH); + SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer); + ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n"); + } /* This tests behavior when no files match the wildcard */ strcpy(pathBuffer, BAD_EXTENSION); @@ -923,9 +947,9 @@ static void test_listbox_LB_DIR() /* There should be no plain files on the listbox */ itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_justDrives + 1, + ok (itemCount == itemCount_justDrives + itemCount_allDirs, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", - itemCount, itemCount_justDrives + 1); + itemCount, itemCount_justDrives + itemCount_allDirs); ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n"); for (i = 0; i < itemCount; i++) { @@ -936,7 +960,8 @@ static void test_listbox_LB_DIR() if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } else { - ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit expected [..]\n", i, pathBuffer); + ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', + "Element %d (%s) does not fit expected [...]\n", i, pathBuffer); } } @@ -954,7 +979,7 @@ static void test_listbox_LB_DIR() strcpy(pathBuffer, "w*.c"); SendMessage(hList, LB_RESETCONTENT, 0, 0); res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); - ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError()); + ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError()); /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */ itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0); @@ -1046,6 +1071,7 @@ static void test_listbox_dlgdir(void) HINSTANCE hInst; HWND hWnd; int res, itemCount; + int itemCount_allDirs; int itemCount_justFiles; int itemCount_justDrives; int i; @@ -1125,13 +1151,14 @@ static void test_listbox_dlgdir(void) ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError()); /* There should be some content in the listbox. In particular, there should - * be exactly one more element than before, since the string "[..]" should + * be exactly more elements than before, since the directories should * have been added. */ itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_justFiles + 1, - "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected %d\n", - itemCount, itemCount_justFiles + 1); + itemCount_allDirs = itemCount - itemCount_justFiles; + ok (itemCount >= itemCount_justFiles, + "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n", + itemCount, itemCount_justFiles); /* Every single item in the control should start with a w and end in .c, * except for the "[..]" string, which should appear exactly as it is. @@ -1140,7 +1167,7 @@ static void test_listbox_dlgdir(void) memset(pathBuffer, 0, MAX_PATH); SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); p = pathBuffer + strlen(pathBuffer); - ok( !strcmp(pathBuffer, "[..]") || + ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') || ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && (*(p-1) == 'c' || *(p-1) == 'C') && (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); @@ -1153,13 +1180,15 @@ static void test_listbox_dlgdir(void) ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res); itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == 1, "DlgDirList() incorrectly filled the listbox! (expected 1 got %d)\n", - itemCount); + ok (itemCount == itemCount_allDirs, + "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n", + itemCount_allDirs, itemCount); for (i = 0; i < itemCount; i++) { memset(pathBuffer, 0, MAX_PATH); SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); p = pathBuffer + strlen(pathBuffer); - ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit requested [..]\n", i, pathBuffer); + ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', + "Element %d (%s) does not fit requested [...]\n", i, pathBuffer); } @@ -1216,9 +1245,9 @@ static void test_listbox_dlgdir(void) * plus one "[..]" */ itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_justFiles + itemCount_justDrives + 1, + ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs, "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", - itemCount, itemCount_justFiles + itemCount_justDrives + 1); + itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs); /* Every single item in the control should start with a w and end in .c, * except for the "[..]" string, which should appear exactly as it is, @@ -1232,7 +1261,7 @@ static void test_listbox_dlgdir(void) if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } else { - ok( !strcmp(pathBuffer, "[..]") || + ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') || ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && (*(p-1) == 'c' || *(p-1) == 'C') && (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); @@ -1246,9 +1275,9 @@ static void test_listbox_dlgdir(void) ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res); itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_justDrives + 1, + ok (itemCount == itemCount_justDrives + itemCount_allDirs, "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n", - itemCount_justDrives + 1, itemCount); + itemCount_justDrives + itemCount_allDirs, itemCount); @@ -1260,14 +1289,16 @@ static void test_listbox_dlgdir(void) /* There should be exactly one element: "[..]" */ itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == 1, + ok (itemCount == itemCount_allDirs, "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", - itemCount, 1); - - memset(pathBuffer, 0, MAX_PATH); - SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer); - ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n"); + itemCount, itemCount_allDirs); + if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */ + { + memset(pathBuffer, 0, MAX_PATH); + SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer); + ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n"); + } /* Test behavior when no files match the wildcard */ strcpy(pathBuffer, BAD_EXTENSION); @@ -1276,7 +1307,7 @@ static void test_listbox_dlgdir(void) ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res); itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == 1, "DlgDirList() incorrectly filled the listbox!\n"); + ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n"); /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ @@ -1287,9 +1318,9 @@ static void test_listbox_dlgdir(void) /* There should be no plain files on the listbox */ itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_justDrives + 1, + ok (itemCount == itemCount_justDrives + itemCount_allDirs, "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", - itemCount, itemCount_justDrives + 1); + itemCount, itemCount_justDrives + itemCount_allDirs); for (i = 0; i < itemCount; i++) { memset(pathBuffer, 0, MAX_PATH); @@ -1299,7 +1330,8 @@ static void test_listbox_dlgdir(void) if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } else { - ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit expected [..]\n", i, pathBuffer); + ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', + "Element %d (%s) does not fit expected [...]\n", i, pathBuffer); } } @@ -1310,7 +1342,8 @@ static void test_listbox_dlgdir(void) ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res); itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); - ok (itemCount == itemCount_justDrives + 1, "DlgDirList() incorrectly filled the listbox!\n"); + ok (itemCount == itemCount_justDrives + itemCount_allDirs, + "DlgDirList() incorrectly filled the listbox!\n"); /* Now test DlgDirSelectEx() in normal operation */ diff --git a/rostests/winetests/user32/menu.c b/rostests/winetests/user32/menu.c index 1aa2eb6688c..adc9410d22c 100755 --- a/rostests/winetests/user32/menu.c +++ b/rostests/winetests/user32/menu.c @@ -57,6 +57,33 @@ static void init_function_pointers(void) #undef GET_PROC } +static BOOL correct_behavior(void) +{ + HMENU hmenu; + MENUITEMINFO info; + BOOL rc; + + hmenu = CreateMenu(); + + memset(&info, 0, sizeof(MENUITEMINFO)); + info.cbSize= sizeof(MENUITEMINFO); + SetLastError(0xdeadbeef); + rc = GetMenuItemInfo(hmenu, 0, TRUE, &info); + /* Win9x : 0xdeadbeef + * NT4 : ERROR_INVALID_PARAMETER + * >= W2K : ERROR_MENU_ITEM_NOT_FOUND + */ + if (!rc && GetLastError() != ERROR_MENU_ITEM_NOT_FOUND) + { + win_skip("NT4 and below can't handle a bigger MENUITEMINFO struct\n"); + DestroyMenu(hmenu); + return FALSE; + } + + DestroyMenu(hmenu); + return TRUE; +} + static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) @@ -357,7 +384,8 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt, MOD_GotDrawItemMsg = FALSE; mii.fMask = MIIM_FTYPE | MIIM_DATA | MIIM_STATE; mii.fType = 0; - mii.fState = MF_CHECKED; + /* check the menu item unless MNS_CHECKORBMP is set */ + mii.fState = (mnuopt != 2 ? MFS_CHECKED : MFS_UNCHECKED); mii.dwItemData =0; MODsizes[0] = bmpsize; hastab = 0; @@ -447,8 +475,14 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt, if( hbmp == HBMMENU_CALLBACK && MOD_GotDrawItemMsg) { /* check the position of the bitmap */ /* horizontal */ - expect = ispop ? (4 + ( mnuopt ? 0 : GetSystemMetrics(SM_CXMENUCHECK))) - : 3; + if (!ispop) + expect = 3; + else if (mnuopt == 0) + expect = 4 + GetSystemMetrics(SM_CXMENUCHECK); + else if (mnuopt == 1) + expect = 4; + else /* mnuopt == 2 */ + expect = 2; ok( expect == MOD_rc[0].left, "bitmap left is %d expected %d\n", MOD_rc[0].left, expect); failed = failed || !(expect == MOD_rc[0].left); @@ -1691,7 +1725,7 @@ static struct menu_mouse_tests_s { static void send_key(WORD wVk) { TEST_INPUT i[2]; - memset(&i, 0, 2*sizeof(INPUT)); + memset(i, 0, sizeof(i)); i[0].type = i[1].type = INPUT_KEYBOARD; i[0].u.ki.wVk = i[1].u.ki.wVk = wVk; i[1].u.ki.dwFlags = KEYEVENTF_KEYUP; @@ -1706,10 +1740,10 @@ static void click_menu(HANDLE hWnd, struct menu_item_pair_s *mi) RECT r; int screen_w = GetSystemMetrics(SM_CXSCREEN); int screen_h = GetSystemMetrics(SM_CYSCREEN); + BOOL ret = GetMenuItemRect(mi->uMenu > 2 ? NULL : hWnd, hMenu, mi->uItem, &r); + if(!ret) return; - GetMenuItemRect(mi->uMenu > 2 ? NULL : hWnd, hMenu, mi->uItem, &r); - - memset(&i, 0, 3*sizeof(INPUT)); + memset(i, 0, sizeof(i)); i[0].type = i[1].type = i[2].type = INPUT_MOUSE; i[0].u.mi.dx = i[1].u.mi.dx = i[2].u.mi.dx = ((r.left + 5) * 65535) / screen_w; @@ -1785,6 +1819,7 @@ static void test_menu_input(void) { WNDCLASSA wclass; HINSTANCE hInstance = GetModuleHandleA( NULL ); HANDLE hThread, hWnd; + DWORD tid; wclass.lpszClassName = "MenuTestClass"; wclass.style = CS_HREDRAW | CS_VREDRAW; @@ -1820,7 +1855,7 @@ static void test_menu_input(void) { ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); - hThread = CreateThread(NULL, 0, test_menu_input_thread, hWnd, 0, NULL); + hThread = CreateThread(NULL, 0, test_menu_input_thread, hWnd, 0, &tid); while(1) { if (WAIT_TIMEOUT != WaitForSingleObject(hThread, 50)) @@ -1997,9 +2032,10 @@ static void test_menu_hilitemenuitem( void ) static void check_menu_items(HMENU hmenu, UINT checked_cmd, UINT checked_type, UINT checked_state) { - UINT i, count; + INT i, count; count = GetMenuItemCount(hmenu); + ok (count != -1, "GetMenuItemCount returned -1\n"); for (i = 0; i < count; i++) { @@ -2140,7 +2176,7 @@ static void test_menu_resource_layout(void) { MF_SEPARATOR, MF_GRAYED|MF_DISABLED, 8, "" } }; HMENU hmenu; - UINT count, i; + INT count, i; BOOL ret; hmenu = LoadMenuIndirect(&menu_template); @@ -2342,13 +2378,23 @@ START_TEST(menu) { init_function_pointers(); + /* Wine defines MENUITEMINFO for W2K and above. NT4 and below can't + * handle that. + */ + if (correct_behavior()) + { + test_menu_add_string(); + test_menu_iteminfo(); + test_menu_search_bycommand(); + test_CheckMenuRadioItem(); + test_menu_resource_layout(); + test_InsertMenu(); + } + register_menu_check_class(); test_menu_locked_by_window(); test_menu_ownerdraw(); - test_menu_add_string(); - test_menu_iteminfo(); - test_menu_search_bycommand(); test_menu_bmp_and_string(); if( !pSendInput) @@ -2358,7 +2404,4 @@ START_TEST(menu) test_menu_flags(); test_menu_hilitemenuitem(); - test_CheckMenuRadioItem(); - test_menu_resource_layout(); - test_InsertMenu(); } diff --git a/rostests/winetests/user32/monitor.c b/rostests/winetests/user32/monitor.c index a723dd1d610..3d0359679eb 100644 --- a/rostests/winetests/user32/monitor.c +++ b/rostests/winetests/user32/monitor.c @@ -2,6 +2,7 @@ * Unit tests for monitor APIs * * Copyright 2005 Huw Davies + * Copyright 2008 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -61,7 +62,7 @@ static BOOL CALLBACK monitor_enum_proc(HMONITOR hmon, HDC hdc, LPRECT lprc, mi.cbSize = sizeof(mi); ok(pGetMonitorInfoA(hmon, (MONITORINFO*)&mi), "GetMonitorInfo failed\n"); - if(mi.dwFlags == MONITORINFOF_PRIMARY) + if (mi.dwFlags & MONITORINFOF_PRIMARY) strcpy(primary, mi.szDevice); return TRUE; @@ -73,15 +74,20 @@ static void test_enumdisplaydevices(void) char primary_device_name[32]; char primary_monitor_device_name[32]; DWORD primary_num = -1, num = 0; + BOOL ret; + + if (!pEnumDisplayDevicesA) + { + skip("EnumDisplayDevicesA is not available\n"); + return; + } dd.cb = sizeof(dd); - if(pEnumDisplayDevicesA == NULL) return; while(1) { BOOL ret; HDC dc; ret = pEnumDisplayDevicesA(NULL, num, &dd, 0); - ok(ret || num != 0, "EnumDisplayDevices fails with num == 0\n"); if(!ret) break; if(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { @@ -97,22 +103,25 @@ static void test_enumdisplaydevices(void) } num++; } - ok(primary_num != -1, "Didn't get the primary device\n"); - if(pEnumDisplayMonitors && pGetMonitorInfoA) { - ok(pEnumDisplayMonitors(NULL, NULL, monitor_enum_proc, (LPARAM)primary_monitor_device_name), - "EnumDisplayMonitors failed\n"); - - ok(!strcmp(primary_monitor_device_name, primary_device_name), - "monitor device name %s, device name %s\n", primary_monitor_device_name, - primary_device_name); + if (primary_num == -1 || !pEnumDisplayMonitors || !pGetMonitorInfoA) + { + win_skip("EnumDisplayMonitors or GetMonitorInfoA are not available\n"); + return; } + + primary_monitor_device_name[0] = 0; + ret = pEnumDisplayMonitors(NULL, NULL, monitor_enum_proc, (LPARAM)primary_monitor_device_name); + ok(ret, "EnumDisplayMonitors failed\n"); + ok(!strcmp(primary_monitor_device_name, primary_device_name), + "monitor device name %s, device name %s\n", primary_monitor_device_name, + primary_device_name); } struct vid_mode { DWORD w, h, bpp, freq, fields; - LONG success; + BOOL must_succeed; }; static const struct vid_mode vid_modes_test[] = { @@ -120,18 +129,20 @@ static const struct vid_mode vid_modes_test[] = { {640, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY, 1}, {640, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL , 1}, {640, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT , 1}, - {640, 480, 0, 0, DM_BITSPERPEL , 1}, - {640, 480, 0, 0, DM_DISPLAYFREQUENCY, 1}, + {640, 480, 0, 0, DM_BITSPERPEL , 0}, + {640, 480, 0, 0, DM_DISPLAYFREQUENCY, 0}, - {0, 0, 0, 0, DM_PELSWIDTH, 1}, - {0, 0, 0, 0, DM_PELSHEIGHT, 1}, + {0, 0, 0, 0, DM_PELSWIDTH, 0}, + {0, 0, 0, 0, DM_PELSHEIGHT, 0}, {640, 480, 0, 0, DM_PELSWIDTH, 0}, {640, 480, 0, 0, DM_PELSHEIGHT, 0}, { 0, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0}, {640, 0, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0}, - {0, 0, 0, 0, DM_DISPLAYFREQUENCY, 0}, + /* the following test succeeds under XP SP3 + {0, 0, 0, 0, DM_DISPLAYFREQUENCY, 0} + */ }; #define vid_modes_cnt (sizeof(vid_modes_test) / sizeof(vid_modes_test[0])) @@ -155,6 +166,45 @@ static void test_ChangeDisplaySettingsEx(void) width = dm.dmPelsWidth; + dm.dmDriverExtra = 1; + res = ChangeDisplaySettingsA(&dm, CDS_TEST); + ok(res == DISP_CHANGE_SUCCESSFUL, + "ChangeDisplaySettingsA returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res); + ok(dm.dmDriverExtra == 0 || broken(dm.dmDriverExtra == 1) /* win9x */, + "ChangeDisplaySettingsA didn't reset dmDriverExtra to 0\n"); + + /* crashes under XP SP3 for large dmDriverExtra values */ + dm.dmDriverExtra = 1; + res = pChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL); + ok(res == DISP_CHANGE_SUCCESSFUL, + "ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_BADMODE\n", res); + ok(dm.dmDriverExtra == 1, "ChangeDisplaySettingsExA shouldn't reset dmDriverExtra to 0\n"); + + memset(&dmW, 0, sizeof(dmW)); + dmW.dmSize = sizeof(dmW); + dmW.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + dmW.dmPelsWidth = dm.dmPelsWidth; + dmW.dmPelsHeight = dm.dmPelsHeight; + dmW.dmDriverExtra = 1; + SetLastError(0xdeadbeef); + res = ChangeDisplaySettingsW(&dmW, CDS_TEST); + if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + { + ok(res == DISP_CHANGE_SUCCESSFUL, + "ChangeDisplaySettingsW returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res); + ok(dmW.dmDriverExtra == 0, "ChangeDisplaySettingsW didn't reset dmDriverExtra to 0\n"); + } + + /* Apparently XP treats dmDriverExtra being != 0 as an error */ + dmW.dmDriverExtra = 1; + res = pChangeDisplaySettingsExW(NULL, &dmW, NULL, CDS_TEST, NULL); + if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + { + ok(res == DISP_CHANGE_SUCCESSFUL, + "ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_BADMODE\n", res); + ok(dmW.dmDriverExtra == 1, "ChangeDisplaySettingsExW shouldn't reset dmDriverExtra to 0\n"); + } + /* the following 2 tests show that dm.dmSize being 0 is invalid, but * ChangeDisplaySettingsExA still reports success. */ @@ -162,8 +212,10 @@ static void test_ChangeDisplaySettingsEx(void) dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; dm.dmPelsWidth = width; res = pChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL); - ok(res == DISP_CHANGE_SUCCESSFUL, - "ChangeDisplaySettingsExA returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res); + ok(res == DISP_CHANGE_SUCCESSFUL || + res == DISP_CHANGE_BADMODE || /* Win98, WinMe */ + res == DISP_CHANGE_FAILED, /* NT4 */ + "ChangeDisplaySettingsExA returned unexpected %d\n", res); memset(&dmW, 0, sizeof(dmW)); dmW.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; @@ -171,8 +223,10 @@ static void test_ChangeDisplaySettingsEx(void) SetLastError(0xdeadbeef); res = pChangeDisplaySettingsExW(NULL, &dmW, NULL, CDS_TEST, NULL); if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) - ok(res == DISP_CHANGE_FAILED, - "ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_FAILED\n", res); + ok(res == DISP_CHANGE_FAILED || + res == DISP_CHANGE_BADPARAM || /* NT4 */ + res == DISP_CHANGE_BADMODE /* XP SP3 */, + "ChangeDisplaySettingsExW returned %d\n", res); memset(&dm, 0, sizeof(dm)); dm.dmSize = sizeof(dm); @@ -184,10 +238,10 @@ static void test_ChangeDisplaySettingsEx(void) dm.dmBitsPerPel = vid_modes_test[i].bpp; dm.dmDisplayFrequency = vid_modes_test[i].freq; dm.dmFields = vid_modes_test[i].fields; - res = pChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_FULLSCREEN, NULL); - ok(vid_modes_test[i].success ? + res = pChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL); + ok(vid_modes_test[i].must_succeed ? (res == DISP_CHANGE_SUCCESSFUL) : - (res == DISP_CHANGE_BADMODE || res == DISP_CHANGE_BADPARAM), + (res == DISP_CHANGE_SUCCESSFUL || res == DISP_CHANGE_BADMODE || res == DISP_CHANGE_BADPARAM), "Unexpected ChangeDisplaySettingsEx() return code for resolution[%d]: %d\n", i, res); if (res == DISP_CHANGE_SUCCESSFUL) @@ -195,6 +249,8 @@ static void test_ChangeDisplaySettingsEx(void) RECT r, r1, virt; SetRect(&virt, 0, 0, GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN)); + if (IsRectEmpty(&virt)) /* NT4 doesn't have SM_CX/YVIRTUALSCREEN */ + SetRect(&virt, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); OffsetRect(&virt, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN)); /* Resolution change resets clip rect */ @@ -214,7 +270,10 @@ static void test_ChangeDisplaySettingsEx(void) SetRect(&r1, virt.left - 10, virt.top - 10, virt.right + 20, virt.bottom + 20); ok(ClipCursor(&r1), "ClipCursor() failed\n"); ok(GetClipCursor(&r), "GetClipCursor() failed\n"); - ok(EqualRect(&r, &virt), "Invalid clip rect: (%d %d) x (%d %d)\n", r.left, r.top, r.right, r.bottom); + ok(EqualRect(&r, &virt) || + broken(EqualRect(&r, &r1)) /* win9x */, + "Invalid clip rect: (%d %d) x (%d %d)\n", r.left, r.top, r.right, r.bottom); + ClipCursor(&virt); } } res = pChangeDisplaySettingsExA(NULL, NULL, NULL, CDS_RESET, NULL); @@ -226,6 +285,12 @@ static void test_monitors(void) HMONITOR monitor, primary; POINT pt; + if (!pMonitorFromPoint || !pMonitorFromWindow) + { + skip("MonitorFromPoint or MonitorFromWindow are not available\n"); + return; + } + pt.x = pt.y = 0; primary = pMonitorFromPoint( pt, MONITOR_DEFAULTTOPRIMARY ); ok( primary != 0, "couldn't get primary monitor\n" ); @@ -238,15 +303,96 @@ static void test_monitors(void) ok( monitor == primary, "got %p, should get primary %p for MONITOR_DEFAULTTONEAREST\n", monitor, primary ); } +static BOOL CALLBACK find_primary_mon(HMONITOR hmon, HDC hdc, LPRECT rc, LPARAM lp) +{ + MONITORINFO mi; + BOOL ret; + + mi.cbSize = sizeof(mi); + ret = pGetMonitorInfoA(hmon, &mi); + ok(ret, "GetMonitorInfo failed\n"); + if (mi.dwFlags & MONITORINFOF_PRIMARY) + { + *(HMONITOR *)lp = hmon; + return FALSE; + } + return TRUE; +} + +static void test_work_area(void) +{ + HMONITOR hmon; + MONITORINFO mi; + RECT rc_work, rc_normal; + HWND hwnd; + WINDOWPLACEMENT wp; + BOOL ret; + + if (!pEnumDisplayMonitors || !pGetMonitorInfoA) + { + skip("EnumDisplayMonitors or GetMonitorInfoA are not available\n"); + return; + } + + hmon = 0; + ret = pEnumDisplayMonitors(NULL, NULL, find_primary_mon, (LPARAM)&hmon); + ok(!ret && hmon != 0, "Failed to find primary monitor\n"); + + mi.cbSize = sizeof(mi); + SetLastError(0xdeadbeef); + ret = pGetMonitorInfoA(hmon, &mi); + ok(ret, "GetMonitorInfo error %u\n", GetLastError()); + ok(mi.dwFlags & MONITORINFOF_PRIMARY, "not a primary monitor\n"); + trace("primary monitor (%d,%d-%d,%d)\n", + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom); + + SetLastError(0xdeadbeef); + ret = SystemParametersInfo(SPI_GETWORKAREA, 0, &rc_work, 0); + ok(ret, "SystemParametersInfo error %u\n", GetLastError()); + trace("work area (%d,%d-%d,%d)\n", rc_work.left, rc_work.top, rc_work.right, rc_work.bottom); + ok(EqualRect(&rc_work, &mi.rcWork), "work area is different\n"); + + hwnd = CreateWindowEx(0, "static", NULL, WS_OVERLAPPEDWINDOW|WS_VISIBLE,100,100,10,10,0,0,0,NULL); + ok(hwnd != 0, "CreateWindowEx failed\n"); + + ret = GetWindowRect(hwnd, &rc_normal); + ok(ret, "GetWindowRect failed\n"); + trace("normal (%d,%d-%d,%d)\n", rc_normal.left, rc_normal.top, rc_normal.right, rc_normal.bottom); + + wp.length = sizeof(wp); + ret = GetWindowPlacement(hwnd, &wp); + ok(ret, "GetWindowPlacement failed\n"); + trace("min: %d,%d max %d,%d normal %d,%d-%d,%d\n", + wp.ptMinPosition.x, wp.ptMinPosition.y, + wp.ptMaxPosition.x, wp.ptMaxPosition.y, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + OffsetRect(&wp.rcNormalPosition, rc_work.left, rc_work.top); + if (!EqualRect(&mi.rcMonitor, &mi.rcWork)) /* FIXME: remove once Wine is fixed */ + todo_wine ok(EqualRect(&rc_normal, &wp.rcNormalPosition), "normal pos is different\n"); + else + ok(EqualRect(&rc_normal, &wp.rcNormalPosition), "normal pos is different\n"); + + SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW); + + wp.length = sizeof(wp); + ret = GetWindowPlacement(hwnd, &wp); + ok(ret, "GetWindowPlacement failed\n"); + trace("min: %d,%d max %d,%d normal %d,%d-%d,%d\n", + wp.ptMinPosition.x, wp.ptMinPosition.y, + wp.ptMaxPosition.x, wp.ptMaxPosition.y, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + ok(EqualRect(&rc_normal, &wp.rcNormalPosition), "normal pos is different\n"); + + DestroyWindow(hwnd); +} START_TEST(monitor) { init_function_pointers(); test_enumdisplaydevices(); - if (winetest_interactive) - test_ChangeDisplaySettingsEx(); - if (pMonitorFromPoint && pMonitorFromWindow) - test_monitors(); - else - skip("MonitorFromPoint and/or MonitorFromWindow are not available\n"); + test_ChangeDisplaySettingsEx(); + test_monitors(); + test_work_area(); } diff --git a/rostests/winetests/user32/msg.c b/rostests/winetests/user32/msg.c index 5c66f0c5a07..16ce1c24e30 100755 --- a/rostests/winetests/user32/msg.c +++ b/rostests/winetests/user32/msg.c @@ -141,6 +141,8 @@ static const struct message WmSWP_ShowOverlappedSeq[] = { { WM_ERASEBKGND, sent|optional }, { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, + { WM_NOTIFYFORMAT, sent|optional }, + { WM_QUERYUISTATE, sent|optional }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* Win9x: SWP_NOSENDCHANGING */ { WM_ACTIVATEAPP, sent|wparam, 1 }, @@ -152,15 +154,20 @@ static const struct message WmSWP_ShowOverlappedSeq[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* Win9x adds SWP_NOZORDER below */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_PAINT, sent|optional }, + { WM_NCPAINT, sent|beginpaint|optional }, + { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 } }; /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE) @@ -219,6 +226,9 @@ static const struct message WmSWP_ResizePopupSeq[] = { */ static const struct message WmSWP_MoveSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE }, + { WM_NCPAINT, sent|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOCLIENTSIZE }, { WM_MOVE, sent|defwinproc|wparam, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, @@ -229,13 +239,13 @@ static const struct message WmSWP_MoveSeq[] = { * SWP_NOZORDER is stripped by the logging code */ static const struct message WmSWP_ResizeNoZOrder[] = { - { WM_WINDOWPOSCHANGING, sent|wparam, 0/*SWP_NOZORDER*/ }, + { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ - { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */ @@ -314,12 +324,12 @@ static const struct message WmSwitchNotMaximizedChild[] = { /* Activate 2nd MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE}, /* in the 2nd MDI child */ { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 2nd MDI child */ - { WM_SETVISIBLE, hook }, /* in the 1st MDI child */ + { HCBT_SETFOCUS, hook }, /* in the 1st MDI child */ { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ { WM_SETFOCUS, sent, 0 }, /* in the MDI client */ - { WM_SETVISIBLE, hook }, + { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, /* in the MDI client */ { WM_IME_SETCONTEXT, sent|optional }, /* in the MDI client */ { WM_IME_SETCONTEXT, sent|defwinproc|optional }, /* in the 1st MDI child */ @@ -395,7 +405,7 @@ static const struct message WmShowOverlappedSeq[] = { { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent|wparam, 1 }, @@ -406,12 +416,14 @@ static const struct message WmShowOverlappedSeq[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* Win9x adds SWP_NOZORDER below */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCCALCSIZE, sent|optional }, + { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE @@ -421,6 +433,8 @@ static const struct message WmShowOverlappedSeq[] = { { WM_SIZE, sent }, { WM_MOVE, sent }, #endif + { WM_PAINT, sent|optional }, + { WM_NCPAINT, sent|beginpaint|optional }, { 0 } }; /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */ @@ -434,7 +448,7 @@ static const struct message WmShowMaxOverlappedSeq[] = { { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, @@ -444,6 +458,7 @@ static const struct message WmShowMaxOverlappedSeq[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, @@ -451,11 +466,72 @@ static const struct message WmShowMaxOverlappedSeq[] = { { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|optional }, { WM_NCPAINT, sent|optional }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_PAINT, sent|optional }, + { WM_NCPAINT, sent|beginpaint|optional }, + { WM_ERASEBKGND, sent|beginpaint|optional }, + { 0 } +}; +/* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */ +static const struct message WmShowRestoreMaxOverlappedSeq[] = { + { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, + { WM_GETTEXT, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, + { WM_GETMINMAXINFO, sent|defwinproc }, + { WM_NCCALCSIZE, sent|wparam, TRUE }, + { WM_NCPAINT, sent|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, + { WM_MOVE, sent|defwinproc|optional }, + { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, + { WM_NCPAINT, sent|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_PAINT, sent|optional }, + { WM_NCPAINT, sent|beginpaint|optional }, + { WM_ERASEBKGND, sent|beginpaint|optional }, + { 0 } +}; +/* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */ +static const struct message WmShowRestoreMinOverlappedSeq[] = { + { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, + { WM_QUERYOPEN, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS }, + { WM_GETMINMAXINFO, sent|defwinproc }, + { WM_NCCALCSIZE, sent|wparam, TRUE }, + { HCBT_ACTIVATE, hook }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, + { WM_ACTIVATEAPP, sent|wparam, 1 }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS }, + { WM_MOVE, sent|defwinproc }, + { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_ERASEBKGND, sent|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|optional }, + { WM_PAINT, sent|optional }, + { WM_NCPAINT, sent|beginpaint|optional }, + { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 } }; /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */ @@ -471,7 +547,7 @@ static const struct message WmShowMinOverlappedSeq[] = { { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, - { WM_NCPAINT, sent }, + { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, @@ -484,6 +560,9 @@ static const struct message WmShowMinOverlappedSeq[] = { { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent }, { WM_ACTIVATEAPP, sent|wparam, 0 }, + { WM_PAINT, sent|optional }, + { WM_NCPAINT, sent|beginpaint|optional }, + { WM_ERASEBKGND, sent|beginpaint|optional }, { 0 } }; /* ShowWindow(SW_HIDE) for a visible overlapped window */ @@ -510,10 +589,10 @@ static const struct message WmDestroyOverlappedSeq[] = { { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { 0x0090, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, - { WM_NCACTIVATE, sent|wparam, 0 }, - { WM_ACTIVATE, sent|wparam, 0 }, - { WM_ACTIVATEAPP, sent|wparam, 0 }, - { WM_KILLFOCUS, sent|wparam, 0 }, + { WM_NCACTIVATE, sent|optional|wparam, 0 }, + { WM_ACTIVATE, sent|optional|wparam, 0 }, + { WM_ACTIVATEAPP, sent|optional|wparam, 0 }, + { WM_KILLFOCUS, sent|optional|wparam, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, @@ -545,6 +624,9 @@ static const struct message WmCreateMaxPopupSeq[] = { { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_NOMOVE|SWP_NOSIZE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_ACTIVATE, sent|wparam, 1 }, @@ -553,6 +635,7 @@ static const struct message WmCreateMaxPopupSeq[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, @@ -597,9 +680,10 @@ static const struct message WmShowMaxPopupResizedSeq[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGED, sent }, /* WinNT4.0 sends WM_MOVE */ { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, @@ -625,6 +709,7 @@ static const struct message WmShowMaxPopupSeq[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, @@ -658,6 +743,7 @@ static const struct message WmCreatePopupSeq[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_GETTEXT, sent|optional }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, @@ -670,6 +756,7 @@ static const struct message WmShowVisMaxPopupSeq[] = { { WM_GETMINMAXINFO, sent }, { WM_GETTEXT, sent|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, + { WM_GETTEXT, sent|optional }, { WM_NCCALCSIZE, sent|wparam, TRUE }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_NCPAINT, sent|wparam|optional, 1 }, @@ -721,7 +808,7 @@ static const struct message WmShowVisiblePopupSeq_3[] = { { HCBT_ACTIVATE, hook }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, @@ -731,6 +818,7 @@ static const struct message WmShowVisiblePopupSeq_3[] = { { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, + { WM_GETTEXT, sent|optional }, { 0 } }; /* CreateWindow (for child window, not initially visible) */ @@ -846,6 +934,7 @@ static const struct message WmShowChildInvisibleParentSeq_1[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_NCCALCSIZE, sent|wparam, 1 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, + { WM_CHILDACTIVATE, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED }, @@ -1081,6 +1170,12 @@ static const struct message WmCreateCustomDialogSeq[] = { { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_NOTIFYFORMAT, sent|optional }, + { WM_QUERYUISTATE, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_GETMINMAXINFO, sent|optional }, + { WM_NCCALCSIZE, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, @@ -1090,13 +1185,14 @@ static const struct message WmCreateCustomDialogSeq[] = { { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_GETTEXT, sent|optional|defwinproc }, { WM_GETTEXT, sent|optional|defwinproc }, { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, { WM_ACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|optional }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, @@ -1155,10 +1251,11 @@ static const struct message WmShowCustomDialogSeq[] = { { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam|optional, 1 }, { WM_NCACTIVATE, sent|wparam, 1 }, { WM_ACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|optional }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, @@ -1246,6 +1343,7 @@ static const struct message WmModalDialogSeq[] = { { WM_ACTIVATE, sent|wparam, 0 }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, @@ -1493,9 +1591,19 @@ static const struct message WmSHOWNAChildInvisParVis[] = { static const struct message WmSHOWNATopVisible[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, { 0 } }; static const struct message WmSHOWNATopInvisible[] = { + { WM_NOTIFYFORMAT, sent|optional }, + { WM_QUERYUISTATE, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_GETMINMAXINFO, sent|optional }, + { WM_NCCALCSIZE, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, @@ -1516,10 +1624,13 @@ static int after_end_dialog, test_def_id; static int sequence_cnt, sequence_size; static struct message* sequence; static int log_all_parent_messages; +static int paint_loop_done; /* user32 functions */ static HWND (WINAPI *pGetAncestor)(HWND,UINT); +static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO); static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG); +static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO); static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*); static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); @@ -1538,7 +1649,9 @@ static void init_procs(void) } GET_PROC(user32, GetAncestor) + GET_PROC(user32, GetMenuInfo) GET_PROC(user32, NotifyWinEvent) + GET_PROC(user32, SetMenuInfo) GET_PROC(user32, SetWinEventHook) GET_PROC(user32, TrackMouseEvent) GET_PROC(user32, UnhookWinEvent) @@ -1583,7 +1696,7 @@ static void flush_events(void) if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break; while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg ); diff = time - GetTickCount(); - min_timeout = 10; + min_timeout = 20; } } @@ -1729,6 +1842,8 @@ static void ok_sequence_(const struct message *expected, const char *context, in flush_sequence(); } +#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT)) + /******************************** MDI test **********************************/ /* CreateWindow for MDI frame window, initially visible */ @@ -1740,6 +1855,12 @@ static const struct message WmCreateMDIframeSeq[] = { { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_NOTIFYFORMAT, sent|optional }, + { WM_QUERYUISTATE, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_GETMINMAXINFO, sent|optional }, + { WM_NCCALCSIZE, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, @@ -1769,10 +1890,10 @@ static const struct message WmCreateMDIframeSeq[] = { static const struct message WmDestroyMDIframeSeq[] = { { HCBT_DESTROYWND, hook }, { 0x0090, sent|optional }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|wparam|optional, 0 }, /* XP */ { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */ { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */ @@ -1795,26 +1916,26 @@ static const struct message WmCreateMDIclientSeq[] = { { WM_MOVE, sent }, { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */ { WM_SHOWWINDOW, sent|wparam, 1 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 } }; /* ShowWindow(SW_SHOW) for MDI client window */ static const struct message WmShowMDIclientSeq[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 } }; /* ShowWindow(SW_HIDE) for MDI client window */ static const struct message WmHideMDIclientSeq[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam|optional, 0, 0 }, /* win2000 */ { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP */ - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { 0 } }; /* DestroyWindow for MDI client window, initially visible */ @@ -1823,9 +1944,9 @@ static const struct message WmDestroyMDIclientSeq[] = { { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */ { WM_SHOWWINDOW, sent|wparam, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, @@ -1918,10 +2039,10 @@ static const struct message WmDestroyMDIchildVisibleSeq[] = { { 0x0090, sent|optional }, { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* { WM_DESTROY, sent } * Win9x: message sequence terminates here. @@ -2129,7 +2250,7 @@ static const struct message WmCreateMDIchildVisibleMaxSeq2[] = { { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, { HCBT_SETFOCUS, hook }, - { WM_KILLFOCUS, sent|defwinproc }, /* in the 1st MDI child */ + { WM_KILLFOCUS, sent|defwinproc|optional }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, /* in the 1st MDI child */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, @@ -2260,6 +2381,9 @@ static const struct message WmCreateMDIchildInvisibleMaxSeq4[] = { { WM_CREATE, sent }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SIZE, sent|wparam, SIZE_RESTORED }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE }, /* MDI frame */ + { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* MDI frame */ + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* MDI frame */ { WM_MOVE, sent }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, { WM_GETMINMAXINFO, sent }, @@ -2469,12 +2593,12 @@ static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = { { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */ /* in MDI frame */ - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, - { WM_NCCALCSIZE, sent|wparam, 1 }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, { 0x0093, sent|defwinproc|optional }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */ { 0x0093, sent|optional }, @@ -2534,10 +2658,10 @@ static const struct message WmDestroyMDIchildVisibleMaxSeq1[] = { { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */ { WM_SHOWWINDOW, sent|wparam, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, { WM_ERASEBKGND, sent|parent|optional }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 }, { WM_DESTROY, sent }, @@ -2553,19 +2677,19 @@ static const struct message WmMaximizeMDIchildInvisibleSeq[] = { { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, - { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, - { HCBT_SETFOCUS, hook }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCACTIVATE, sent|wparam|optional|defwinproc, 1 }, + { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, - { WM_SETFOCUS, sent }, /* in MDI client */ - { HCBT_SETFOCUS, hook }, - { WM_KILLFOCUS, sent }, /* in MDI client */ + { WM_SETFOCUS, sent|optional }, /* in MDI client */ + { HCBT_SETFOCUS, hook|optional }, + { WM_KILLFOCUS, sent|optional }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, - { WM_SETFOCUS, sent|defwinproc }, - { WM_MDIACTIVATE, sent|defwinproc }, + { WM_SETFOCUS, sent|optional|defwinproc }, + { WM_MDIACTIVATE, sent|optional|defwinproc }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_STATECHANGED }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in MDI frame */ @@ -2586,19 +2710,19 @@ static const struct message WmMaximizeMDIchildInvisibleSeq2[] = { { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 }, - { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, - { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, - { HCBT_SETFOCUS, hook }, + { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCACTIVATE, sent|wparam|defwinproc|optional, 1 }, + { HCBT_SETFOCUS, hook|optional }, { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, - { WM_SETFOCUS, sent }, /* in MDI client */ - { HCBT_SETFOCUS, hook }, - { WM_KILLFOCUS, sent }, /* in MDI client */ + { WM_SETFOCUS, sent|optional }, /* in MDI client */ + { HCBT_SETFOCUS, hook|optional }, + { WM_KILLFOCUS, sent|optional }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, - { WM_SETFOCUS, sent|defwinproc }, - { WM_MDIACTIVATE, sent|defwinproc }, + { WM_SETFOCUS, sent|defwinproc|optional }, + { WM_MDIACTIVATE, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */ { 0 } @@ -2787,7 +2911,7 @@ static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wPara WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -2838,7 +2962,7 @@ static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -2895,7 +3019,8 @@ static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, message != WM_NCHITTEST && message != WM_GETTEXT && message != WM_GETICON && - message != WM_DEVICECHANGE) + message != WM_DEVICECHANGE && + message < 0xc000) { trace("mdi frame: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam); @@ -2907,7 +3032,7 @@ static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -3324,7 +3449,7 @@ static void test_mdi_messages(void) 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, mdi_client, 0, GetModuleHandleA(0), NULL); assert(mdi_child2); - ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", TRUE); + ok_sequence(WmCreateMDIchildInvisibleMaxSeq4, "Create maximized invisible MDI child window", FALSE); ok(IsZoomed(mdi_child2), "MDI child should be maximized\n"); ok(!(GetWindowLongA(mdi_child2, GWL_STYLE) & WS_VISIBLE), "MDI child should be not visible\n"); ok(!IsWindowVisible(mdi_child2), "MDI child should be not visible\n"); @@ -3506,6 +3631,7 @@ static void test_WM_SETREDRAW(HWND hwnd) { DWORD style = GetWindowLongA(hwnd, GWL_STYLE); + flush_events(); flush_sequence(); SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); @@ -3524,6 +3650,7 @@ static void test_WM_SETREDRAW(HWND hwnd) /* restore original WS_VISIBLE state */ SetWindowLongA(hwnd, GWL_STYLE, style); + flush_events(); flush_sequence(); } @@ -3536,6 +3663,9 @@ static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam /* explicitly ignore WM_GETICON message */ if (message == WM_GETICON) return 0; + /* ignore registered messages */ + if (message >= 0xc000) return 0; + switch (message) { /* ignore */ @@ -3552,7 +3682,7 @@ static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -3682,6 +3812,9 @@ static void test_scroll_messages(HWND hwnd) INT min, max; BOOL ret; + flush_events(); + flush_sequence(); + min = 0xdeadbeef; max = 0xdeadbeef; ret = GetScrollRange(hwnd, SB_CTL, &min, &max); @@ -4029,7 +4162,31 @@ static const struct message WmInitEndSession_4[] = { /* Sending undocumented 0x3B message with wparam = 0x80000001 */ static const struct message WmInitEndSession_5[] = { { 0x003B, sent }, - { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 1, ENDSESSION_LOGOFF }, + { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF }, + { 0 } +}; + +static const struct message WmZOrder[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0, 0 }, + { WM_GETMINMAXINFO, sent|defwinproc|wparam, 0, 0 }, + { HCBT_ACTIVATE, hook }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0 }, + { WM_GETTEXT, sent|optional }, + { WM_NCCALCSIZE, sent|wparam|optional, 1 }, + { WM_ACTIVATEAPP, sent|wparam, 1, 0 }, + { WM_NCACTIVATE, sent|wparam|lparam, 1, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam|lparam, 1, 0 }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_GETTEXT, sent|optional }, + { WM_NCCALCSIZE, sent|optional }, { 0 } }; @@ -4046,7 +4203,7 @@ static void test_MsgWaitForMultipleObjects(HWND hwnd) ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); - ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); + ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); @@ -4057,7 +4214,7 @@ static void test_MsgWaitForMultipleObjects(HWND hwnd) ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); - ok(PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); + ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); /* shows QS_POSTMESSAGE flag is cleared in the PeekMessage call */ @@ -4070,9 +4227,9 @@ static void test_MsgWaitForMultipleObjects(HWND hwnd) ret = MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_POSTMESSAGE); ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %x\n", ret); - ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); + ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); - ok(PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); + ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message); } @@ -4100,36 +4257,45 @@ static void test_messages(void) test_WM_SETREDRAW(hwnd); SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); + flush_events(); ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped", FALSE); ok(IsWindowVisible(hwnd), "window should be visible at this point\n"); ok(GetActiveWindow() == hwnd, "window should be active\n"); ok(GetFocus() == hwnd, "window should have input focus\n"); ShowWindow(hwnd, SW_HIDE); - ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE); + flush_events(); + ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); ShowWindow(hwnd, SW_SHOW); + flush_events(); ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE); ShowWindow(hwnd, SW_HIDE); + flush_events(); ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); ShowWindow(hwnd, SW_SHOWMAXIMIZED); + flush_events(); ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE); ShowWindow(hwnd, SW_RESTORE); - /* FIXME: add ok_sequence() here */ + ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", FALSE); + flush_events(); flush_sequence(); ShowWindow(hwnd, SW_MINIMIZE); + flush_events(); ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE); flush_sequence(); ShowWindow(hwnd, SW_RESTORE); - /* FIXME: add ok_sequence() here */ + flush_events(); + ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); flush_sequence(); ShowWindow(hwnd, SW_SHOW); + flush_events(); ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW):overlapped already visible", FALSE); ok(GetActiveWindow() == hwnd, "window should be active\n"); @@ -4141,6 +4307,7 @@ static void test_messages(void) /* test WM_SETREDRAW on a visible top level window */ ShowWindow(hwnd, SW_SHOW); + flush_events(); test_WM_SETREDRAW(hwnd); trace("testing scroll APIs on a visible top level window %p\n", hwnd); @@ -4155,7 +4322,7 @@ static void test_messages(void) ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE ); flush_events(); flush_sequence(); - SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER ); + SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE ); ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE ); flush_events(); flush_sequence(); @@ -4283,7 +4450,7 @@ static void test_messages(void) ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2", FALSE); flush_sequence(); SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); - ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", TRUE); + ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3", FALSE); DestroyWindow(hchild); /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually @@ -4460,42 +4627,70 @@ static void test_messages(void) flush_sequence(); res = SendMessage(hwnd, 0x3B, 0x8000000b, 0); + if (!res) + { + todo_wine win_skip( "Message 0x3b not supported\n" ); + goto done; + } ok_sequence(WmInitEndSession, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x8000000b", TRUE); - todo_wine ok(res == 1, "SendMessage(hwnd, 0x3B, 0x8000000b, 0) should have returned 1 instead of %ld\n", res); res = SendMessage(hwnd, 0x3B, 0x0000000b, 0); ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000b", TRUE); - todo_wine ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000b, 0) should have returned 1 instead of %ld\n", res); res = SendMessage(hwnd, 0x3B, 0x0000000f, 0); ok_sequence(WmInitEndSession_2, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x0000000f", TRUE); - todo_wine ok(res == 1, "SendMessage(hwnd, 0x3B, 0x0000000f, 0) should have returned 1 instead of %ld\n", res); flush_sequence(); res = SendMessage(hwnd, 0x3B, 0x80000008, 0); ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000008", TRUE); - todo_wine ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000008, 0) should have returned 2 instead of %ld\n", res); res = SendMessage(hwnd, 0x3B, 0x00000008, 0); ok_sequence(WmInitEndSession_4, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x00000008", TRUE); - todo_wine ok(res == 2, "SendMessage(hwnd, 0x3B, 0x00000008, 0) should have returned 2 instead of %ld\n", res); res = SendMessage(hwnd, 0x3B, 0x80000004, 0); ok_sequence(WmInitEndSession_3, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000004", TRUE); - todo_wine ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000004, 0) should have returned 2 instead of %ld\n", res); res = SendMessage(hwnd, 0x3B, 0x80000001, 0); ok_sequence(WmInitEndSession_5, "Handling of undocumented 0x3B message by DefWindowProc wparam=0x80000001", TRUE); - todo_wine ok(res == 2, "SendMessage(hwnd, 0x3B, 0x80000001, 0) should have returned 2 instead of %ld\n", res); +done: DestroyWindow(hwnd); flush_sequence(); } +static void test_setwindowpos(void) +{ + HWND hwnd; + RECT rc; + LRESULT res; + const INT winX = 100; + const INT winY = 100; + const INT sysX = GetSystemMetrics(SM_CXMINTRACK); + + hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0, + 0, 0, winX, winY, 0, + NULL, NULL, 0); + + GetWindowRect(hwnd, &rc); + expect(sysX, rc.right); + expect(winY, rc.bottom); + + flush_events(); + flush_sequence(); + res = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, winX, winY, 0); + ok_sequence(WmZOrder, "Z-Order", TRUE); + ok(res == TRUE, "SetWindowPos expected TRUE, got %ld\n", res); + + GetWindowRect(hwnd, &rc); + expect(sysX, rc.right); + expect(winY, rc.bottom); + DestroyWindow(hwnd); +} + static void invisible_parent_tests(void) { HWND hparent, hchild; @@ -4749,6 +4944,9 @@ static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, /* explicitly ignore WM_GETICON message */ if (message == WM_GETICON) return 0; + /* ignore registered messages */ + if (message >= 0xc000) return 0; + msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; @@ -4859,7 +5057,7 @@ static void test_button_messages(void) ok_sequence(WmLButtonUpSeq, "WM_LBUTTONUP on a button", FALSE); flush_sequence(); - zfont = (HFONT)GetStockObject(SYSTEM_FONT); + zfont = GetStockObject(SYSTEM_FONT); SendMessageA(hwnd, WM_SETFONT, (WPARAM)zfont, TRUE); UpdateWindow(hwnd); ok_sequence(WmSetFontButtonSeq, "WM_SETFONT on a button", FALSE); @@ -4890,6 +5088,9 @@ static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, /* explicitly ignore WM_GETICON message */ if (message == WM_GETICON) return 0; + /* ignore registered messages */ + if (message >= 0xc000) return 0; + msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; @@ -5076,8 +5277,8 @@ static const struct message WmImeKeydownMsgSeq_0[] = static const struct message WmImeKeydownMsgSeq_1[] = { - { WM_KEYDOWN, wparam, VK_RETURN }, - { WM_CHAR, wparam, VK_RETURN }, + { WM_KEYDOWN, optional|wparam, VK_RETURN }, + { WM_CHAR, optional|wparam, VK_RETURN }, { 0 } }; @@ -5420,7 +5621,9 @@ static void test_paint_messages(void) trace("testing ValidateRgn(0, NULL)\n"); SetLastError(0xdeadbeef); ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n"); - ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %d\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || + broken( GetLastError() == 0xdeadbeef ) /* win9x */, + "wrong error code %d\n", GetLastError()); check_update_rgn( hwnd, 0 ); flush_events(); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); @@ -5777,10 +5980,90 @@ static void test_paint_messages(void) flush_events(); ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE ); + ok(GetWindowLong( hparent, GWL_STYLE ) & WS_VISIBLE, "parent should be visible\n"); + ok(GetWindowLong( hchild, GWL_STYLE ) & WS_VISIBLE, "child should be visible\n"); + + UpdateWindow( hparent ); + flush_events(); + flush_sequence(); + trace("testing SetWindowPos(-10000, -10000) on child\n"); + SetWindowPos( hchild, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); + check_update_rgn( hchild, 0 ); + flush_events(); + +#if 0 /* this one doesn't pass under Wine yet */ + UpdateWindow( hparent ); + flush_events(); + flush_sequence(); + trace("testing ShowWindow(SW_MINIMIZE) on child\n"); + ShowWindow( hchild, SW_MINIMIZE ); + check_update_rgn( hchild, 0 ); + flush_events(); +#endif + + UpdateWindow( hparent ); + flush_events(); + flush_sequence(); + trace("testing SetWindowPos(-10000, -10000) on parent\n"); + SetWindowPos( hparent, 0, -10000, -10000, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); + check_update_rgn( hparent, 0 ); + flush_events(); + log_all_parent_messages--; DestroyWindow( hparent ); ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); + /* tests for moving windows off-screen (needs simple WS_POPUP windows) */ + + hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok (hparent != 0, "Failed to create parent window\n"); + + hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE, + 10, 10, 100, 100, hparent, 0, 0, NULL); + ok (hchild != 0, "Failed to create child window\n"); + + ShowWindow( hparent, SW_SHOW ); + UpdateWindow( hparent ); + UpdateWindow( hchild ); + flush_events(); + flush_sequence(); + + /* moving child outside of parent boundaries changes update region */ + SetRect( &rect, 0, 0, 40, 40 ); + RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); + SetRectRgn( hrgn, 0, 0, 40, 40 ); + check_update_rgn( hchild, hrgn ); + MoveWindow( hchild, -10, 10, 100, 100, FALSE ); + SetRectRgn( hrgn, 10, 0, 40, 40 ); + check_update_rgn( hchild, hrgn ); + MoveWindow( hchild, -10, -10, 100, 100, FALSE ); + SetRectRgn( hrgn, 10, 10, 40, 40 ); + check_update_rgn( hchild, hrgn ); + + /* moving parent off-screen does too */ + SetRect( &rect, 0, 0, 100, 100 ); + RedrawWindow( hparent, &rect, 0, RDW_INVALIDATE | RDW_ERASE | RDW_NOCHILDREN ); + SetRectRgn( hrgn, 0, 0, 100, 100 ); + check_update_rgn( hparent, hrgn ); + SetRectRgn( hrgn, 10, 10, 40, 40 ); + check_update_rgn( hchild, hrgn ); + MoveWindow( hparent, -20, -20, 200, 200, FALSE ); + SetRectRgn( hrgn, 20, 20, 100, 100 ); + check_update_rgn( hparent, hrgn ); + SetRectRgn( hrgn, 30, 30, 40, 40 ); + check_update_rgn( hchild, hrgn ); + + /* invalidated region is cropped by the parent rects */ + SetRect( &rect, 0, 0, 50, 50 ); + RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); + SetRectRgn( hrgn, 30, 30, 50, 50 ); + check_update_rgn( hchild, hrgn ); + + DestroyWindow( hparent ); + ok(!IsWindow(hchild), "child must be destroyed with its parent\n"); + flush_sequence(); + DeleteObject( hrgn ); DeleteObject( hrgn2 ); } @@ -5860,7 +6143,7 @@ static void test_interthread_messages(void) memset(buf, 0, sizeof(buf)); SetLastError(0xdeadbeef); len = DispatchMessageA(&msg); - ok(!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY, + ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */ "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %d\n", len, GetLastError()); /* the following test causes an exception in user.exe under win9x */ @@ -6141,6 +6424,7 @@ static void pump_msg_loop(HWND hwnd, HACCEL hAccel) /* ignore some unwanted messages */ if (msg.message == WM_MOUSEMOVE || msg.message == WM_GETICON || + msg.message == WM_TIMER || msg.message == WM_DEVICECHANGE) continue; @@ -6183,6 +6467,7 @@ static void test_accelerators(void) hAccel = LoadAccelerators(GetModuleHandleA(0), MAKEINTRESOURCE(1)); assert(hAccel != 0); + flush_events(); pump_msg_loop(hwnd, 0); flush_sequence(); @@ -6366,6 +6651,9 @@ static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, /* explicitly ignore WM_GETICON message */ if (message == WM_GETICON) return 0; + /* ignore registered messages */ + if (message >= 0xc000) return 0; + switch (message) { case WM_ENABLE: @@ -6434,7 +6722,7 @@ static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -6465,17 +6753,12 @@ static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, GetClientRect(parent, &rc); trace("parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom); - - trace("ptReserved = (%d,%d)\n" - "ptMaxSize = (%d,%d)\n" - "ptMaxPosition = (%d,%d)\n" - "ptMinTrackSize = (%d,%d)\n" - "ptMaxTrackSize = (%d,%d)\n", - minmax->ptReserved.x, minmax->ptReserved.y, - minmax->ptMaxSize.x, minmax->ptMaxSize.y, - minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, - minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, - minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n", + minmax->ptReserved.x, minmax->ptReserved.y, + minmax->ptMaxSize.x, minmax->ptMaxSize.y, + minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, + minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, + minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %d != %d\n", minmax->ptMaxSize.x, rc.right); @@ -6519,11 +6802,19 @@ static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, trace("popup: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam); - /* explicitly ignore WM_GETICON message */ - if (message == WM_GETICON) return 0; - - msg.message = message; - msg.flags = sent|wparam|lparam; + switch (message) + { + case WM_GETICON: + /* explicitly ignore WM_GETICON message */ + return 0; + case WM_QUERYENDSESSION: + case WM_ENDSESSION: + lParam &= ~0x01; /* Vista adds a 0x01 flag */ + break; + } + + msg.message = message; + msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; @@ -6555,6 +6846,9 @@ static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam /* explicitly ignore WM_GETICON message */ if (message == WM_GETICON) return 0; + /* ignore registered messages */ + if (message >= 0xc000) return 0; + logged_lParam=lParam; if (log_all_parent_messages || message == WM_PARENTNOTIFY || message == WM_CANCELMODE || @@ -6588,7 +6882,7 @@ static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -6659,6 +6953,9 @@ static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARA /* explicitly ignore WM_GETICON message */ if (message == WM_GETICON) return 0; + /* ignore registered messages */ + if (message >= 0xc000) return 0; + if (test_def_id) { DefDlgProcA(hwnd, DM_SETDEFID, 1, 0); @@ -6677,7 +6974,7 @@ static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARA WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -6815,6 +7112,35 @@ static LRESULT WINAPI ShowWindowProcA(HWND hwnd, UINT message, WPARAM wParam, LP return ret; } +LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CREATE: return 0; + case WM_PAINT: + { + MSG msg2; + static int i = 0; + + if (i < 256) + { + i++; + if (PeekMessageA(&msg2, 0, 0, 0, 1)) + { + TranslateMessage(&msg2); + DispatchMessage(&msg2); + } + i--; + } + else ok(broken(1), "infinite loop\n"); + if ( i == 0) + paint_loop_done = 1; + return DefWindowProcA(hWnd,msg,wParam,lParam); + } + } + return DefWindowProcA(hWnd,msg,wParam,lParam); +} + static BOOL RegisterWindowClasses(void) { WNDCLASSA cls; @@ -6848,6 +7174,10 @@ static BOOL RegisterWindowClasses(void) cls.lpszClassName = "SimpleWindowClass"; if(!RegisterClassA(&cls)) return FALSE; + cls.lpfnWndProc = PaintLoopProcA; + cls.lpszClassName = "PaintLoopWindowClass"; + if(!RegisterClassA(&cls)) return FALSE; + cls.style = CS_NOCLOSE; cls.lpszClassName = "NoCloseWindowClass"; if(!RegisterClassA(&cls)) return FALSE; @@ -6875,6 +7205,35 @@ static BOOL RegisterWindowClasses(void) return TRUE; } +static BOOL is_our_logged_class(HWND hwnd) +{ + char buf[256]; + + if (GetClassNameA(hwnd, buf, sizeof(buf))) + { + if (!lstrcmpiA(buf, "TestWindowClass") || + !lstrcmpiA(buf, "ShowWindowClass") || + !lstrcmpiA(buf, "TestParentClass") || + !lstrcmpiA(buf, "TestPopupClass") || + !lstrcmpiA(buf, "SimpleWindowClass") || + !lstrcmpiA(buf, "TestDialogClass") || + !lstrcmpiA(buf, "MDI_frame_class") || + !lstrcmpiA(buf, "MDI_client_class") || + !lstrcmpiA(buf, "MDI_child_class") || + !lstrcmpiA(buf, "my_button_class") || + !lstrcmpiA(buf, "my_edit_class") || + !lstrcmpiA(buf, "static") || + !lstrcmpiA(buf, "ListBox") || + !lstrcmpiA(buf, "ComboBox") || + !lstrcmpiA(buf, "MyDialogClass") || + !lstrcmpiA(buf, "#32770") || + !lstrcmpiA(buf, "#32768")) + return TRUE; + trace("ignoring window class %s\n", buf); + } + return FALSE; +} + static HHOOK hCBT_hook; static DWORD cbt_hook_thread_id; @@ -6893,7 +7252,6 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) "HCBT_SETFOCUS" }; const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown"; HWND hwnd; - char buf[256]; trace("CBT: %d (%s), %08lx, %08lx\n", nCode, code_name, wParam, lParam); @@ -6935,33 +7293,15 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) /* Log also SetFocus(0) calls */ hwnd = wParam ? (HWND)wParam : (HWND)lParam; - if (GetClassNameA(hwnd, buf, sizeof(buf))) + if (is_our_logged_class(hwnd)) { - if (!lstrcmpiA(buf, "TestWindowClass") || - !lstrcmpiA(buf, "ShowWindowClass") || - !lstrcmpiA(buf, "TestParentClass") || - !lstrcmpiA(buf, "TestPopupClass") || - !lstrcmpiA(buf, "SimpleWindowClass") || - !lstrcmpiA(buf, "TestDialogClass") || - !lstrcmpiA(buf, "MDI_frame_class") || - !lstrcmpiA(buf, "MDI_client_class") || - !lstrcmpiA(buf, "MDI_child_class") || - !lstrcmpiA(buf, "my_button_class") || - !lstrcmpiA(buf, "my_edit_class") || - !lstrcmpiA(buf, "static") || - !lstrcmpiA(buf, "ListBox") || - !lstrcmpiA(buf, "ComboBox") || - !lstrcmpiA(buf, "MyDialogClass") || - !lstrcmpiA(buf, "#32770")) - { - struct message msg; + struct message msg; - msg.message = nCode; - msg.flags = hook|wparam|lparam; - msg.wParam = wParam; - msg.lParam = lParam; - add_message(&msg); - } + msg.message = nCode; + msg.flags = hook|wparam|lparam; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); } return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); } @@ -6974,8 +7314,6 @@ static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, DWORD thread_id, DWORD event_time) { - char buf[256]; - trace("WEH:%p,event %08x,hwnd %p,obj %08x,id %08x,thread %08x,time %08x\n", hevent, event, hwnd, object_id, child_id, thread_id, event_time); @@ -6984,33 +7322,15 @@ static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, /* ignore mouse cursor events */ if (object_id == OBJID_CURSOR) return; - if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf))) + if (!hwnd || is_our_logged_class(hwnd)) { - if (!hwnd || - !lstrcmpiA(buf, "TestWindowClass") || - !lstrcmpiA(buf, "TestParentClass") || - !lstrcmpiA(buf, "TestPopupClass") || - !lstrcmpiA(buf, "SimpleWindowClass") || - !lstrcmpiA(buf, "TestDialogClass") || - !lstrcmpiA(buf, "MDI_frame_class") || - !lstrcmpiA(buf, "MDI_client_class") || - !lstrcmpiA(buf, "MDI_child_class") || - !lstrcmpiA(buf, "my_button_class") || - !lstrcmpiA(buf, "my_edit_class") || - !lstrcmpiA(buf, "static") || - !lstrcmpiA(buf, "ListBox") || - !lstrcmpiA(buf, "ComboBox") || - !lstrcmpiA(buf, "MyDialogClass") || - !lstrcmpiA(buf, "#32770")) - { - struct message msg; + struct message msg; - msg.message = event; - msg.flags = winevent_hook|wparam|lparam; - msg.wParam = object_id; - msg.lParam = child_id; - add_message(&msg); - } + msg.message = event; + msg.flags = winevent_hook|wparam|lparam; + msg.wParam = object_id; + msg.lParam = child_id; + add_message(&msg); } } @@ -7034,7 +7354,7 @@ static LRESULT CALLBACK MsgConversionProcW(HWND hwnd, UINT uMsg, WPARAM wParam, static const struct message WmGetTextLengthAfromW[] = { { WM_GETTEXTLENGTH, sent }, - { WM_GETTEXT, sent }, + { WM_GETTEXT, sent|optional }, { 0 } }; @@ -7164,13 +7484,15 @@ static void test_message_conversion(void) newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ); lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), - NULL, 0, NULL, NULL ), + NULL, 0, NULL, NULL ) || + broken(lRes == lstrlenW(dummy_window_text) + 37), "got bad length %ld\n", lRes ); SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc ); /* restore old wnd proc */ lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 ); ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text), - NULL, 0, NULL, NULL ), + NULL, 0, NULL, NULL ) || + broken(lRes == lstrlenW(dummy_window_text) + 37), "got bad length %ld\n", lRes ); ret = DestroyWindow(hwnd); @@ -8137,8 +8459,11 @@ struct sendmsg_info static DWORD CALLBACK send_msg_thread( LPVOID arg ) { struct sendmsg_info *info = arg; + SetLastError( 0xdeadbeef ); info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL ); - if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT, "unexpected error %d\n", GetLastError()); + if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT || + broken(GetLastError() == 0), /* win9x */ + "unexpected error %d\n", GetLastError()); return 0; } @@ -8162,6 +8487,7 @@ static void test_SendMessageTimeout(void) HANDLE thread; struct sendmsg_info info; DWORD tid; + BOOL is_win9x; info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); @@ -8185,17 +8511,18 @@ static void test_SendMessageTimeout(void) ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); - /* 0 means infinite timeout */ + /* 0 means infinite timeout (but not on win9x) */ info.timeout = 0; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); Sleep(100); wait_for_thread( thread ); CloseHandle( thread ); - ok( info.ret == 1, "SendMessageTimeout failed\n" ); - ok_sequence( WmUser, "WmUser", FALSE ); + is_win9x = !info.ret; + if (is_win9x) ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); + else ok_sequence( WmUser, "WmUser", FALSE ); - /* timeout is treated as signed despite the prototype */ + /* timeout is treated as signed despite the prototype (but not on win9x) */ info.timeout = 0x7fffffff; info.ret = 0xdeadbeef; thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid ); @@ -8211,8 +8538,16 @@ static void test_SendMessageTimeout(void) Sleep(100); wait_for_thread( thread ); CloseHandle( thread ); - ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); - ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); + if (is_win9x) + { + ok( info.ret == 1, "SendMessageTimeout failed\n" ); + ok_sequence( WmUser, "WmUser", FALSE ); + } + else + { + ok( info.ret == 0, "SendMessageTimeout succeeded\n" ); + ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); + } /* now check for timeout during message processing */ SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc ); @@ -8348,6 +8683,9 @@ static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, L /* explicitly ignore WM_GETICON message */ if (message == WM_GETICON) return 0; + /* ignore registered messages */ + if (message >= 0xc000) return 0; + msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; @@ -8483,7 +8821,7 @@ static const struct message WmKeyUpSkippedSeq[] = { 0 } }; -#define EV_START_STOP 0 +#define EV_STOP 0 #define EV_SENDMSG 1 #define EV_ACK 2 @@ -8498,9 +8836,8 @@ static DWORD CALLBACK send_msg_thread_2(void *param) DWORD ret; struct peekmsg_info *info = param; - trace("thread: waiting for start\n"); - WaitForSingleObject(info->hevent[EV_START_STOP], INFINITE); trace("thread: looping\n"); + SetEvent(info->hevent[EV_ACK]); while (1) { @@ -8508,13 +8845,14 @@ static DWORD CALLBACK send_msg_thread_2(void *param) switch (ret) { - case WAIT_OBJECT_0 + EV_START_STOP: + case WAIT_OBJECT_0 + EV_STOP: trace("thread: exiting\n"); return 0; case WAIT_OBJECT_0 + EV_SENDMSG: trace("thread: sending message\n"); - SendNotifyMessageA(info->hwnd, WM_USER, 0, 0); + ok( SendNotifyMessageA(info->hwnd, WM_USER, 0, 0), + "SendNotifyMessageA failed error %u\n", GetLastError()); SetEvent(info->hevent[EV_ACK]); break; @@ -8544,15 +8882,12 @@ static void test_PeekMessage(void) UpdateWindow(info.hwnd); SetFocus(info.hwnd); - info.hevent[EV_START_STOP] = CreateEventA(NULL, 0, 0, NULL); + info.hevent[EV_STOP] = CreateEventA(NULL, 0, 0, NULL); info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL); info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL); hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid); - Sleep(100); - - trace("signalling to start looping\n"); - SetEvent(info.hevent[EV_START_STOP]); + WaitForSingleObject(info.hevent[EV_ACK], 10000); flush_events(); flush_sequence(); @@ -8574,10 +8909,12 @@ static void test_PeekMessage(void) /* pass invalid QS_xxxx flags */ SetLastError(0xdeadbeef); qstatus = GetQueueStatus(0xffffffff); - ok(qstatus == 0, "GetQueueStatus should fail: %08x\n", qstatus); - ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError()); - - qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == 0 || broken(qstatus) /* win9x */, "GetQueueStatus should fail: %08x\n", qstatus); + if (!qstatus) + { + ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %d\n", GetLastError()); + qstatus = GetQueueStatus(qs_all_input); + } ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE), "wrong qstatus %08x\n", qstatus); @@ -8617,9 +8954,19 @@ static void test_PeekMessage(void) msg.message = 0; ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16)); + if (ret && msg.message == WM_CHAR) + { + win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); + goto done; + } ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); + if (!sequence_cnt) /* nt4 doesn't fetch anything with PM_QS_* flags */ + { + win_skip( "PM_QS_* flags not supported in PeekMessage\n" ); + goto done; + } ok_sequence(WmUser, "WmUser", FALSE); qstatus = GetQueueStatus(qs_all_input); @@ -8635,7 +8982,7 @@ static void test_PeekMessage(void) "wrong qstatus %08x\n", qstatus); msg.message = 0; - ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE); + ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE ); ok(!ret, "PeekMessageA should have returned FALSE instead of msg %04x\n", msg.message); @@ -8861,8 +9208,102 @@ todo_wine { ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); + /* some GetMessage tests */ + + keybd_event('N', 0, 0, 0); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); + + PostMessageA(info.hwnd, WM_CHAR, 'z', 0); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); + + if (qstatus) + { + ret = GetMessageA( &msg, 0, 0, 0 ); + ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', + "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", + ret, msg.message, msg.wParam); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(0, QS_KEY), "wrong qstatus %08x\n", qstatus); + } + + if (qstatus) + { + ret = GetMessageA( &msg, 0, 0, 0 ); + ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', + "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", + ret, msg.message, msg.wParam); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); + } + + keybd_event('N', 0, 0, 0); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); + + PostMessageA(info.hwnd, WM_CHAR, 'z', 0); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); + + if (qstatus & (QS_KEY << 16)) + { + ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); + ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N', + "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", + ret, msg.message, msg.wParam); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); + } + + if (qstatus) + { + ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); + ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', + "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", + ret, msg.message, msg.wParam); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); + } + + keybd_event('N', 0, KEYEVENTF_KEYUP, 0); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(QS_KEY, QS_KEY), "wrong qstatus %08x\n", qstatus); + + PostMessageA(info.hwnd, WM_CHAR, 'z', 0); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY), "wrong qstatus %08x\n", qstatus); + + trace("signalling to send message\n"); + SetEvent(info.hevent[EV_SENDMSG]); + WaitForSingleObject(info.hevent[EV_ACK], INFINITE); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY), + "wrong qstatus %08x\n", qstatus); + + if (qstatus & (QS_KEY << 16)) + { + ret = GetMessageA( &msg, 0, WM_KEYDOWN, WM_KEYUP ); + ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N', + "got %d and %04x wParam %08lx instead of TRUE and WM_KEYDOWN wParam 'N'\n", + ret, msg.message, msg.wParam); + ok_sequence(WmUser, "WmUser", FALSE); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == MAKELONG(0, QS_POSTMESSAGE), "wrong qstatus %08x\n", qstatus); + } + + if (qstatus) + { + ret = GetMessageA( &msg, 0, WM_CHAR, WM_CHAR ); + ok(ret && msg.message == WM_CHAR && msg.wParam == 'z', + "got %d and %04x wParam %08lx instead of TRUE and WM_CHAR wParam 'z'\n", + ret, msg.message, msg.wParam); + qstatus = GetQueueStatus(qs_all_input); + ok(qstatus == 0, "wrong qstatus %08x\n", qstatus); + } +done: trace("signalling to exit\n"); - SetEvent(info.hevent[EV_START_STOP]); + SetEvent(info.hevent[EV_STOP]); WaitForSingleObject(hthread, INFINITE); @@ -8982,6 +9423,7 @@ static void test_quit_message(void) BOOL ret; /* test using PostQuitMessage */ + flush_events(); PostQuitMessage(0xbeef); ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); @@ -9042,8 +9484,8 @@ static void pump_msg_loop_timeout(DWORD timeout, BOOL inject_mouse_move) DWORD start_ticks, end_ticks; start_ticks = GetTickCount(); - /* add some deviation (5%) to cover not expected delays */ - start_ticks += timeout / 20; + /* add some deviation (50%) to cover not expected delays */ + start_ticks += timeout / 2; do { @@ -9123,17 +9565,20 @@ static void test_TrackMouseEvent(void) default_hover_time = 0xdeadbeef; SetLastError(0xdeadbeef); ret = SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &default_hover_time, 0); - ok(ret, "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError()); + ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ + "SystemParametersInfo(SPI_GETMOUSEHOVERTIME) error %u\n", GetLastError()); if (!ret) default_hover_time = 400; trace("SPI_GETMOUSEHOVERTIME returned %u ms\n", default_hover_time); SetLastError(0xdeadbeef); ret = SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0); - ok(ret, "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError()); + ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ + "SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH) error %u\n", GetLastError()); if (!ret) hover_width = 4; SetLastError(0xdeadbeef); ret = SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0); - ok(ret, "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError()); + ok(ret || broken(GetLastError() == 0xdeadbeef), /* win9x */ + "SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT) error %u\n", GetLastError()); if (!ret) hover_height = 4; trace("hover rect is %u x %d\n", hover_width, hover_height); @@ -9149,6 +9594,7 @@ static void test_TrackMouseEvent(void) NULL, NULL, 0); assert(hchild); + SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); flush_events(); flush_sequence(); @@ -9159,7 +9605,8 @@ static void test_TrackMouseEvent(void) SetLastError(0xdeadbeef); ret = pTrackMouseEvent(&tme); ok(!ret, "TrackMouseEvent should fail\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "not expected error %d\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), + "not expected error %u\n", GetLastError()); tme.cbSize = sizeof(tme); tme.dwFlags = TME_HOVER; @@ -9168,7 +9615,8 @@ static void test_TrackMouseEvent(void) SetLastError(0xdeadbeef); ret = pTrackMouseEvent(&tme); ok(!ret, "TrackMouseEvent should fail\n"); - ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "not expected error %d\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), + "not expected error %u\n", GetLastError()); tme.cbSize = sizeof(tme); tme.dwFlags = TME_HOVER | TME_CANCEL; @@ -9177,7 +9625,8 @@ static void test_TrackMouseEvent(void) SetLastError(0xdeadbeef); ret = pTrackMouseEvent(&tme); ok(!ret, "TrackMouseEvent should fail\n"); - ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "not expected error %d\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), + "not expected error %u\n", GetLastError()); GetWindowRect(hwnd, &rc_parent); GetWindowRect(hchild, &rc_child); @@ -9242,9 +9691,9 @@ static void test_TrackMouseEvent(void) static const struct message WmSetWindowRgn[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, - { WM_NCPAINT, sent }, /* wparam != 1 */ + { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|defwinproc|optional }, - { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ + { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } @@ -9259,14 +9708,24 @@ static const struct message WmSetWindowRgn_no_redraw[] = { }; static const struct message WmSetWindowRgn_clear[] = { - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGING, sent/*|wparam*/, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ }, { WM_NCCALCSIZE, sent|wparam, 1 }, - { WM_NCPAINT, sent }, /* wparam != 1 */ + { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, - { WM_NCPAINT, sent|optional }, /* wparam != 1 */ + { WM_NCPAINT, sent|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_NCCALCSIZE, sent|optional|wparam, 1 }, + { WM_NCPAINT, sent|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCCALCSIZE, sent|optional|wparam, 1 }, + { WM_NCPAINT, sent|optional }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, @@ -9422,7 +9881,7 @@ static const struct message WmHide_3[] = { { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, - { HCBT_SETFOCUS, hook }, + { HCBT_SETFOCUS, hook|optional }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { 0 } }; @@ -9448,6 +9907,7 @@ static const struct message WmMinimize_1[] = { }; static const struct message WmMinimize_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, + { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, @@ -9500,15 +9960,17 @@ static const struct message WmShowMaximized_1[] = { static const struct message WmShowMaximized_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, { WM_GETMINMAXINFO, sent }, - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { HCBT_ACTIVATE, hook|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, { WM_MOVE, sent|optional }, /* Win9x doesn't send it */ { WM_SIZE, sent|wparam|optional, SIZE_MAXIMIZED }, /* Win9x doesn't send it */ - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, + { WM_WINDOWPOSCHANGING, sent }, + { HCBT_SETFOCUS, hook|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|wparam|defwinproc, SIZE_MAXIMIZED }, - { HCBT_SETFOCUS, hook }, + { HCBT_SETFOCUS, hook|optional }, { 0 } }; static const struct message WmShowMaximized_3[] = { @@ -9567,7 +10029,7 @@ static void test_ShowWindow(void) /* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE }, /* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, FALSE }, /* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, TRUE }, +/* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, FALSE }, /* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, /* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE }, /* what does this mean?! */ /* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE }, @@ -9656,7 +10118,7 @@ static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPAR WINDOWPOS *winpos = (WINDOWPOS *)lParam; trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); - trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x ", winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); dump_winpos_flags(winpos->flags); @@ -9868,6 +10330,167 @@ static void test_nullCallback(void) DestroyWindow(hwnd); } +/* SetActiveWindow( 0 ) hwnd visible */ +static const struct message SetActiveWindowSeq0[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|defwinproc }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { WM_GETTEXT, sent|optional }, + { 0 } +}; +/* SetActiveWindow( hwnd ) hwnd visible */ +static const struct message SetActiveWindowSeq1[] = +{ + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { 0 } +}; +/* SetActiveWindow( popup ) hwnd visible, popup visible */ +static const struct message SetActiveWindowSeq2[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_NCPAINT, sent|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|defwinproc }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { WM_GETTEXT, sent|optional }, + { 0 } +}; + +/* SetActiveWindow( hwnd ) hwnd not visible */ +static const struct message SetActiveWindowSeq3[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_ACTIVATEAPP, sent|wparam, 1 }, + { WM_ACTIVATEAPP, sent|wparam, 1 }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { 0 } +}; +/* SetActiveWindow( popup ) hwnd not visible, popup not visible */ +static const struct message SetActiveWindowSeq4[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|defwinproc }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { 0 } +}; + + +static void test_SetActiveWindow(void) +{ + HWND hwnd, popup, ret; + + hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + + popup = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", + WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_POPUP, + 100, 100, 200, 200, hwnd, 0, 0, NULL); + + ok(hwnd != 0, "Failed to create overlapped window\n"); + flush_sequence(); + + ok(popup != 0, "Failed to create popup window\n"); + flush_sequence(); + + trace("SetActiveWindow(0)\n"); + ret = SetActiveWindow(0); + ok( ret == popup, "Failed to SetActiveWindow(0)\n"); + ok_sequence(SetActiveWindowSeq0, "SetActiveWindow(0)", TRUE); + flush_sequence(); + + trace("SetActiveWindow(hwnd), hwnd visible\n"); + ret = SetActiveWindow(hwnd); + todo_wine + { + ok( ret == hwnd, "Failed to SetActiveWindow(hwnd), hwnd visible\n"); + } + ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE); + flush_sequence(); + + trace("SetActiveWindow(popup), hwnd visible, popup visible\n"); + ret = SetActiveWindow(popup); + ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visible\n"); + ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visible", FALSE); + flush_sequence(); + + ShowWindow(hwnd, SW_HIDE); + ShowWindow(popup, SW_HIDE); + flush_sequence(); + + trace("SetActiveWindow(hwnd), hwnd not visible\n"); + ret = SetActiveWindow(hwnd); + ok( ret == NULL, "Failed to SetActiveWindow(hwnd), hwnd not visible\n"); + ok_sequence(SetActiveWindowSeq3, "SetActiveWindow(hwnd), hwnd not visible", TRUE); + flush_sequence(); + + trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n"); + ret = SetActiveWindow(popup); + ok( ret == hwnd, "Failed to SetActiveWindow(popup)\n"); + ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE); + flush_sequence(); + + trace("done\n"); + + DestroyWindow(hwnd); +} + static const struct message SetForegroundWindowSeq[] = { { WM_NCACTIVATE, sent|wparam, 0 }, @@ -10224,7 +10847,7 @@ static const struct message wm_lb_click_0[] = { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|wparam|optional|parent, 0 }, - { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, @@ -10365,6 +10988,315 @@ static void test_listbox_messages(void) DestroyWindow(parent); } +/*************************** Menu test ******************************/ +static const struct message wm_popup_menu_1[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'E', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'e', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'e' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(1,MF_HILITE|MF_POPUP) }, + { WM_INITMENUPOPUP, sent|lparam, 0, 1 }, + { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't create a window */ + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(200,MF_HILITE) }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'E', 0xf0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, + { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't create a window */ + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_MENUCOMMAND, sent }, /* |wparam, 200 - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, + { 0 } +}; +static const struct message wm_popup_menu_2[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, + { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ + { HCBT_CREATEWND, hook }, + { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP + |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ + { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, + { HCBT_DESTROYWND, hook }, + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_MENUCOMMAND, sent }, /* |wparam, 100 - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, + { 0 } +}; +static const struct message wm_popup_menu_3[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'F', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'f', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'f' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, + { WM_INITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(0,MF_HILITE|MF_POPUP) }, /* Win9x */ + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x */ + { HCBT_CREATEWND, hook }, + { WM_MENUSELECT, sent }, /*|wparam, MAKEWPARAM(0,MF_HILITE|MF_POPUP) - XP + |wparam, MAKEWPARAM(100,MF_HILITE) - Win9x */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'F', 0xf0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0x10000001 }, + { WM_INITMENUPOPUP, sent|lparam|optional, 0, 0 }, /* Win9x doesn't send it */ + { HCBT_CREATEWND, hook|optional }, /* Win9x doesn't send it */ + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(100,MF_HILITE) }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RIGHT, 0xd0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0x10000001 }, + { HCBT_DESTROYWND, hook }, + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { HCBT_DESTROYWND, hook|optional }, /* Win9x doesn't send it */ + { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_COMMAND, sent|wparam|lparam, 100, 0 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_RETURN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_RETURN, 0xc0000001 }, + { 0 } +}; + +static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) +{ + if (message == WM_ENTERIDLE || + message == WM_INITMENU || + message == WM_INITMENUPOPUP || + message == WM_MENUSELECT || + message == WM_PARENTNOTIFY || + message == WM_ENTERMENULOOP || + message == WM_EXITMENULOOP || + message == WM_UNINITMENUPOPUP || + message == WM_KEYDOWN || + message == WM_KEYUP || + message == WM_CHAR || + message == WM_SYSKEYDOWN || + message == WM_SYSKEYUP || + message == WM_SYSCHAR || + message == WM_COMMAND || + message == WM_MENUCOMMAND) + { + struct message msg; + + trace("parent_menu_proc: %p, %04x, %08lx, %08lx\n", hwnd, message, wp, lp); + + msg.message = message; + msg.flags = sent|wparam|lparam; + msg.wParam = wp; + msg.lParam = lp; + add_message(&msg); + } + + return DefWindowProcA(hwnd, message, wp, lp); +} + +static void set_menu_style(HMENU hmenu, DWORD style) +{ + MENUINFO mi; + BOOL ret; + + mi.cbSize = sizeof(mi); + mi.fMask = MIM_STYLE; + mi.dwStyle = style; + SetLastError(0xdeadbeef); + ret = pSetMenuInfo(hmenu, &mi); + ok(ret, "SetMenuInfo error %u\n", GetLastError()); +} + +static DWORD get_menu_style(HMENU hmenu) +{ + MENUINFO mi; + BOOL ret; + + mi.cbSize = sizeof(mi); + mi.fMask = MIM_STYLE; + mi.dwStyle = 0; + SetLastError(0xdeadbeef); + ret = pGetMenuInfo(hmenu, &mi); + ok(ret, "GetMenuInfo error %u\n", GetLastError()); + + return mi.dwStyle; +} + +static void test_menu_messages(void) +{ + MSG msg; + WNDCLASSA cls; + HMENU hmenu, hmenu_popup; + HWND hwnd; + DWORD style; + + if (!pGetMenuInfo || !pSetMenuInfo) + { + skip("GetMenuInfo and/or SetMenuInfo are not available\n"); + return; + } + cls.style = 0; + cls.lpfnWndProc = parent_menu_proc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "TestMenuClass"; + UnregisterClass(cls.lpszClassName, cls.hInstance); + if (!RegisterClassA(&cls)) assert(0); + + SetLastError(0xdeadbeef); + hwnd = CreateWindowExA(0, "TestMenuClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(hwnd != 0, "LoadMenuA error %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + hmenu = LoadMenuA(GetModuleHandle(0), MAKEINTRESOURCE(1)); + ok(hmenu != 0, "LoadMenuA error %u\n", GetLastError()); + + SetMenu(hwnd, hmenu); + SetForegroundWindow( hwnd ); + + set_menu_style(hmenu, MNS_NOTIFYBYPOS); + style = get_menu_style(hmenu); + ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + style = get_menu_style(hmenu_popup); + ok(style == 0, "expected 0, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu_popup, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + style = get_menu_style(hmenu_popup); + ok(style == 0, "expected 0, got %u\n", style); + + /* Alt+E, Enter */ + trace("testing a popup menu command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('E', 0, 0, 0); + keybd_event('E', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RETURN, 0, 0, 0); + keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_popup_menu_1, "popup menu command", FALSE); + + /* Alt+F, Right, Enter */ + trace("testing submenu of a popup menu command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('F', 0, 0, 0); + keybd_event('F', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RIGHT, 0, 0, 0); + keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RETURN, 0, 0, 0); + keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE); + + set_menu_style(hmenu, 0); + style = get_menu_style(hmenu); + ok(style == 0, "expected 0, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + set_menu_style(hmenu_popup, MNS_NOTIFYBYPOS); + style = get_menu_style(hmenu_popup); + ok(style == MNS_NOTIFYBYPOS, "expected MNS_NOTIFYBYPOS, got %u\n", style); + + hmenu_popup = GetSubMenu(hmenu_popup, 0); + ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); + style = get_menu_style(hmenu_popup); + ok(style == 0, "expected 0, got %u\n", style); + + /* Alt+F, Right, Enter */ + trace("testing submenu of a popup menu command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('F', 0, 0, 0); + keybd_event('F', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RIGHT, 0, 0, 0); + keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_RETURN, 0, 0, 0); + keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_popup_menu_3, "submenu of a popup menu command", FALSE); + + DestroyWindow(hwnd); + DestroyMenu(hmenu); +} + + +static void test_paintingloop(void) +{ + HWND hwnd; + + paint_loop_done = 0; + hwnd = CreateWindowExA(0x0,"PaintLoopWindowClass", + "PaintLoopWindowClass",WS_OVERLAPPEDWINDOW, + 100, 100, 100, 100, 0, 0, 0, NULL ); + ok(hwnd != 0, "PaintLoop window error %u\n", GetLastError()); + ShowWindow(hwnd,SW_NORMAL); + SetFocus(hwnd); + + while (!paint_loop_done) + { + MSG msg; + if (PeekMessageA(&msg, 0, 0, 0, 1)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + DestroyWindow(hwnd); +} + START_TEST(msg) { BOOL ret; @@ -10414,6 +11346,7 @@ START_TEST(msg) test_PeekMessage2(); test_scrollwindowex(); test_messages(); + test_setwindowpos(); test_showwindow(); invisible_parent_tests(); test_mdi_messages(); @@ -10434,6 +11367,7 @@ START_TEST(msg) test_SendMessageTimeout(); test_edit_messages(); test_quit_message(); + test_SetActiveWindow(); if (!pTrackMouseEvent) skip("TrackMouseEvent is not available\n"); @@ -10444,8 +11378,13 @@ START_TEST(msg) test_sys_menu(); test_dialog_messages(); test_nullCallback(); - test_SetForegroundWindow(); test_dbcs_wm_char(); + test_menu_messages(); + test_paintingloop(); + /* keep it the last test, under Windows it tends to break the tests + * which rely on active/foreground windows being correct. + */ + test_SetForegroundWindow(); UnhookWindowsHookEx(hCBT_hook); if (pUnhookWinEvent) diff --git a/rostests/winetests/user32/resource.c b/rostests/winetests/user32/resource.c index a8b6c08f3f6..b8e04932098 100755 --- a/rostests/winetests/user32/resource.c +++ b/rostests/winetests/user32/resource.c @@ -40,7 +40,16 @@ static void test_LoadStringW(void) /* Check that the string which is returned by LoadStringW matches the string at the pointer returned by LoadStringW when called with buflen = 0 */ + SetLastError(0xdeadbeef); length1 = LoadStringW(hInst, 2, (WCHAR *) &resourcepointer, 0); /* get pointer to resource. */ + if (!length1) + { + if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + win_skip( "LoadStringW not implemented\n" ); + else + win_skip( "LoadStringW does not return a pointer to the resource\n" ); + return; + } length2 = LoadStringW(hInst, 2, returnedstringw, sizeof(returnedstringw) /sizeof(WCHAR)); /* get resource string */ ok(length2 > 0, "LoadStringW failed to load resource 2, ret %d, err %d\n", length2, GetLastError()); ok(length1 == length2, "LoadStringW returned different values dependent on buflen. ret1 %d, ret2 %d\n", @@ -114,7 +123,8 @@ static void test_LoadStringA (void) "LoadString failed: ret %d err %d\n", ret, GetLastError()); ret = LoadStringA(hInst, 0, buf, 0); - ok( ret == -1, "LoadStringA did not return -1 when called with buflen = 0, got %d, err %d\n", + ok( ret == -1 || broken(ret == 0), + "LoadStringA did not return -1 when called with buflen = 0, got %d, err %d\n", ret, GetLastError()); } @@ -170,41 +180,43 @@ static void test_accel1(void) ok( hAccel != NULL, "create accelerator table\n"); r = CopyAcceleratorTable( hAccel, NULL, 0 ); - ok( r == n, "two entries in table\n"); + ok( r == n || broken(r == 2), /* win9x */ + "two entries in table %u/%u\n", r, n); - r = CopyAcceleratorTable( hAccel, &ac[0], r ); - ok( r == n, "still should be two entries in table\n"); + r = CopyAcceleratorTable( hAccel, &ac[0], n ); + ok( r == n || broken(r == 2), /* win9x */ + "still should be two entries in table %u/%u\n", r, n); n=0; ok( ac[n].cmd == 1000, "cmd 0 not preserved\n"); ok( ac[n].key == 'A', "key 0 not preserved\n"); ok( ac[n].fVirt == (FVIRTKEY | FNOINVERT), "fVirt 0 not preserved\n"); - n++; + if (++n == r) goto done; ok( ac[n].cmd == 0xffff, "cmd 1 not preserved\n"); ok( ac[n].key == 0xffff, "key 1 not preserved\n"); ok( ac[n].fVirt == 0x007f, "fVirt 1 not changed\n"); - n++; + if (++n == r) goto done; ok( ac[n].cmd == 0xfff0, "cmd 2 not preserved\n"); ok( ac[n].key == 0x00ff, "key 2 not preserved\n"); ok( ac[n].fVirt == 0x0070, "fVirt 2 not changed\n"); - n++; + if (++n == r) goto done; ok( ac[n].cmd == 0xfff0, "cmd 3 not preserved\n"); ok( ac[n].key == 0x00ff, "key 3 not preserved\n"); ok( ac[n].fVirt == 0x0000, "fVirt 3 not changed\n"); - n++; + if (++n == r) goto done; ok( ac[n].cmd == 0xfff0, "cmd 4 not preserved\n"); ok( ac[n].key == 0xffff, "key 4 not preserved\n"); ok( ac[n].fVirt == 0x0001, "fVirt 4 not changed\n"); - +done: r = DestroyAcceleratorTable( hAccel ); ok( r, "destroy accelerator table\n"); hAccel = CreateAcceleratorTable( &ac[0], 0 ); - ok( !hAccel, "zero elements should fail\n"); + ok( !hAccel || broken(hAccel != NULL), /* nt4 */ "zero elements should fail\n"); /* these will on crash win2k hAccel = CreateAcceleratorTable( NULL, 1 ); @@ -220,6 +232,7 @@ static void test_accel2(void) { ACCEL ac[2], out[2]; HACCEL hac; + int res; ac[0].cmd = 0; ac[0].fVirt = 0; @@ -236,8 +249,8 @@ static void test_accel2(void) /* try a zero count */ hac = CreateAcceleratorTable( &ac[0], 0 ); - ok( !hac , "fail\n"); - ok( !DestroyAcceleratorTable( hac ), "destroy failed\n"); + ok( !hac || broken(hac != NULL), /* nt4 */ "fail\n"); + if (!hac) ok( !DestroyAcceleratorTable( hac ), "destroy failed\n"); /* creating one accelerator should work */ hac = CreateAcceleratorTable( &ac[0], 1 ); @@ -248,9 +261,12 @@ static void test_accel2(void) /* how about two of the same type? */ hac = CreateAcceleratorTable( &ac[0], 2); ok( hac != NULL , "fail\n"); - ok( 2 == CopyAcceleratorTable( hac, NULL, 100 ), "copy null failed\n"); - ok( 2 == CopyAcceleratorTable( hac, NULL, 0 ), "copy null failed\n"); - ok( 2 == CopyAcceleratorTable( hac, NULL, 1 ), "copy null failed\n"); + res = CopyAcceleratorTable( hac, NULL, 100 ); + ok( res == 2 || broken(res == 0), /* win9x */ "copy null failed %d\n", res); + res = CopyAcceleratorTable( hac, NULL, 0 ); + ok( res == 2, "copy null failed %d\n", res); + res = CopyAcceleratorTable( hac, NULL, 1 ); + ok( res == 2 || broken(res == 0), /* win9x */ "copy null failed %d\n", res); ok( 1 == CopyAcceleratorTable( hac, out, 1 ), "copy 1 failed\n"); ok( 2 == CopyAcceleratorTable( hac, out, 2 ), "copy 2 failed\n"); ok( DestroyAcceleratorTable( hac ), "destroy failed\n"); @@ -301,14 +317,18 @@ static void test_accel2(void) memset( ac, 0xff, sizeof ac ); hac = CreateAcceleratorTable( &ac[0], 2); ok( hac != NULL , "fail\n"); - ok( 2 == CopyAcceleratorTable( hac, out, 2 ), "copy 2 failed\n"); + res = CopyAcceleratorTable( hac, out, 2 ); + ok( res == 2 || broken(res == 1), /* win9x */ "copy 2 failed %d\n", res); /* ok( memcmp( ac, out, sizeof ac ), "tables not different\n"); */ ok( out[0].cmd == ac[0].cmd, "cmd modified\n"); ok( out[0].fVirt == (ac[0].fVirt&0x7f), "fVirt not modified\n"); ok( out[0].key == ac[0].key, "key modified\n"); - ok( out[1].cmd == ac[1].cmd, "cmd modified\n"); - ok( out[1].fVirt == (ac[1].fVirt&0x7f), "fVirt not modified\n"); - ok( out[1].key == ac[1].key, "key modified\n"); + if (res == 2) + { + ok( out[1].cmd == ac[1].cmd, "cmd modified\n"); + ok( out[1].fVirt == (ac[1].fVirt&0x7f), "fVirt not modified\n"); + ok( out[1].key == ac[1].key, "key modified\n"); + } ok( DestroyAcceleratorTable( hac ), "destroy failed\n"); } @@ -333,9 +353,13 @@ static void test_PrivateExtractIcons(void) { cIcons = pPrivateExtractIconsA(szShell32Dll, 0, 16, 16, ahIcon, aIconId, 3, 0); ok(cIcons == 3, "Three icons requested got cIcons=%d\n", cIcons); - cIcons = pPrivateExtractIconsA(szShell32Dll, 0, MAKELONG(32,16), MAKELONG(32,16), - ahIcon, aIconId, 3, 0); - ok(cIcons == 4, "Three icons requested, four expected, got cIcons=%d\n", cIcons); + /* count must be a multiple of two when getting two sizes */ + cIcons = pPrivateExtractIconsA(szShell32Dll, 0, MAKELONG(16,32), MAKELONG(16,32), + ahIcon, aIconId, 3, 0); + ok(cIcons == 0 /* vista */ || cIcons == 4, "Three icons requested got cIcons=%d\n", cIcons); + cIcons = pPrivateExtractIconsA(szShell32Dll, 0, MAKELONG(16,32), MAKELONG(16,32), + ahIcon, aIconId, 4, 0); + ok(cIcons == 4, "Four icons requested got cIcons=%d\n", cIcons); } static void test_LoadImage(void) diff --git a/rostests/winetests/user32/resource.rc b/rostests/winetests/user32/resource.rc index 7da8a6c2d79..79c036cbdb0 100755 --- a/rostests/winetests/user32/resource.rc +++ b/rostests/winetests/user32/resource.rc @@ -165,13 +165,16 @@ FONT 8, "MS Shell Dlg" { POPUP "&File" { - MENUITEM "&New", 100 + POPUP "&New..." + { + MENUITEM "&New file", 100 + } MENUITEM "&Open", 101 MENUITEM "&Save", 102 MENUITEM SEPARATOR MENUITEM "E&xit", 103 } - POPUP "Edit" + POPUP "&Edit" { MENUITEM "&Undo", 200 MENUITEM SEPARATOR diff --git a/rostests/winetests/user32/scroll.c b/rostests/winetests/user32/scroll.c index 3bc407a8641..9547d543082 100644 --- a/rostests/winetests/user32/scroll.c +++ b/rostests/winetests/user32/scroll.c @@ -127,6 +127,74 @@ static void scrollbar_test3(void) } +static void scrollbar_test4(void) +{ + BOOL ret; + SCROLLBARINFO sbi; + RECT rect; + BOOL (WINAPI *pGetScrollBarInfo)(HWND, LONG, LPSCROLLBARINFO); + + pGetScrollBarInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetScrollBarInfo"); + if (!pGetScrollBarInfo) + { + win_skip("GetScrollBarInfo is not available\n"); + return; + } + + /* Test GetScrollBarInfo to make sure it returns rcScrollBar in screen + * coordinates. */ + sbi.cbSize = sizeof(sbi); + ret = pGetScrollBarInfo( hScroll, OBJID_CLIENT, &sbi); + ok( ret, "The GetScrollBarInfo() call should not fail.\n" ); + GetWindowRect( hScroll, &rect ); + ok( ret, "The GetWindowRect() call should not fail.\n" ); + ok( !(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)), + "unexpected rgstate(0x%x)\n", sbi.rgstate[0]); + ok( EqualRect(&rect, &sbi.rcScrollBar), + "WindowRect(%d, %d, %d, %d) != rcScrollBar(%d, %d, %d, %d)\n", + rect.top, rect.left, rect.bottom, rect.right, + sbi.rcScrollBar.top, sbi.rcScrollBar.left, + sbi.rcScrollBar.bottom, sbi.rcScrollBar.right ); + + /* Test windows horizontal and vertical scrollbar to make sure rcScrollBar + * is still returned in screen coordinates by moving the window, and + * making sure that it shifts the rcScrollBar value. */ + ShowWindow( hMainWnd, SW_SHOW ); + sbi.cbSize = sizeof(sbi); + ret = pGetScrollBarInfo( hMainWnd, OBJID_HSCROLL, &sbi); + ok( ret, "The GetScrollBarInfo() call should not fail.\n" ); + GetWindowRect( hMainWnd, &rect ); + ok( ret, "The GetWindowRect() call should not fail.\n" ); + MoveWindow( hMainWnd, rect.left+5, rect.top+5, + rect.right-rect.left, rect.bottom-rect.top, TRUE ); + rect = sbi.rcScrollBar; + OffsetRect(&rect, 5, 5); + ret = pGetScrollBarInfo( hMainWnd, OBJID_HSCROLL, &sbi); + ok( ret, "The GetScrollBarInfo() call should not fail.\n" ); + ok( EqualRect(&rect, &sbi.rcScrollBar), + "PreviousRect(%d, %d, %d, %d) != CurrentRect(%d, %d, %d, %d)\n", + rect.top, rect.left, rect.bottom, rect.right, + sbi.rcScrollBar.top, sbi.rcScrollBar.left, + sbi.rcScrollBar.bottom, sbi.rcScrollBar.right ); + + sbi.cbSize = sizeof(sbi); + ret = pGetScrollBarInfo( hMainWnd, OBJID_VSCROLL, &sbi); + ok( ret, "The GetScrollBarInfo() call should not fail.\n" ); + GetWindowRect( hMainWnd, &rect ); + ok( ret, "The GetWindowRect() call should not fail.\n" ); + MoveWindow( hMainWnd, rect.left+5, rect.top+5, + rect.right-rect.left, rect.bottom-rect.top, TRUE ); + rect = sbi.rcScrollBar; + OffsetRect(&rect, 5, 5); + ret = pGetScrollBarInfo( hMainWnd, OBJID_VSCROLL, &sbi); + ok( ret, "The GetScrollBarInfo() call should not fail.\n" ); + ok( EqualRect(&rect, &sbi.rcScrollBar), + "PreviousRect(%d, %d, %d, %d) != CurrentRect(%d, %d, %d, %d)\n", + rect.top, rect.left, rect.bottom, rect.right, + sbi.rcScrollBar.top, sbi.rcScrollBar.left, + sbi.rcScrollBar.bottom, sbi.rcScrollBar.right ); +} + START_TEST ( scroll ) { WNDCLASSA wc; @@ -143,7 +211,8 @@ START_TEST ( scroll ) wc.lpfnWndProc = MyWndProc; RegisterClassA(&wc); - hMainWnd = CreateWindowExA( 0, "MyTestWnd", "Scroll", WS_OVERLAPPEDWINDOW, + hMainWnd = CreateWindowExA( 0, "MyTestWnd", "Scroll", + WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0 ); if ( !ok( hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n" ) ) @@ -154,6 +223,7 @@ START_TEST ( scroll ) scrollbar_test1(); scrollbar_test2(); scrollbar_test3(); + scrollbar_test4(); DestroyWindow(hScroll); DestroyWindow(hMainWnd); diff --git a/rostests/winetests/user32/static.c b/rostests/winetests/user32/static.c index 7810db4e399..6a474ff5903 100644 --- a/rostests/winetests/user32/static.c +++ b/rostests/winetests/user32/static.c @@ -33,12 +33,12 @@ static HWND hMainWnd; -#define expect_eq(expr, value, type, fmt) { type val = expr; ok(val == (value), #expr " expected " #fmt " got " #fmt "\n", (value), val); } +#define expect_eq(expr, value, type, fmt) { type val = expr; ok(val == (value), #expr " expected " fmt " got " fmt "\n", (value), val); } #define expect_rect(r, _left, _top, _right, _bottom) ok(r.left == _left && r.top == _top && \ r.bottom == _bottom && r.right == _right, "Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", \ r.left, r.top, r.right, r.bottom, _left, _top, _right, _bottom); -int g_nReceivedColorStatic = 0; +static int g_nReceivedColorStatic = 0; static HWND build_static(DWORD style) { @@ -63,7 +63,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara return DefWindowProc(hwnd, msg, wparam, lparam); } -void test_updates(int style, int flags) +static void test_updates(int style, int flags) { RECT r1 = {20, 20, 30, 30}; HWND hStatic = build_static(style); @@ -89,6 +89,10 @@ void test_updates(int style, int flags) if (flags & TODO_COUNT) todo_wine { expect_eq(g_nReceivedColorStatic, exp, int, "%d"); } + else if (style == SS_ICON || style == SS_BITMAP) + ok( g_nReceivedColorStatic == exp || + broken(g_nReceivedColorStatic == 0), /* win9x */ + "expected %u got %u\n", exp, g_nReceivedColorStatic ); else expect_eq(g_nReceivedColorStatic, exp, int, "%d"); DestroyWindow(hStatic); @@ -108,7 +112,7 @@ START_TEST(static) wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); - wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wndclass.hbrBackground = GetStockObject(WHITE_BRUSH); wndclass.lpszClassName = szClassName; wndclass.lpszMenuName = NULL; RegisterClassEx(&wndclass); diff --git a/rostests/winetests/user32/sysparams.c b/rostests/winetests/user32/sysparams.c index 8e95ffd7da3..d6135657c45 100755 --- a/rostests/winetests/user32/sysparams.c +++ b/rostests/winetests/user32/sysparams.c @@ -22,8 +22,7 @@ #include #include -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 /* For SPI_GETMOUSEHOVERWIDTH and more */ +#define SPI_SETWHEELSCROLLCHARS 109 #include "wine/test.h" #include "windef.h" @@ -129,12 +128,16 @@ static HDC hdc; #define SPI_SETPOWEROFFACTIVE_VALNAME "PowerOffActive" #define SPI_SETDRAGFULLWINDOWS_REGKEY "Control Panel\\Desktop" #define SPI_SETDRAGFULLWINDOWS_VALNAME "DragFullWindows" +#define SPI_SETSNAPTODEFBUTTON_REGKEY "Control Panel\\Mouse" +#define SPI_SETSNAPTODEFBUTTON_VALNAME "SnapToDefaultButton" #define SPI_SETMOUSEHOVERWIDTH_REGKEY "Control Panel\\Mouse" #define SPI_SETMOUSEHOVERWIDTH_VALNAME "MouseHoverWidth" #define SPI_SETMOUSEHOVERHEIGHT_REGKEY "Control Panel\\Mouse" #define SPI_SETMOUSEHOVERHEIGHT_VALNAME "MouseHoverHeight" #define SPI_SETMOUSEHOVERTIME_REGKEY "Control Panel\\Mouse" #define SPI_SETMOUSEHOVERTIME_VALNAME "MouseHoverTime" +#define SPI_SETMOUSESCROLLCHARS_REGKEY "Control Panel\\Desktop" +#define SPI_SETMOUSESCROLLCHARS_VALNAME "WheelScrollChars" #define SPI_SETMOUSESCROLLLINES_REGKEY "Control Panel\\Desktop" #define SPI_SETMOUSESCROLLLINES_VALNAME "WheelScrollLines" #define SPI_SETMENUSHOWDELAY_REGKEY "Control Panel\\Desktop" @@ -219,7 +222,7 @@ static BOOL test_error_msg ( int rc, const char *name ) if (rc==0) { - if (last_error==0xdeadbeef || last_error==ERROR_INVALID_SPI_VALUE) + if (last_error==0xdeadbeef || last_error==ERROR_INVALID_SPI_VALUE || last_error==ERROR_INVALID_PARAMETER) { trace("%s not supported on this platform. Skipping test\n", name); } @@ -1773,7 +1776,7 @@ static void test_SPI_SETSHOWSOUNDS( void ) /* 57 */ rc=SystemParametersInfoA( SPI_SETSHOWSOUNDS, vals[i], 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ); ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError()); - test_change_message( SPI_SETSHOWSOUNDS, 0 ); + test_change_message( SPI_SETSHOWSOUNDS, 1 ); test_reg_key( SPI_SETSHOWSOUNDS_REGKEY, SPI_SETSHOWSOUNDS_VALNAME, vals[i] ? "1" : "0" ); @@ -1809,7 +1812,7 @@ static void test_SPI_SETKEYBOARDPREF( void ) /* 69 */ rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, vals[i], 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ); ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError()); - test_change_message( SPI_SETKEYBOARDPREF, 0 ); + test_change_message( SPI_SETKEYBOARDPREF, 1 ); test_reg_key_ex2( SPI_SETKEYBOARDPREF_REGKEY, SPI_SETKEYBOARDPREF_REGKEY_LEGACY, SPI_SETKEYBOARDPREF_VALNAME, SPI_SETKEYBOARDPREF_VALNAME_LEGACY, vals[i] ? "1" : "0" ); @@ -1843,7 +1846,7 @@ static void test_SPI_SETSCREENREADER( void ) /* 71 */ rc=SystemParametersInfoA( SPI_SETSCREENREADER, vals[i], 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ); ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError()); - test_change_message( SPI_SETSCREENREADER, 0 ); + test_change_message( SPI_SETSCREENREADER, 1 ); test_reg_key_ex2( SPI_SETSCREENREADER_REGKEY, SPI_SETSCREENREADER_REGKEY_LEGACY, SPI_SETSCREENREADER_VALNAME, SPI_SETSCREENREADER_VALNAME_LEGACY, vals[i] ? "1" : "0" ); @@ -1912,14 +1915,17 @@ static void test_SPI_SETLOWPOWERACTIVE( void ) /* 85 */ rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, vals[i], 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ); ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError()); - test_change_message( SPI_SETLOWPOWERACTIVE, 0 ); + test_change_message( SPI_SETLOWPOWERACTIVE, 1 ); test_reg_key( SPI_SETLOWPOWERACTIVE_REGKEY, SPI_SETLOWPOWERACTIVE_VALNAME, vals[i] ? "1" : "0" ); + /* SPI_SETLOWPOWERACTIVE is not persistent in win2k3 and above */ rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 ); ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError()); - eq( v, vals[i], "SPI_GETLOWPOWERACTIVE", "%d" ); + ok(v == vals[i] || + v == 0, /* win2k3 */ + "SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]); } rc=SystemParametersInfoA( SPI_SETLOWPOWERACTIVE, old_b, 0, SPIF_UPDATEINIFILE ); @@ -1946,20 +1952,57 @@ static void test_SPI_SETPOWEROFFACTIVE( void ) /* 86 */ rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, vals[i], 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ); ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError()); - test_change_message( SPI_SETPOWEROFFACTIVE, 0 ); + test_change_message( SPI_SETPOWEROFFACTIVE, 1 ); test_reg_key( SPI_SETPOWEROFFACTIVE_REGKEY, SPI_SETPOWEROFFACTIVE_VALNAME, vals[i] ? "1" : "0" ); + /* SPI_SETPOWEROFFACTIVE is not persistent in win2k3 and above */ rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 ); ok(rc!=0,"%d: rc=%d err=%d\n",i,rc,GetLastError()); - eq( v, vals[i], "SPI_GETPOWEROFFACTIVE", "%d" ); + ok(v == vals[i] || + v == 0, /* win2k3 */ + "SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]); } rc=SystemParametersInfoA( SPI_SETPOWEROFFACTIVE, old_b, 0, SPIF_UPDATEINIFILE ); ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError()); } +static void test_SPI_SETSNAPTODEFBUTTON( void ) /* 95 */ +{ + BOOL rc; + BOOL old_b; + const UINT vals[]={TRUE,FALSE}; + unsigned int i; + + trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n"); + SetLastError(0xdeadbeef); + rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 ); + if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON")) + return; + + for (i=0;i #include @@ -46,6 +45,11 @@ void dump_region(HRGN hrgn); static HWND (WINAPI *pGetAncestor)(HWND,UINT); static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*); +static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT); +static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*); +static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD); +static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); +static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); static BOOL test_lbuttondown_flag; static HWND hwndMessage; @@ -58,6 +62,16 @@ static DWORD our_pid; #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0])) +static void dump_minmax_info( const MINMAXINFO *minmax ) +{ + trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n", + minmax->ptReserved.x, minmax->ptReserved.y, + minmax->ptMaxSize.x, minmax->ptMaxSize.y, + minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, + minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, + minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); +} + /* try to make sure pending X events have been processed before continuing */ static void flush_events( BOOL remove_messages ) { @@ -141,8 +155,10 @@ static void test_parent_owner(void) SetLastError(0xdeadbeef); test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL ); - ok( GetLastError() == ERROR_TLW_WITH_WSCHILD, "CreateWindowExA should call SetLastError\n" ); ok( !test, "WS_CHILD without parent created\n" ); + ok( GetLastError() == ERROR_TLW_WITH_WSCHILD || + broken(GetLastError() == 0xdeadbeef), /* win9x */ + "CreateWindowExA error %u\n", GetLastError() ); /* desktop window */ check_parents( desktop, 0, 0, 0, 0, 0, 0 ); @@ -551,13 +567,7 @@ static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPAR MINMAXINFO* minmax = (MINMAXINFO *)lparam; trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam); - trace("ptReserved (%d,%d), ptMaxSize (%d,%d), ptMaxPosition (%d,%d)\n" - " ptMinTrackSize (%d,%d), ptMaxTrackSize (%d,%d)\n", - minmax->ptReserved.x, minmax->ptReserved.y, - minmax->ptMaxSize.x, minmax->ptMaxSize.y, - minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, - minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, - minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + dump_minmax_info( minmax ); SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021); break; } @@ -651,13 +661,7 @@ static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPAR MINMAXINFO* minmax = (MINMAXINFO *)lparam; trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam); - trace("ptReserved (%d,%d), ptMaxSize (%d,%d), ptMaxPosition (%d,%d)\n" - " ptMinTrackSize (%d,%d), ptMaxTrackSize (%d,%d)\n", - minmax->ptReserved.x, minmax->ptReserved.y, - minmax->ptMaxSize.x, minmax->ptMaxSize.y, - minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, - minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, - minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + dump_minmax_info( minmax ); SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021); break; } @@ -731,17 +735,15 @@ static void verify_window_info(HWND hwnd, const WINDOWINFO *info) ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE), "wrong dwStyle: %08x != %08x\n", info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE)); - /* Windows reports a not documented exstyle 0x800 in WINDOWINFO, but - * doesn't return it in GetWindowLong(hwnd, GWL_EXSTYLE). + /* Windows reports some undocumented exstyles in WINDOWINFO, but + * doesn't return them in GetWindowLong(hwnd, GWL_EXSTYLE). */ - ok((info->dwExStyle & ~0x800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE), + ok((info->dwExStyle & ~0xe0000800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE), "wrong dwExStyle: %08x != %08x\n", info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE)); status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0; - ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x\n", - info->dwWindowStatus, status); - - trace("rcWindow: %d,%d - %d,%d\n", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom); - trace("rcClient: %d,%d - %d,%d\n", rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); + if (GetForegroundWindow()) + ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x active %p fg %p\n", + info->dwWindowStatus, status, GetActiveWindow(), GetForegroundWindow()); /* win2k and XP return broken border info in GetWindowInfo most of * the time, so there is no point in testing it. @@ -781,6 +783,7 @@ static void test_nonclient_area(HWND hwnd) RECT rc_window, rc_client, rc; BOOL menu; BOOL is_win9x = GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == 0; + LRESULT ret; style = GetWindowLongA(hwnd, GWL_STYLE); exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); @@ -809,6 +812,10 @@ static void test_nonclient_area(HWND hwnd) trace("calc client: (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); ok(EqualRect(&rc, &rc_client), "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d\n", style, exstyle, menu); + /* NULL rectangle shouldn't crash */ + ret = DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, 0); + ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret); + /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */; if (is_win9x) return; @@ -963,12 +970,14 @@ static void test_shell_window(void) DWORD pid; HANDLE hProcess; + SetLastError(0xdeadbeef); ret = DestroyWindow(shellWindow); error = GetLastError(); ok(!ret, "DestroyWindow(shellWindow)\n"); /* passes on Win XP, but not on Win98 */ - ok(error==ERROR_ACCESS_DENIED, "ERROR_ACCESS_DENIED after DestroyWindow(shellWindow)\n"); + ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef, + "got %u after DestroyWindow(shellWindow)\n", error); /* close old shell instance */ GetWindowThreadProcessId(shellWindow, &pid); @@ -1421,17 +1430,7 @@ static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, L style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ AdjustWindowRectEx(&rc, style, 0, exstyle); trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top); - - trace("ptReserved = (%d,%d)\n" - "ptMaxSize = (%d,%d)\n" - "ptMaxPosition = (%d,%d)\n" - "ptMinTrackSize = (%d,%d)\n" - "ptMaxTrackSize = (%d,%d)\n", - minmax->ptReserved.x, minmax->ptReserved.y, - minmax->ptMaxSize.x, minmax->ptMaxSize.y, - minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, - minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, - minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + dump_minmax_info( minmax ); ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n", minmax->ptMaxSize.x, rc.right - rc.left); @@ -1440,17 +1439,8 @@ static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, L DefMDIChildProcA(hwnd, msg, wparam, lparam); - trace("DefMDIChildProc returned:\n" - "ptReserved = (%d,%d)\n" - "ptMaxSize = (%d,%d)\n" - "ptMaxPosition = (%d,%d)\n" - "ptMinTrackSize = (%d,%d)\n" - "ptMaxTrackSize = (%d,%d)\n", - minmax->ptReserved.x, minmax->ptReserved.y, - minmax->ptMaxSize.x, minmax->ptMaxSize.y, - minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, - minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, - minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + trace("DefMDIChildProc returned:\n"); + dump_minmax_info( minmax ); MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax); ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n", @@ -1528,17 +1518,7 @@ static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, L style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ AdjustWindowRectEx(&rc, style, 0, exstyle); trace("calculated max child window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top); - - trace("ptReserved = (%d,%d)\n" - "ptMaxSize = (%d,%d)\n" - "ptMaxPosition = (%d,%d)\n" - "ptMinTrackSize = (%d,%d)\n" - "ptMaxTrackSize = (%d,%d)\n", - minmax->ptReserved.x, minmax->ptReserved.y, - minmax->ptMaxSize.x, minmax->ptMaxSize.y, - minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, - minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, - minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + dump_minmax_info( minmax ); ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n", minmax->ptMaxSize.x, rc.right - rc.left); @@ -1899,7 +1879,8 @@ static void test_SetMenu(HWND parent) /* test whether we can destroy a menu assigned to a window */ retok = DestroyMenu(hMenu); ok( retok, "DestroyMenu error %d\n", GetLastError()); - ok(!IsMenu(hMenu), "menu handle should be not valid after DestroyMenu\n"); + retok = IsMenu(hMenu); + ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n"); ret = GetMenu(parent); /* This test fails on Win9x */ if (!is_win9x) @@ -2060,7 +2041,7 @@ static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner, test = GetWindow(hwnd, GW_HWNDNEXT); /* skip foreign windows */ while (test && (GetWindowThreadProcessId(test, NULL) != our_pid || - ULongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)) != GetModuleHandle(0))) + (void *)(ULONG_PTR)(GetWindowLongPtr(test, GWLP_HINSTANCE)) != GetModuleHandle(0))) { /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/ test = GetWindow(test, GW_HWNDNEXT); @@ -2070,7 +2051,7 @@ static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner, test = GetWindow(hwnd, GW_HWNDPREV); /* skip foreign windows */ while (test && (GetWindowThreadProcessId(test, NULL) != our_pid || - ULongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)) != GetModuleHandle(0))) + (void *)(ULONG_PTR)(GetWindowLongPtr(test, GWLP_HINSTANCE)) != GetModuleHandle(0))) { /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/ test = GetWindow(test, GW_HWNDPREV); @@ -2197,9 +2178,23 @@ static void test_vis_rgn( HWND hwnd ) ReleaseDC( hwnd, hdc ); } +static LRESULT WINAPI set_focus_on_activate_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + if (msg == WM_ACTIVATE && LOWORD(wp) == WA_ACTIVE) + { + HWND child = GetWindow(hwnd, GW_CHILD); + ok(child != 0, "couldn't find child window\n"); + SetFocus(child); + ok(GetFocus() == child, "Focus should be on child %p\n", child); + return 0; + } + return DefWindowProc(hwnd, msg, wp, lp); +} + static void test_SetFocus(HWND hwnd) { HWND child; + WNDPROC old_wnd_proc; /* check if we can set focus to non-visible windows */ @@ -2246,22 +2241,47 @@ static void test_SetFocus(HWND hwnd) ok( GetFocus() == child, "Focus should still be on child %p\n", child ); EnableWindow(hwnd, TRUE); + ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); + ShowWindow(hwnd, SW_SHOWMINIMIZED); + ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); +todo_wine + ok( GetFocus() != child, "Focus should not be on child %p\n", child ); + ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd ); + ShowWindow(hwnd, SW_RESTORE); + ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); + ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd ); + ShowWindow(hwnd, SW_SHOWMINIMIZED); + ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); + ok( GetFocus() != child, "Focus should not be on child %p\n", child ); +todo_wine + ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd ); + old_wnd_proc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)set_focus_on_activate_proc); + ShowWindow(hwnd, SW_RESTORE); + ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); +todo_wine + ok( GetFocus() == child, "Focus should be on child %p, not %p\n", child, GetFocus() ); + + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)old_wnd_proc); + DestroyWindow( child ); } -static void check_wnd_state(HWND active, HWND foreground, HWND focus, HWND capture) +#define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d) +static void check_wnd_state_(const char *file, int line, + HWND active, HWND foreground, HWND focus, HWND capture) { - ok(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow()); - if (foreground) - ok(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow()); - ok(focus == GetFocus(), "GetFocus() = %p\n", GetFocus()); - ok(capture == GetCapture(), "GetCapture() = %p\n", GetCapture()); + ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow()); + if (foreground && GetForegroundWindow()) + ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow()); + ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus()); + ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture()); } static void test_SetActiveWindow(HWND hwnd) { HWND hwnd2; + flush_events( TRUE ); ShowWindow(hwnd, SW_HIDE); SetFocus(0); SetActiveWindow(0); @@ -2274,10 +2294,12 @@ static void test_SetActiveWindow(HWND hwnd) hwnd2 = SetActiveWindow(0); ok(hwnd2 == hwnd, "SetActiveWindow returned %p instead of %p\n", hwnd2, hwnd); - check_wnd_state(0, 0, 0, 0); - - hwnd2 = SetActiveWindow(hwnd); - ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2); + if (!GetActiveWindow()) /* doesn't always work on vista */ + { + check_wnd_state(0, 0, 0, 0); + hwnd2 = SetActiveWindow(hwnd); + ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2); + } check_wnd_state(hwnd, hwnd, hwnd, 0); SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); @@ -2317,6 +2339,7 @@ static void test_SetForegroundWindow(HWND hwnd) BOOL ret; HWND hwnd2; + flush_events( TRUE ); ShowWindow(hwnd, SW_HIDE); SetFocus(0); SetActiveWindow(0); @@ -2329,7 +2352,10 @@ static void test_SetForegroundWindow(HWND hwnd) hwnd2 = SetActiveWindow(0); ok(hwnd2 == hwnd, "SetActiveWindow(0) returned %p instead of %p\n", hwnd2, hwnd); - check_wnd_state(0, 0, 0, 0); + if (GetActiveWindow() == hwnd) /* doesn't always work on vista */ + check_wnd_state(hwnd, hwnd, hwnd, 0); + else + check_wnd_state(0, 0, 0, 0); ret = SetForegroundWindow(hwnd); ok(ret, "SetForegroundWindow returned FALSE instead of TRUE\n"); @@ -2338,7 +2364,9 @@ static void test_SetForegroundWindow(HWND hwnd) SetLastError(0xdeadbeef); ret = SetForegroundWindow(0); ok(!ret, "SetForegroundWindow returned TRUE instead of FALSE\n"); - ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || + broken(GetLastError() == 0xdeadbeef), /* win9x */ + "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError()); check_wnd_state(hwnd, hwnd, hwnd, 0); SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); @@ -2440,7 +2468,10 @@ static LRESULT WINAPI button_hook_proc(HWND button, UINT msg, WPARAM wparam, LPA static void test_capture_1(void) { - HWND button, capture; + HWND button, capture, oldFocus, oldActive; + + oldFocus = GetFocus(); + oldActive = GetActiveWindow(); capture = GetCapture(); ok(capture == 0, "GetCapture() = %p\n", capture); @@ -2458,14 +2489,16 @@ static void test_capture_1(void) check_wnd_state(button, 0, button, button); DestroyWindow(button); - check_wnd_state(0, 0, 0, 0); + check_wnd_state(oldActive, 0, oldFocus, 0); } static void test_capture_2(void) { - HWND button, hwnd, capture; + HWND button, hwnd, capture, oldFocus, oldActive; - check_wnd_state(0, 0, 0, 0); + oldFocus = GetFocus(); + oldActive = GetActiveWindow(); + check_wnd_state(oldActive, 0, oldFocus, 0); button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); assert(button); @@ -2515,7 +2548,7 @@ static void test_capture_2(void) check_wnd_state(button, button, button, 0); DestroyWindow(button); - check_wnd_state(0, 0, 0, 0); + check_wnd_state(oldActive, 0, oldFocus, 0); } static void test_capture_3(HWND hwnd1, HWND hwnd2) @@ -2548,7 +2581,8 @@ static void test_keyboard_input(HWND hwnd) MSG msg; BOOL ret; - ShowWindow(hwnd, SW_SHOW); + flush_events( TRUE ); + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW); UpdateWindow(hwnd); flush_events( TRUE ); @@ -2645,12 +2679,19 @@ static void test_mouse_input(HWND hwnd) flush_events( TRUE ); - /* Check that setting the same position will generate WM_MOUSEMOVE */ + /* Check that setting the same position may generate WM_MOUSEMOVE */ SetCursorPos(x, y); msg.message = 0; - ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n"); - ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message); - ok(msg.pt.x == x && msg.pt.y == y, "wrong message coords (%d,%d)/(%d,%d)\n", x, y, msg.pt.x, msg.pt.y); + do + ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); + while (ret && msg.message >= 0xc000); /* skip registered messages */ + if (ret) + { + ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", + msg.hwnd, msg.message); + ok(msg.pt.x == x && msg.pt.y == y, "wrong message coords (%d,%d)/(%d,%d)\n", + x, y, msg.pt.x, msg.pt.y); + } /* force the system to update its internal queue mouse position, * otherwise it won't generate relative mouse movements below. @@ -2660,23 +2701,29 @@ static void test_mouse_input(HWND hwnd) msg.message = 0; mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0); - ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n"); - ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message); /* FIXME: SetCursorPos in Wine generates additional WM_MOUSEMOVE message */ - if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) - ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message); + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + { + if (msg.message >= 0xc000) continue; /* skip registered messages */ + ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, + "hwnd %p message %04x\n", msg.hwnd, msg.message); + } ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); ok( !ret, "message %04x available\n", msg.message); mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0); ShowWindow(popup, SW_HIDE); - ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n"); + do + ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n"); + while (msg.message >= 0xc000); /* skip registered messages */ ok(msg.hwnd == hwnd && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message); flush_events( TRUE ); mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0); ShowWindow(hwnd, SW_HIDE); - ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); + do + ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); + while (ret && msg.message >= 0xc000); /* skip registered messages */ ok( !ret, "message %04x available\n", msg.message); flush_events( TRUE ); @@ -2742,7 +2789,9 @@ static void test_mouse_input(HWND hwnd) SendMessageA(hwnd, WM_COMMAND, (WPARAM)popup, 0); test_lbuttondown_flag = FALSE; - ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n"); + do + ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n"); + while (msg.message >= 0xc000); /* skip registered messages */ ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n", msg.hwnd, popup, msg.message); ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n"); @@ -3219,7 +3268,12 @@ static void test_scroll(void) 100, 100, 200, 200, 0, 0, 0, NULL); /* horizontal */ ret = GetScrollRange( hwnd, SB_HORZ, &min, &max); - ok( ret, "GetScrollRange returns FALSE\n"); + if (!ret) /* win9x */ + { + win_skip( "GetScrollRange doesn't work\n" ); + DestroyWindow( hwnd); + return; + } ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min); ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min); si.cbSize = sizeof( si); @@ -3321,9 +3375,17 @@ static void test_params(void) INT rc; /* Just a param check */ - SetLastError(0xdeadbeef); - rc = GetWindowText(hwndMain2, NULL, 1024); - ok( rc==0, "GetWindowText: rc=%d err=%d\n",rc,GetLastError()); + if (pGetMonitorInfoA) + { + SetLastError(0xdeadbeef); + rc = GetWindowText(hwndMain2, NULL, 1024); + ok( rc==0, "GetWindowText: rc=%d err=%d\n",rc,GetLastError()); + } + else + { + /* Skips actually on Win95 and NT4 */ + win_skip("Test would crash on Win95\n"); + } SetLastError(0xdeadbeef); hwnd=CreateWindow("LISTBOX", "TestList", @@ -3898,7 +3960,7 @@ static LRESULT CALLBACK minmax_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM l } static int expected_cx, expected_cy; -static RECT expected_rect; +static RECT expected_rect, broken_rect; static LRESULT CALLBACK winsizes_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { @@ -3920,10 +3982,16 @@ static LRESULT CALLBACK winsizes_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM GetWindowRect( hwnd, &rect ); trace( "hwnd %p msg %x size %dx%d rect %d,%d-%d,%d\n", hwnd, msg, cs->cx, cs->cy, rect.left, rect.top, rect.right, rect.bottom ); - ok( cs->cx == expected_cx, "wrong x size %d/%d\n", cs->cx, expected_cx ); - ok( cs->cy == expected_cy, "wrong y size %d/%d\n", cs->cy, expected_cy ); - ok( rect.right - rect.left == expected_rect.right - expected_rect.left && - rect.bottom - rect.top == expected_rect.bottom - expected_rect.top, + ok( cs->cx == expected_cx || broken(cs->cx == (short)expected_cx), + "wrong x size %d/%d\n", cs->cx, expected_cx ); + ok( cs->cy == expected_cy || broken(cs->cy == (short)expected_cy), + "wrong y size %d/%d\n", cs->cy, expected_cy ); + ok( (rect.right - rect.left == expected_rect.right - expected_rect.left && + rect.bottom - rect.top == expected_rect.bottom - expected_rect.top) || + broken( rect.right - rect.left == broken_rect.right - broken_rect.left && + rect.bottom - rect.top == broken_rect.bottom - broken_rect.top) || + broken( rect.right - rect.left == (short)broken_rect.right - (short)broken_rect.left && + rect.bottom - rect.top == (short)broken_rect.bottom - (short)broken_rect.top), "wrong rect %d,%d-%d,%d / %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom, expected_rect.left, expected_rect.top, expected_rect.right, expected_rect.bottom ); @@ -3961,6 +4029,11 @@ static void test_CreateWindow(void) #define expect_ex_style(window, ex_style)\ ok(GetWindowLong(window, GWL_EXSTYLE) == (ex_style), "expected ex_style %x != %x\n", (LONG)(ex_style), GetWindowLong(window, GWL_EXSTYLE)) +#define expect_gle_broken_9x(gle)\ + ok(GetLastError() == gle ||\ + broken(GetLastError() == 0xdeadbeef),\ + "IsMenu set error %d\n", GetLastError()) + hmenu = CreateMenu(); assert(hmenu != 0); parent = GetDesktopWindow(); @@ -4017,7 +4090,7 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); hmenu = CreateMenu(); assert(hmenu != 0); @@ -4031,7 +4104,7 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); hmenu = CreateMenu(); assert(hmenu != 0); @@ -4045,7 +4118,7 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); hmenu = CreateMenu(); assert(hmenu != 0); @@ -4059,14 +4132,16 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); /* WS_CHILD | WS_POPUP */ SetLastError(0xdeadbeef); hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP, 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); - ok(!hwnd, "CreateWindowEx should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); + if (hwnd) + DestroyWindow(hwnd); hmenu = CreateMenu(); assert(hmenu != 0); @@ -4080,13 +4155,15 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); SetLastError(0xdeadbeef); hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION, 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); - ok(!hwnd, "CreateWindowEx should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); + if (hwnd) + DestroyWindow(hwnd); hmenu = CreateMenu(); assert(hmenu != 0); @@ -4100,13 +4177,15 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); SetLastError(0xdeadbeef); hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_POPUP, 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); - ok(!hwnd, "CreateWindowEx should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); + if (hwnd) + DestroyWindow(hwnd); hmenu = CreateMenu(); assert(hmenu != 0); @@ -4120,13 +4199,15 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); SetLastError(0xdeadbeef); hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION, 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); - ok(!hwnd, "CreateWindowEx should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); + if (hwnd) + DestroyWindow(hwnd); hmenu = CreateMenu(); assert(hmenu != 0); @@ -4140,7 +4221,7 @@ static void test_CreateWindow(void) DestroyWindow(hwnd); SetLastError(0xdeadbeef); ok(!IsMenu(hmenu), "IsMenu should fail\n"); - ok(GetLastError() == ERROR_INVALID_MENU_HANDLE, "IsMenu set error %d\n", GetLastError()); + expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); /* test child window sizing */ cls.style = 0; @@ -4204,15 +4285,17 @@ static void test_CreateWindow(void) expected_cx = expected_cy = 200000; SetRect( &expected_rect, 0, 0, 200000, 200000 ); + broken_rect = expected_rect; hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 300000, 300000, 200000, 200000, parent, 0, 0, NULL); ok( hwnd != 0, "creation failed err %u\n", GetLastError()); GetClientRect( hwnd, &rc ); - ok( rc.right == 200000, "invalid rect right %u\n", rc.right ); - ok( rc.bottom == 200000, "invalid rect bottom %u\n", rc.bottom ); + ok( rc.right == 200000 || broken(rc.right == (short)200000), "invalid rect right %u\n", rc.right ); + ok( rc.bottom == 200000 || broken(rc.bottom == (short)200000), "invalid rect bottom %u\n", rc.bottom ); DestroyWindow(hwnd); expected_cx = expected_cy = -10; SetRect( &expected_rect, 0, 0, 0, 0 ); + SetRect( &broken_rect, 0, 0, -10, -10 ); hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -20, -20, -10, -10, parent, 0, 0, NULL); ok( hwnd != 0, "creation failed err %u\n", GetLastError()); GetClientRect( hwnd, &rc ); @@ -4222,6 +4305,7 @@ static void test_CreateWindow(void) expected_cx = expected_cy = -200000; SetRect( &expected_rect, 0, 0, 0, 0 ); + SetRect( &broken_rect, 0, 0, -200000, -200000 ); hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -300000, -300000, -200000, -200000, parent, 0, 0, NULL); ok( hwnd != 0, "creation failed err %u\n", GetLastError()); GetClientRect( hwnd, &rc ); @@ -4229,6 +4313,33 @@ static void test_CreateWindow(void) ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom ); DestroyWindow(hwnd); + /* we need a parent at 0,0 so that child coordinates match */ + DestroyWindow(parent); + parent = CreateWindowEx(0, "MinMax_WndClass", NULL, WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL); + ok(parent != 0, "CreateWindowEx error %d\n", GetLastError()); + + expected_cx = 100; + expected_cy = 0x7fffffff; + SetRect( &expected_rect, 10, 10, 110, 0x7fffffff ); + SetRect( &broken_rect, 10, 10, 110, 0x7fffffffU + 10 ); + hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 10, 10, 100, 0x7fffffff, parent, 0, 0, NULL); + ok( hwnd != 0, "creation failed err %u\n", GetLastError()); + GetClientRect( hwnd, &rc ); + ok( rc.right == 100, "invalid rect right %u\n", rc.right ); + ok( rc.bottom == 0x7fffffff - 10 || broken(rc.bottom == 0), "invalid rect bottom %u\n", rc.bottom ); + DestroyWindow(hwnd); + + expected_cx = 0x7fffffff; + expected_cy = 0x7fffffff; + SetRect( &expected_rect, 20, 10, 0x7fffffff, 0x7fffffff ); + SetRect( &broken_rect, 20, 10, 0x7fffffffU + 20, 0x7fffffffU + 10 ); + hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 20, 10, 0x7fffffff, 0x7fffffff, parent, 0, 0, NULL); + ok( hwnd != 0, "creation failed err %u\n", GetLastError()); + GetClientRect( hwnd, &rc ); + ok( rc.right == 0x7fffffff - 20 || broken(rc.right == 0), "invalid rect right %u\n", rc.right ); + ok( rc.bottom == 0x7fffffff - 10 || broken(rc.bottom == 0), "invalid rect bottom %u\n", rc.bottom ); + DestroyWindow(hwnd); + /* top level window */ expected_cx = expected_cy = 200000; SetRect( &expected_rect, 0, 0, GetSystemMetrics(SM_CXMAXTRACK), GetSystemMetrics(SM_CYMAXTRACK) ); @@ -4244,6 +4355,7 @@ static void test_CreateWindow(void) UnregisterClass("MinMax_WndClass", GetModuleHandle(0)); UnregisterClass("Sizes_WndClass", GetModuleHandle(0)); +#undef expect_gle_broken_9x #undef expect_menu #undef expect_style #undef expect_ex_style @@ -4278,7 +4390,7 @@ static void test_SetWindowLong(void) SetLastError(0xdeadbeef); retval = SetWindowLongPtr(hwndMain, GWLP_WNDPROC, 0); - ok((WNDPROC)retval == main_window_procA, + ok((WNDPROC)retval == main_window_procA || broken(!retval), /* win9x */ "SetWindowLongPtr on invalid window proc should have returned address of main_window_procA instead of 0x%lx\n", retval); ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError()); retval = GetWindowLongPtr(hwndMain, GWLP_WNDPROC); @@ -4325,7 +4437,9 @@ static void test_ShowWindow(void) ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); GetWindowRect(hwnd, &rc); - ok(EqualRect(&rcMain, &rc), "rects should match\n"); + ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n", + rcMain.left, rcMain.top, rcMain.right, rcMain.bottom, + rc.left, rc.top, rc.right, rc.bottom); ret = ShowWindow(hwnd, SW_SHOW); ok(!ret, "not expected ret: %lu\n", ret); @@ -4335,7 +4449,9 @@ static void test_ShowWindow(void) ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); GetWindowRect(hwnd, &rc); - ok(EqualRect(&rcMain, &rc), "rects should match\n"); + ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n", + rcMain.left, rcMain.top, rcMain.right, rcMain.bottom, + rc.left, rc.top, rc.right, rc.bottom); ret = ShowWindow(hwnd, SW_MINIMIZE); ok(ret, "not expected ret: %lu\n", ret); @@ -4355,7 +4471,9 @@ static void test_ShowWindow(void) ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); GetWindowRect(hwnd, &rc); - ok(EqualRect(&rcMain, &rc), "rects should match\n"); + ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n", + rcMain.left, rcMain.top, rcMain.right, rcMain.bottom, + rc.left, rc.top, rc.right, rc.bottom); ret = EnableWindow(hwnd, FALSE); ok(!ret, "not expected ret: %lu\n", ret); @@ -4370,7 +4488,9 @@ static void test_ShowWindow(void) ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); GetWindowRect(hwnd, &rc); - ok(EqualRect(&rcMain, &rc), "rects should match\n"); + ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n", + rcMain.left, rcMain.top, rcMain.right, rcMain.bottom, + rc.left, rc.top, rc.right, rc.bottom); ret = DefWindowProc(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); ok(!ret, "not expected ret: %lu\n", ret); @@ -4380,7 +4500,9 @@ static void test_ShowWindow(void) ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); GetWindowRect(hwnd, &rc); - ok(EqualRect(&rcMain, &rc), "rects should match\n"); + ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n", + rcMain.left, rcMain.top, rcMain.right, rcMain.bottom, + rc.left, rc.top, rc.right, rc.bottom); ret = ShowWindow(hwnd, SW_MINIMIZE); ok(ret, "not expected ret: %lu\n", ret); @@ -4410,7 +4532,9 @@ static void test_ShowWindow(void) ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); GetWindowRect(hwnd, &rc); - ok(EqualRect(&rcMain, &rc), "rects should match\n"); + ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n", + rcMain.left, rcMain.top, rcMain.right, rcMain.bottom, + rc.left, rc.top, rc.right, rc.bottom); ret = DefWindowProc(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); ok(!ret, "not expected ret: %lu\n", ret); @@ -4602,10 +4726,7 @@ static LRESULT CALLBACK TestExposedRegion_WndProc(HWND hwnd, UINT msg, WPARAM wP if(waitResult != WAIT_TIMEOUT) { GetUpdateRect(hwnd, &updateRect, FALSE); -todo_wine -{ - ok(!IsRectEmpty(&updateRect), "Exposed rect should not be empty\n"); -} + ok(IsRectEmpty(&updateRect), "Exposed rect should be empty\n"); } return 1; @@ -4631,25 +4752,575 @@ static void test_Expose(void) DestroyWindow(mw); } -START_TEST(win) +static void test_GetWindowModuleFileName(void) +{ + HWND hwnd; + HINSTANCE hinst; + UINT ret1, ret2; + char buf1[MAX_PATH], buf2[MAX_PATH]; + + if (!pGetWindowModuleFileNameA) + { + skip("GetWindowModuleFileNameA is not available\n"); + return; + } + + hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL); + assert(hwnd); + + hinst = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE); + ok(hinst == 0 || broken(hinst == GetModuleHandle(0)), /* win9x */ "expected 0, got %p\n", hinst); + + buf1[0] = 0; + SetLastError(0xdeadbeef); + ret1 = GetModuleFileName(hinst, buf1, sizeof(buf1)); + ok(ret1, "GetModuleFileName error %u\n", GetLastError()); + + buf2[0] = 0; + SetLastError(0xdeadbeef); + ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2)); + ok(ret2, "GetWindowModuleFileNameA error %u\n", GetLastError()); + + ok(ret1 == ret2 || broken(ret2 == ret1 + 1), /* win98 */ "%u != %u\n", ret1, ret2); + ok(!strcmp(buf1, buf2), "%s != %s\n", buf1, buf2); + + hinst = GetModuleHandle(0); + + SetLastError(0xdeadbeef); + ret2 = GetModuleFileName(hinst, buf2, ret1 - 2); + ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3), /* win98 */ + "expected %u, got %u\n", ret1 - 2, ret2); + ok(GetLastError() == 0xdeadbeef /* XP */ || + GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ + "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret2 = GetModuleFileName(hinst, buf2, 0); + ok(!ret2, "GetModuleFileName should return 0\n"); + ok(GetLastError() == 0xdeadbeef /* XP */ || + GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ + "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret2 = pGetWindowModuleFileNameA(hwnd, buf2, ret1 - 2); + ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3), /* win98 */ + "expected %u, got %u\n", ret1 - 2, ret2); + ok(GetLastError() == 0xdeadbeef /* XP */ || + GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ + "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret2 = pGetWindowModuleFileNameA(hwnd, buf2, 0); + ok(!ret2, "expected 0, got %u\n", ret2); + ok(GetLastError() == 0xdeadbeef /* XP */ || + GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ + "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); + + DestroyWindow(hwnd); + + buf2[0] = 0; + hwnd = (HWND)0xdeadbeef; + SetLastError(0xdeadbeef); + ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1)); + ok(!ret1, "expected 0, got %u\n", ret1); + ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), /* win9x */ + "expected ERROR_INVALID_WINDOW_HANDLE, got %u\n", GetLastError()); + + hwnd = FindWindow("Shell_TrayWnd", NULL); + ok(IsWindow(hwnd), "got invalid tray window %p\n", hwnd); + SetLastError(0xdeadbeef); + ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1)); + ok(!ret1 || broken(ret1), /* win98 */ "expected 0, got %u\n", ret1); + + if (!ret1) /* inter-process GetWindowModuleFileName works on win9x, so don't test the desktop there */ + { + ret1 = GetModuleFileName(0, buf1, sizeof(buf1)); + hwnd = GetDesktopWindow(); + ok(IsWindow(hwnd), "got invalid desktop window %p\n", hwnd); + SetLastError(0xdeadbeef); + ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2)); + ok(!ret2 || ret1 == ret2 /* vista */, "expected 0 or %u, got %u %s\n", ret1, ret2, buf2); + } +} + +static void test_hwnd_message(void) +{ + static const WCHAR mainwindowclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s',0}; + static const WCHAR message_windowW[] = {'m','e','s','s','a','g','e',' ','w','i','n','d','o','w',0}; + + HWND parent = 0, hwnd, found; + RECT rect; + + /* HWND_MESSAGE is not supported below w2k, but win9x return != 0 + on CreateWindowExA and crash later in the test. + Use UNICODE here to fail on win9x */ + hwnd = CreateWindowExW(0, mainwindowclassW, message_windowW, WS_CAPTION | WS_VISIBLE, + 100, 100, 200, 200, HWND_MESSAGE, 0, 0, NULL); + if (!hwnd) + { + win_skip("CreateWindowExW with parent HWND_MESSAGE failed\n"); + return; + } + + ok( !GetParent(hwnd), "GetParent should return 0 for message only windows\n" ); + if (pGetAncestor) + { + char buffer[100]; + HWND root, desktop = GetDesktopWindow(); + + parent = pGetAncestor(hwnd, GA_PARENT); + ok(parent != 0, "GetAncestor(GA_PARENT) should not return 0 for message windows\n"); + ok(parent != desktop, "GetAncestor(GA_PARENT) should not return desktop for message windows\n"); + root = pGetAncestor(hwnd, GA_ROOT); + ok(root == hwnd, "GetAncestor(GA_ROOT) should return hwnd for message windows\n"); + ok( !pGetAncestor(parent, GA_PARENT), "parent shouldn't have parent %p\n", + pGetAncestor(parent, GA_PARENT) ); + trace("parent %p root %p desktop %p\n", parent, root, desktop); + if (!GetClassNameA( parent, buffer, sizeof(buffer) )) buffer[0] = 0; + ok( !lstrcmpi( buffer, "Message" ), "wrong parent class '%s'\n", buffer ); + GetWindowRect( parent, &rect ); + ok( rect.left == 0 && rect.right == 100 && rect.top == 0 && rect.bottom == 100, + "wrong parent rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom ); + } + GetWindowRect( hwnd, &rect ); + ok( rect.left == 100 && rect.right == 300 && rect.top == 100 && rect.bottom == 300, + "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom ); + + /* test FindWindow behavior */ + + found = FindWindowExA( 0, 0, 0, "message window" ); + ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd ); + SetLastError(0xdeadbeef); + found = FindWindowExA( GetDesktopWindow(), 0, 0, "message window" ); + ok( found == 0, "found message window %p/%p\n", found, hwnd ); + ok( GetLastError() == 0xdeadbeef, "expected deadbeef, got %d\n", GetLastError() ); + if (parent) + { + found = FindWindowExA( parent, 0, 0, "message window" ); + ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd ); + } + + /* test IsChild behavior */ + + if (parent) ok( !IsChild( parent, hwnd ), "HWND_MESSAGE is child of top window\n" ); + + /* test IsWindowVisible behavior */ + + ok( !IsWindowVisible( hwnd ), "HWND_MESSAGE window is visible\n" ); + if (parent) ok( !IsWindowVisible( parent ), "HWND_MESSAGE parent is visible\n" ); + + DestroyWindow(hwnd); +} + +static void test_layered_window(void) { - pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" ); - pGetWindowInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetWindowInfo" ); + HWND hwnd; + COLORREF key = 0; + BYTE alpha = 0; + DWORD flags = 0; + BOOL ret; - hwndMain = CreateWindowExA(0, "static", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL); - if (hwndMain) + if (!pGetLayeredWindowAttributes || !pSetLayeredWindowAttributes) { - ok(!GetParent(hwndMain), "GetParent should return 0 for message only windows\n"); - if (pGetAncestor) + win_skip( "layered windows not supported\n" ); + return; + } + hwnd = CreateWindowExA(0, "MainWindowClass", "message window", WS_CAPTION, + 100, 100, 200, 200, 0, 0, 0, NULL); + assert( hwnd ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( !ret, "GetLayeredWindowAttributes should fail on non-layered window\n" ); + ret = pSetLayeredWindowAttributes( hwnd, 0, 0, LWA_ALPHA ); + ok( !ret, "SetLayeredWindowAttributes should fail on non-layered window\n" ); + SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); + ret = pSetLayeredWindowAttributes( hwnd, 0x123456, 44, LWA_ALPHA ); + ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); + ok( key == 0x123456, "wrong color key %x\n", key ); + ok( alpha == 44, "wrong alpha %u\n", alpha ); + ok( flags == LWA_ALPHA, "wrong flags %x\n", flags ); + + /* clearing WS_EX_LAYERED resets attributes */ + SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( !ret, "GetLayeredWindowAttributes should fail on no longer layered window\n" ); + SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); + ret = pSetLayeredWindowAttributes( hwnd, 0x654321, 22, LWA_COLORKEY | LWA_ALPHA ); + ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); + ok( key == 0x654321, "wrong color key %x\n", key ); + ok( alpha == 22, "wrong alpha %u\n", alpha ); + ok( flags == (LWA_COLORKEY | LWA_ALPHA), "wrong flags %x\n", flags ); + + ret = pSetLayeredWindowAttributes( hwnd, 0x888888, 33, LWA_COLORKEY ); + ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); + alpha = 0; + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); + ok( key == 0x888888, "wrong color key %x\n", key ); + /* alpha not changed on vista if LWA_ALPHA is not set */ + ok( alpha == 22 || alpha == 33, "wrong alpha %u\n", alpha ); + ok( flags == LWA_COLORKEY, "wrong flags %x\n", flags ); + + /* color key always changed */ + ret = pSetLayeredWindowAttributes( hwnd, 0x999999, 44, 0 ); + ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); + alpha = 0; + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); + ok( key == 0x999999, "wrong color key %x\n", key ); + ok( alpha == 22 || alpha == 44, "wrong alpha %u\n", alpha ); + ok( flags == 0, "wrong flags %x\n", flags ); + + /* default alpha is 0 */ + SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); + SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); + ret = pSetLayeredWindowAttributes( hwnd, 0x222222, 55, 0 ); + ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); + ok( key == 0x222222, "wrong color key %x\n", key ); + ok( alpha == 0 || alpha == 55, "wrong alpha %u\n", alpha ); + ok( flags == 0, "wrong flags %x\n", flags ); + + DestroyWindow( hwnd ); +} + +static MONITORINFO mi; + +static LRESULT CALLBACK fullscreen_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + switch (msg) + { + case WM_NCCREATE: { - hwndMessage = pGetAncestor(hwndMain, GA_PARENT); - ok(hwndMessage != 0, "GetAncestor(GA_PARENT) should not return 0 for message only windows\n"); - trace("hwndMessage %p\n", hwndMessage); + CREATESTRUCTA *cs = (CREATESTRUCTA *)lp; + trace("WM_NCCREATE: rect %d,%d-%d,%d\n", cs->x, cs->y, cs->cx, cs->cy); + ok(cs->x == mi.rcMonitor.left && cs->y == mi.rcMonitor.top && + cs->cx == mi.rcMonitor.right && cs->cy == mi.rcMonitor.bottom, + "expected %d,%d-%d,%d, got %d,%d-%d,%d\n", + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + cs->x, cs->y, cs->cx, cs->cy); + break; + } + case WM_GETMINMAXINFO: + { + MINMAXINFO *minmax = (MINMAXINFO *)lp; + dump_minmax_info(minmax); + ok(minmax->ptMaxPosition.x <= mi.rcMonitor.left, "%d <= %d\n", minmax->ptMaxPosition.x, mi.rcMonitor.left); + ok(minmax->ptMaxPosition.y <= mi.rcMonitor.top, "%d <= %d\n", minmax->ptMaxPosition.y, mi.rcMonitor.top); + ok(minmax->ptMaxSize.x >= mi.rcMonitor.right, "%d >= %d\n", minmax->ptMaxSize.x, mi.rcMonitor.right); + ok(minmax->ptMaxSize.y >= mi.rcMonitor.bottom, "%d >= %d\n", minmax->ptMaxSize.y, mi.rcMonitor.bottom); + break; } - DestroyWindow(hwndMain); } - else - trace("CreateWindowExA with parent HWND_MESSAGE failed\n"); + return DefWindowProc(hwnd, msg, wp, lp); +} + +static void test_fullscreen(void) +{ + static const DWORD t_style[] = { + WS_OVERLAPPED, WS_POPUP, WS_CHILD, WS_THICKFRAME, WS_DLGFRAME + }; + static const DWORD t_ex_style[] = { + 0, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW + }; + WNDCLASS cls; + HWND hwnd; + int i, j; + POINT pt; + RECT rc; + HMONITOR hmon; + LRESULT ret; + + if (!pGetMonitorInfoA || !pMonitorFromPoint) + { + win_skip("GetMonitorInfoA or MonitorFromPoint are not available on this platform\n"); + return; + } + + pt.x = pt.y = 0; + SetLastError(0xdeadbeef); + hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); + ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError()); + + mi.cbSize = sizeof(mi); + SetLastError(0xdeadbeef); + ret = pGetMonitorInfoA(hmon, &mi); + ok(ret, "GetMonitorInfo error %u\n", GetLastError()); + trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n", + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom); + + cls.style = 0; + cls.lpfnWndProc = fullscreen_wnd_proc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandle(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "fullscreen_class"; + RegisterClass(&cls); + + for (i = 0; i < sizeof(t_style)/sizeof(t_style[0]); i++) + { + DWORD style, ex_style; + + /* avoid a WM interaction */ + assert(!(t_style[i] & WS_VISIBLE)); + + for (j = 0; j < sizeof(t_ex_style)/sizeof(t_ex_style[0]); j++) + { + int fixup; + + style = t_style[i]; + ex_style = t_ex_style[j]; + + hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + GetDesktopWindow(), 0, GetModuleHandle(0), NULL); + ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); + GetWindowRect(hwnd, &rc); + trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && + rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + DestroyWindow(hwnd); + + style = t_style[i] | WS_MAXIMIZE; + hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + GetDesktopWindow(), 0, GetModuleHandle(0), NULL); + ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); + GetWindowRect(hwnd, &rc); + trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && + rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + DestroyWindow(hwnd); + + style = t_style[i] | WS_MAXIMIZE | WS_CAPTION; + hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + GetDesktopWindow(), 0, GetModuleHandle(0), NULL); + ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); + GetWindowRect(hwnd, &rc); + trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && + rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + DestroyWindow(hwnd); + + style = t_style[i] | WS_CAPTION | WS_MAXIMIZEBOX; + hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + GetDesktopWindow(), 0, GetModuleHandle(0), NULL); + ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); + GetWindowRect(hwnd, &rc); + trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && + rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + DestroyWindow(hwnd); + + style = t_style[i] | WS_MAXIMIZE | WS_CAPTION | WS_MAXIMIZEBOX; + hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + GetDesktopWindow(), 0, GetModuleHandle(0), NULL); + ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); + GetWindowRect(hwnd, &rc); + trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + /* Windows makes a maximized window slightly larger (to hide the borders?) */ + fixup = min(abs(rc.left), abs(rc.top)); + InflateRect(&rc, -fixup, -fixup); + /* FIXME: this doesn't work correctly in Wine for child windows yet */ + if (style & WS_CHILD) + todo_wine + ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top && + rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + else + ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top && + rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + DestroyWindow(hwnd); + + style = t_style[i] | WS_MAXIMIZE | WS_MAXIMIZEBOX; + hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + GetDesktopWindow(), 0, GetModuleHandle(0), NULL); + ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); + GetWindowRect(hwnd, &rc); + trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + /* Windows makes a maximized window slightly larger (to hide the borders?) */ + fixup = min(abs(rc.left), abs(rc.top)); + InflateRect(&rc, -fixup, -fixup); + if (style & (WS_CHILD | WS_POPUP)) + ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && + rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + else + ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top && + rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom, + "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom); + DestroyWindow(hwnd); + } + } + + UnregisterClass("fullscreen_class", GetModuleHandle(0)); +} + +static BOOL test_thick_child_got_minmax; + +static int getExpectedThickChildInc(void) +{ + const int outer = 2; + int resizeBorder = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); + return (outer + resizeBorder); +} + +static LRESULT WINAPI test_thick_child_size_winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + MINMAXINFO* minmax; + int expectedMinTrack; + int actualMinTrackX; + int actualMinTrackY; + int expectedMaxTrackX; + int expectedMaxTrackY; + int actualMaxTrackX; + int actualMaxTrackY; + int expectedMaxSizeX; + int expectedMaxSizeY; + int actualMaxSizeX; + int actualMaxSizeY; + int expectedPosX; + int expectedPosY; + int actualPosX; + int actualPosY; + RECT rect; + switch (msg) + { + case WM_GETMINMAXINFO: + { + minmax = (MINMAXINFO *)lparam; + trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam); + dump_minmax_info( minmax ); + + test_thick_child_got_minmax = TRUE; + + expectedMinTrack = 2* getExpectedThickChildInc(); + actualMinTrackX = minmax->ptMinTrackSize.x; + actualMinTrackY = minmax->ptMinTrackSize.y; + todo_wine + ok(actualMinTrackX == expectedMinTrack && actualMinTrackY == expectedMinTrack, + "expected minTrack %dx%d, actual minTrack %dx%d\n", + expectedMinTrack, expectedMinTrack, actualMinTrackX, actualMinTrackY); + + actualMaxTrackX = minmax->ptMaxTrackSize.x; + actualMaxTrackY = minmax->ptMaxTrackSize.y; + expectedMaxTrackX = GetSystemMetrics(SM_CXMAXTRACK); + expectedMaxTrackY = GetSystemMetrics(SM_CYMAXTRACK); + ok(actualMaxTrackX == expectedMaxTrackX && actualMaxTrackY == expectedMaxTrackY, + "expected maxTrack %dx%d, actual maxTrack %dx%d\n", + expectedMaxTrackX, expectedMaxTrackY, actualMaxTrackX, actualMaxTrackY); + + GetClientRect(GetParent(hwnd), &rect); + AdjustWindowRectEx(&rect, WS_CHILD | WS_VISIBLE | WS_THICKFRAME, FALSE, 0); + expectedMaxSizeX = rect.right - rect.left; + expectedMaxSizeY = rect.bottom - rect.top; + actualMaxSizeX = minmax->ptMaxSize.x; + actualMaxSizeY = minmax->ptMaxSize.y; + ok(actualMaxSizeX == expectedMaxSizeX && actualMaxSizeY == expectedMaxSizeY, + "expected maxTrack %dx%d, actual maxTrack %dx%d\n", + expectedMaxSizeX, expectedMaxSizeY, actualMaxSizeX, actualMaxSizeY); + + expectedPosX = - getExpectedThickChildInc(); + expectedPosY = expectedPosX; + actualPosX = minmax->ptMaxPosition.x; + actualPosY = minmax->ptMaxPosition.y; + todo_wine + ok(actualPosX == expectedPosX && actualPosY == expectedPosY, + "expected maxPosition (%d/%d), actual maxPosition (%d/%d)\n", + expectedPosX, expectedPosY, actualPosX, actualPosY); + break; + } + } + + return DefWindowProcA(hwnd, msg, wparam, lparam); +} + +static void test_thick_child_size(HWND parentWindow) +{ + BOOL success; + RECT childRect; + HWND childWindow; + LONG childWidth; + LONG childHeight; + WNDCLASSA cls; + LPCTSTR className = "THICK_CHILD_CLASS"; + LONG style = WS_CHILD | WS_VISIBLE | WS_THICKFRAME; + LONG exStyle = 0; + int expectedSize = 2*getExpectedThickChildInc(); + + + cls.style = 0; + cls.lpfnWndProc = test_thick_child_size_winproc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = className; + SetLastError(0xdeadbeef); + ok(RegisterClassA(&cls),"RegisterClassA failed, error: %u\n", GetLastError()); + + test_thick_child_got_minmax = FALSE; + + SetLastError(0xdeadbeef); + childWindow = CreateWindowEx( exStyle, className, "", style, 0, 0, 0, 0, parentWindow, 0, GetModuleHandleA(0), NULL ); + ok(childWindow != NULL, "Failed to create child window, error: %u\n", GetLastError()); + + ok(test_thick_child_got_minmax, "Got no WM_GETMINMAXINFO\n"); + + SetLastError(0xdeadbeef); + success = GetWindowRect(childWindow, &childRect); + ok(success,"GetWindowRect call failed, error: %u\n", GetLastError()); + childWidth = childRect.right - childRect.left; + childHeight = childRect.bottom - childRect.top; + + todo_wine + ok( (childWidth == expectedSize) && (childHeight == expectedSize), + "size of window with style WS_CHILD | WS_VISIBLE | WS_THICKFRAME is wrong: expected size %dx%d != actual size %dx%d\n", + expectedSize, expectedSize, childWidth, childHeight); + + + SetLastError(0xdeadbeef); + success = DestroyWindow(childWindow); + ok(success,"DestroyWindow call failed, error: %u\n", GetLastError()); + ok(UnregisterClass(className, GetModuleHandleA(0)),"UnregisterClass call failed\n"); +} + + +START_TEST(win) +{ + HMODULE user32 = GetModuleHandleA( "user32.dll" ); + pGetAncestor = (void *)GetProcAddress( user32, "GetAncestor" ); + pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" ); + pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" ); + pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" ); + pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" ); + pGetMonitorInfoA = (void *)GetProcAddress( user32, "GetMonitorInfoA" ); + pMonitorFromPoint = (void *)GetProcAddress( user32, "MonitorFromPoint" ); if (!RegisterWindowClasses()) assert(0); @@ -4661,8 +5332,6 @@ START_TEST(win) WS_MAXIMIZEBOX | WS_POPUP, 100, 100, 200, 200, 0, 0, GetModuleHandle(0), NULL); - test_nonclient_area(hwndMain); - hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, @@ -4674,8 +5343,12 @@ START_TEST(win) our_pid = GetWindowThreadProcessId(hwndMain, NULL); /* Add the tests below this line */ + test_thick_child_size(hwndMain); + test_fullscreen(); + test_hwnd_message(); + test_nonclient_area(hwndMain); test_params(); - + test_GetWindowModuleFileName(); test_capture_1(); test_capture_2(); test_capture_3(hwndMain, hwndMain2); @@ -4683,7 +5356,6 @@ START_TEST(win) test_CreateWindow(); test_parent_owner(); test_SetParent(); - test_shell_window(); test_mdi(); test_icons(); @@ -4691,7 +5363,6 @@ START_TEST(win) test_SetMenu(hwndMain); test_SetFocus(hwndMain); test_SetActiveWindow(hwndMain); - test_SetForegroundWindow(hwndMain); test_children_zorder(hwndMain); test_popup_zorder(hwndMain2, hwndMain); @@ -4711,9 +5382,13 @@ START_TEST(win) test_csparentdc(); test_SetWindowLong(); test_ShowWindow(); - test_gettext(); + if (0) test_gettext(); /* crashes on NT4 */ test_GetUpdateRect(); test_Expose(); + test_layered_window(); + + test_SetForegroundWindow(hwndMain); + test_shell_window(); /* add the tests above this line */ UnhookWindowsHookEx(hhook); diff --git a/rostests/winetests/user32/winstation.c b/rostests/winetests/user32/winstation.c index 42f2644b295..efc122a32dc 100755 --- a/rostests/winetests/user32/winstation.c +++ b/rostests/winetests/user32/winstation.c @@ -122,7 +122,9 @@ static void test_handles(void) flags = 0; ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" ); - ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", w1 ); + ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) || + broken(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), /* set on nt4 */ + "handle %p PROTECT_FROM_CLOSE set\n", w1 ); ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); @@ -201,7 +203,11 @@ static void test_handles(void) ok( GetLastError() == ERROR_BUSY, "bad last error %d\n", GetLastError() ); SetLastError( 0xdeadbeef ); - ok( !CloseHandle(d1), "closing thread desktop handle failed\n" ); + if (CloseHandle( d1 )) /* succeeds on nt4 */ + { + win_skip( "NT4 desktop handle management is completely different\n" ); + return; + } ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() ); ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0, -- 2.17.1