Dmitry Timoshkov : user32: DeleteDC() should allow to delete a DC returned by GetDC().

Alexandre Julliard julliard at winehq.org
Wed Feb 24 10:21:35 CST 2010


Module: wine
Branch: master
Commit: d6cfc3223ef8861830237fe415667a5ba73231d2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d6cfc3223ef8861830237fe415667a5ba73231d2

Author: Dmitry Timoshkov <dmitry at 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;




More information about the wine-cvs mailing list