On 18.10.2012 21:05, Daniel Santos wrote:
On 10/16/2012 01:12 PM, Christian Costa wrote:
+ /* Choose point inside the client area */
+ point.x = rect.right / 2 - 50;
+ point.y = rect.bottom / 2 - 50;
+ ret = ScreenToClient(wnd, &point);
+ ok(ret, "ScreenToClient failed with %#x\n", GetLastError());
+ ret = MapWindowPoints(NULL, wnd, &point, 1);
+ ok(ret, "MapWindowPoints failed with %#x\n", GetLastError());
+
+ /* Choose point outside the client area */
+ point.x = rect.right / 2 + 50;
+ point.y = rect.bottom / 2 + 50;
+ ret = ScreenToClient(wnd, &point);
+ ok(ret, "ScreenToClient failed with %#x\n", GetLastError());
+ ret = MapWindowPoints(NULL, wnd, &point, 1);
+ ok(ret, "MapWindowPoints failed with %#x\n", GetLastError());
When I do these tests, I like throwing every stupid thing I can possibly
come up with (and I'm gifted and coming up with stupid things) but
always get shot down because I can't produce an example of a real-world
app doing it. So here's one from LoTRO:
8.385:0009:Call user32.ScreenToClient(00000000,0033fd68) ret=006d4d87
And if you don't return zero when it does this, the game crashes
resulting in my in-box filling up from desperate game addicts posting to
appdb.
So if you can please include the below in your patch, I can omit it from
mine (see http://bugs.winehq.org/show_bug.cgi?id=31979) and thank you!
+ /* LoTRO will do this and crash if we don't return zero, precious indeed!
*/
+ ret = ScreenToClient( NULL, &point );
+ ok(!ret, "ScreenToClient didn't fail as expected (got %d)\n", ret);
Daniel
Please, be a bit more patient. The problem is known since end of August
and no one filed a bug for it. Even I asked the guy in #winehq after
creating the initial hack to file a bug for it. (Someone with a log from
the channel from 29/30. August might look up the details / logs) I
didn't send the patch, because it's only a hack and I wasn't able to
produce a nice test case and later forgot about it.
I was stuck at the different returned point results for different win
versions (see https://testbot.winehq.org/JobDetails.pl?Key=22315 - I
used uitools instead of win there to get a smaller log). So someone with
some more knowledge in that area needs to gave a hint to make a nice
test. Nevertheless attached is my latest version of the test and
implementation, but be warned, it is still not ready to be send to
wine-patches.
If I remember correctly, lotro doesn't need the Get/SetLastError part,
but I added it anyway. It may be split out and added in a later patch,
Cheers
Rico
commit add782bc2eee075b5658b484795467a1e106ac5d
Author: Rico Schüller <kgbric...@web.de>
Date: Thu Aug 30 22:39:31 2012 +0200
winpos
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index e84824d..2f86807 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -7104,6 +7104,190 @@ todo_wine
ok(ret, "UnregisterClass(my_window) failed\n");
}
+static void test_MapWindowPoints(void)
+{
+ BOOL ret;
+ POINT p;
+ HWND wnd, dwnd;
+ INT n;
+ DWORD err;
+
+ /* create test window */
+ wnd = CreateWindow("static", "test", 100, 200, 150, 150, 0, NULL, NULL, NULL, NULL);
+ ok(wnd != NULL, "Failed %p\n", wnd);
+ dwnd = CreateWindow("static", "test", 200, 300, 150, 150, 0, NULL, NULL, NULL, NULL);
+ DestroyWindow(dwnd);
+ ok(dwnd != NULL, "Failed %p\n", dwnd);
+
+ SetLastError(0xdeadbeef);
+ n = MapWindowPoints(NULL, NULL, NULL, 0);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ ret = ClientToScreen(NULL, NULL);
+ err = GetLastError();
+ ok(!ret, "Failed\n");
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ ret = ScreenToClient(NULL, NULL);
+ err = GetLastError();
+ ok(!ret, "Failed\n");
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ n = MapWindowPoints(wnd, NULL, NULL, 0);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ n = MapWindowPoints(NULL, wnd, NULL, 0);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ n = MapWindowPoints(wnd, wnd, NULL, 0);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ /*
+ * These crash on xp:
+ * MapWindowPoints(NULL, NULL, NULL, 1);
+ * MapWindowPoints(wnd, NULL, NULL, 1);
+ * ClientToScreen(wnd, NULL);
+ * MapWindowPoints(NULL, wnd, NULL, 1);
+ * ScreenToClient(wnd, NULL);
+ * MapWindowPoints(wnd, wnd, NULL, 1);
+ */
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(NULL, NULL, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ ret = ScreenToClient(NULL, &p);
+ err = GetLastError();
+ ok(!ret, "Failed\n");
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ ret = ClientToScreen(NULL, &p);
+ err = GetLastError();
+ ok(!ret, "Failed\n");
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(NULL, wnd, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ ret = ScreenToClient(wnd, &p);
+ err = GetLastError();
+ ok(ret, "Failed\n");
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(NULL, dwnd, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ ret = ScreenToClient(dwnd, &p);
+ err = GetLastError();
+ ok(ret == FALSE, "Failed\n");
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(wnd, NULL, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ ret = ClientToScreen(wnd, &p);
+ err = GetLastError();
+ ok(ret, "Failed\n");
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(dwnd, NULL, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ ret = ClientToScreen(dwnd, &p);
+ err = GetLastError();
+ ok(!ret, "Failed\n");
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(wnd, wnd, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(dwnd, dwnd, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(dwnd, wnd, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ SetLastError(0xdeadbeef);
+ p.x = p.y = 100;
+ n = MapWindowPoints(wnd, dwnd, &p, 1);
+ err = GetLastError();
+ ok(n == 0, "Got %d, expected %d\n", n, 0);
+ ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
+ ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
+
+ DestroyWindow(wnd);
+}
+
START_TEST(win)
{
HMODULE user32 = GetModuleHandleA( "user32.dll" );
@@ -7213,6 +7397,8 @@ START_TEST(win)
test_handles( hwndMain );
test_winregion();
+ test_MapWindowPoints();
+
/* add the tests above this line */
if (hhook) UnhookWindowsHookEx(hhook);
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 5a2f1f2..2251109 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -240,8 +240,12 @@ BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
*/
BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
{
- MapWindowPoints( hwnd, 0, lppnt, 1 );
- return TRUE;
+ if (!hwnd)
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return FALSE;
+ }
+ return MapWindowPoints( hwnd, 0, lppnt, 1 ) != 0;
}
@@ -250,8 +254,12 @@ BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
*/
BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
{
- MapWindowPoints( 0, hwnd, lppnt, 1 );
- return TRUE;
+ if (!hwnd)
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return FALSE;
+ }
+ return MapWindowPoints( 0, hwnd, lppnt, 1 ) != 0;
}
@@ -557,9 +565,17 @@ void map_window_region( HWND from, HWND to, HRGN hrgn )
INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
{
BOOL mirrored;
- POINT offset = WINPOS_GetWinOffset( hwndFrom, hwndTo, &mirrored );
+ POINT offset;
UINT i;
+ if ((hwndFrom && !IsWindow( hwndFrom )) || (hwndTo && !IsWindow( hwndTo )))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return 0;
+ }
+
+ offset = WINPOS_GetWinOffset( hwndFrom, hwndTo, &mirrored );
+
for (i = 0; i < count; i++)
{
lppt[i].x += offset.x;