From: Daniel Lehman Subject: gdi32: use HandleToULong inline function to convert handle to index instead of casting (try 2) Message-Id: <2EE9C16F5A58104387BC411DC1EFA8F902FD0E@RED-INF-EXMB-P1.esri.com> Date: Thu, 11 Oct 2012 21:45:57 +0000 > This would need some test cases. > > -- > Alexandre Julliard > julliard@winehq.org Try2: - added tests - used HandleToUlong in free_gdi_handle found that test fails unless it's added there as well From 241e04f421cd14f59a7f5a7487bdd49cbc7d0b98 Mon Sep 17 00:00:00 2001 From: Daniel Lehman Date: Mon, 16 Apr 2012 14:53:43 -0700 Subject: [PATCH] gdi32: use HandleToULong inline function to convert handle to index instead of casting if the handle has 1's in the upper 32-bits, the cast and shift creates an invalid index 0xffffffff000026a8 becomes 0xc00009aa instead of just 0x9aa --- dlls/gdi32/gdiobj.c | 4 ++-- dlls/gdi32/tests/gdiobj.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c index 14ac692..06279dd 100644 --- a/dlls/gdi32/gdiobj.c +++ b/dlls/gdi32/gdiobj.c @@ -699,7 +699,7 @@ void *free_gdi_handle( HGDIOBJ handle ) GDIOBJHDR *object = NULL; int i; - i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE; + i = (HandleToULong(handle) >> 2) - FIRST_LARGE_HANDLE; if (i >= 0 && i < MAX_LARGE_HANDLES) { EnterCriticalSection( &gdi_section ); @@ -732,7 +732,7 @@ void *GDI_GetObjPtr( HGDIOBJ handle, WORD type ) EnterCriticalSection( &gdi_section ); - i = ((UINT_PTR)handle >> 2) - FIRST_LARGE_HANDLE; + i = (HandleToULong(handle) >> 2) - FIRST_LARGE_HANDLE; if (i >= 0 && i < MAX_LARGE_HANDLES) { ptr = large_handles[i]; diff --git a/dlls/gdi32/tests/gdiobj.c b/dlls/gdi32/tests/gdiobj.c index c854311..c160b9c 100644 --- a/dlls/gdi32/tests/gdiobj.c +++ b/dlls/gdi32/tests/gdiobj.c @@ -319,10 +319,48 @@ static void test_region(void) DeleteObject(hrgn); } +static void test_handles_on_x64(void) +{ + int i; + BOOL ret; + HRGN hrgn, hrgn_test; + struct test_handles + { + ULONGLONG bits; + BOOL ret; + }; + + struct test_handles cases[] = + { + { 0x0000000000000000, TRUE }, + { 0x000000000000ffe0, FALSE }, /* just over MAX_LARGE_HANDLES */ + { 0x000000000000ffb0, FALSE }, /* just under MAX_LARGE_HANDLES */ + { 0xffffffffffff0000, FALSE }, + { 0xffffffff00000000, TRUE }, + { 0xdeadbeef00000000, TRUE }, + { 0xcccccccccccccccc, FALSE } + }; + + if (sizeof(void*) != 8) + return; + + for (i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) + { + hrgn = CreateRectRgn(10, 10, 20, 20); + hrgn_test = (HRGN)(SIZE_T)((SIZE_T)hrgn | cases[i].bits); + ret = DeleteObject(hrgn_test); + ok( cases[i].ret == ret, "DeleteObject should return %s (%p)\n", + cases[i].ret ? "TRUE" : "FALSE", hrgn_test); + /* actually free it if above is expected to fail */ + if (!ret) DeleteObject(hrgn); + } +} + START_TEST(gdiobj) { test_gdi_objects(); test_thread_objects(); test_GetCurrentObject(); test_region(); + test_handles_on_x64(); } -- 1.7.12.3