Commit d6cfc322 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

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

parent e7c909a1
...@@ -819,7 +819,7 @@ BOOL WINAPI DeleteDC( HDC hdc ) ...@@ -819,7 +819,7 @@ BOOL WINAPI DeleteDC( HDC hdc )
if (dc->hookProc && !dc->hookProc( hdc, DCHC_DELETEDC, dc->dwHookData, 0 )) if (dc->hookProc && !dc->hookProc( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ))
{ {
release_dc_ptr( dc ); release_dc_ptr( dc );
return FALSE; return TRUE;
} }
while (dc->saveLevel) while (dc->saveLevel)
......
...@@ -69,7 +69,7 @@ static void test_savedc_2(void) ...@@ -69,7 +69,7 @@ static void test_savedc_2(void)
assert(hrgn != 0); assert(hrgn != 0);
hdc = GetDC(hwnd); hdc = GetDC(hwnd);
ok(hdc != NULL, "CreateDC rets %p\n", hdc); ok(hdc != NULL, "GetDC failed\n");
ret = GetClipBox(hdc, &rc_clip); ret = GetClipBox(hdc, &rc_clip);
ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret); ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
...@@ -328,6 +328,155 @@ static void test_DC_bitmap(void) ...@@ -328,6 +328,155 @@ static void test_DC_bitmap(void)
ReleaseDC( 0, hdc ); 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) START_TEST(dc)
{ {
test_savedc(); test_savedc();
...@@ -335,4 +484,5 @@ START_TEST(dc) ...@@ -335,4 +484,5 @@ START_TEST(dc)
test_GdiConvertToDevmodeW(); test_GdiConvertToDevmodeW();
test_CreateCompatibleDC(); test_CreateCompatibleDC();
test_DC_bitmap(); test_DC_bitmap();
test_DeleteDC();
} }
...@@ -296,6 +296,7 @@ static struct dce *get_window_dce( HWND hwnd ) ...@@ -296,6 +296,7 @@ static struct dce *get_window_dce( HWND hwnd )
{ {
win->dce = dce; win->dce = dce;
dce->hwnd = hwnd; dce->hwnd = hwnd;
dce->count++;
list_add_tail( &dce_list, &dce->entry ); list_add_tail( &dce_list, &dce->entry );
} }
WIN_ReleasePtr( win ); WIN_ReleasePtr( win );
...@@ -495,7 +496,7 @@ static BOOL CALLBACK dc_hook( HDC hDC, WORD code, DWORD_PTR data, LPARAM lParam ...@@ -495,7 +496,7 @@ static BOOL CALLBACK dc_hook( HDC hDC, WORD code, DWORD_PTR data, LPARAM lParam
* (between GetDC and ReleaseDC) * (between GetDC and ReleaseDC)
*/ */
USER_Lock(); USER_Lock();
if (dce->count) if (dce->count > 1)
{ {
WARN("Application trying to delete a busy DC %p\n", dce->hdc); WARN("Application trying to delete a busy DC %p\n", dce->hdc);
retv = FALSE; retv = FALSE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment