Module: wine Branch: master Commit: d6cfc3223ef8861830237fe415667a5ba73231d2 URL: http://source.winehq.org/git/wine.git/?a=commit;h=d6cfc3223ef8861830237fe415...
Author: Dmitry Timoshkov dmitry@codeweavers.com Date: Wed Feb 24 22:44:41 2010 +0800
user32: DeleteDC() should allow to delete a DC returned by GetDC().
---
dlls/gdi32/dc.c | 2 +- dlls/gdi32/tests/dc.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++- dlls/user32/painting.c | 3 +- 3 files changed, 154 insertions(+), 3 deletions(-)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 2aeeec2..577c151 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -819,7 +819,7 @@ BOOL WINAPI DeleteDC( HDC hdc ) if (dc->hookProc && !dc->hookProc( hdc, DCHC_DELETEDC, dc->dwHookData, 0 )) { release_dc_ptr( dc ); - return FALSE; + return TRUE; }
while (dc->saveLevel) diff --git a/dlls/gdi32/tests/dc.c b/dlls/gdi32/tests/dc.c index 1efde38..43c2480 100644 --- a/dlls/gdi32/tests/dc.c +++ b/dlls/gdi32/tests/dc.c @@ -69,7 +69,7 @@ static void test_savedc_2(void) assert(hrgn != 0);
hdc = GetDC(hwnd); - ok(hdc != NULL, "CreateDC rets %p\n", hdc); + ok(hdc != NULL, "GetDC failed\n");
ret = GetClipBox(hdc, &rc_clip); ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret); @@ -328,6 +328,155 @@ static void test_DC_bitmap(void) ReleaseDC( 0, hdc ); }
+static void test_DeleteDC(void) +{ + HWND hwnd; + HDC hdc, hdc_test; + WNDCLASSEX cls; + int ret; + + /* window DC */ + hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100, + 0, 0, 0, NULL); + ok(hwnd != 0, "CreateWindowExA failed\n"); + + hdc = GetDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + hdc = GetWindowDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + DestroyWindow(hwnd); + + /* desktop window DC */ + hwnd = GetDesktopWindow(); + ok(hwnd != 0, "GetDesktopWindow failed\n"); + + hdc = GetDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + hdc = GetWindowDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + /* CS_CLASSDC */ + memset(&cls, 0, sizeof(cls)); + cls.cbSize = sizeof(cls); + cls.style = CS_CLASSDC; + cls.hInstance = GetModuleHandle(0); + cls.lpszClassName = "Wine class DC"; + cls.lpfnWndProc = DefWindowProcA; + ret = RegisterClassExA(&cls); + ok(ret, "RegisterClassExA failed\n"); + + hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100, + 0, 0, 0, NULL); + ok(hwnd != 0, "CreateWindowExA failed\n"); + + hdc = GetDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = ReleaseDC(hwnd, hdc); + ok(ret, "ReleaseDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + + hdc_test = hdc; + + hdc = GetWindowDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + DestroyWindow(hwnd); + + ret = GetObjectType(hdc_test); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + + ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL)); + ok(ret, "UnregisterClassA failed\n"); + + ret = GetObjectType(hdc_test); +todo_wine + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + /* CS_OWNDC */ + memset(&cls, 0, sizeof(cls)); + cls.cbSize = sizeof(cls); + cls.style = CS_OWNDC; + cls.hInstance = GetModuleHandle(0); + cls.lpszClassName = "Wine own DC"; + cls.lpfnWndProc = DefWindowProcA; + ret = RegisterClassExA(&cls); + ok(ret, "RegisterClassExA failed\n"); + + hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100, + 0, 0, 0, NULL); + ok(hwnd != 0, "CreateWindowExA failed\n"); + + hdc = GetDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = ReleaseDC(hwnd, hdc); + ok(ret, "ReleaseDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + + hdc = GetWindowDC(hwnd); + ok(hdc != 0, "GetDC failed\n"); + ret = GetObjectType(hdc); + ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); + ret = DeleteDC(hdc); + ok(ret, "DeleteDC failed\n"); + ret = GetObjectType(hdc); + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + DestroyWindow(hwnd); + + ret = GetObjectType(hdc_test); + ok(!ret, "GetObjectType should fail for a deleted DC\n"); + + ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL)); + ok(ret, "UnregisterClassA failed\n"); +} + START_TEST(dc) { test_savedc(); @@ -335,4 +484,5 @@ START_TEST(dc) test_GdiConvertToDevmodeW(); test_CreateCompatibleDC(); test_DC_bitmap(); + test_DeleteDC(); } diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index cde642c..732c889 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -296,6 +296,7 @@ static struct dce *get_window_dce( HWND hwnd ) { win->dce = dce; dce->hwnd = hwnd; + dce->count++; list_add_tail( &dce_list, &dce->entry ); } WIN_ReleasePtr( win ); @@ -495,7 +496,7 @@ static BOOL CALLBACK dc_hook( HDC hDC, WORD code, DWORD_PTR data, LPARAM lParam * (between GetDC and ReleaseDC) */ USER_Lock(); - if (dce->count) + if (dce->count > 1) { WARN("Application trying to delete a busy DC %p\n", dce->hdc); retv = FALSE;