Commit 36366f12 authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

win32u: Find the correct DIB driver in windrv_CreateDC().

push_dc_driver() places drivers based on their priorities, so the newly created driver is not necessarily on top. Thus in windrv_CreateDC(), find_dc_driver() should be used to find the DIB driver instead of assuming the DIB driver is the top driver, which could be the path driver because it has a higher priority. The exact wrong code path was: 1. A path driver with priority 400 is created for a DC. 2. windrv_CreateDC() is called to create a window driver for the DC. 3. Then in dibdrv_CreateDC(), push_dc_driver() is called with 'dev' pointing to the top driver, which is the path driver. 4. push_dc_driver() updates 'dev' to point to the address of the next driver because DIB driver has a lower 300 priority. 5. The DIB driver is assigned to 'dev', which is not the original parameter passed into push_dc_driver(). 6. In windrv_CreateDC(), get_dibdrv_pdev(*dev) is called, assuming the top driver is the DIB driver. But actually the top driver that '*dev' points to is still the path driver. The added tests can demonstrate the memory corruption before this fix is applied.
parent 9aefdbb9
......@@ -607,6 +607,7 @@ static void test_polydraw(void)
BOOL retb;
POINT pos;
HDC hdc = GetDC(0);
HWND hwnd;
MoveToEx( hdc, -20, -20, NULL );
......@@ -620,7 +621,8 @@ static void test_polydraw(void)
{
/* PolyDraw is only available on Win2k and later */
win_skip("PolyDraw is not available\n");
goto done;
ReleaseDC(0, hdc);
return;
}
expect(TRUE, retb);
GetCurrentPositionEx( hdc, &pos );
......@@ -684,8 +686,20 @@ static void test_polydraw(void)
ok_path(hdc, "polydraw_path", polydraw_path, ARRAY_SIZE(polydraw_path));
GetCurrentPositionEx( hdc, &pos );
ok( pos.x == 80 && pos.y == 80, "wrong pos %ld,%ld\n", pos.x, pos.y );
done:
ReleaseDC(0, hdc);
/* Test a special case that GDI path driver is created before window driver */
hwnd = CreateWindowA("static", NULL, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
hdc = GetDC(hwnd);
BeginPath(hdc);
SetWindowPos(hwnd, 0, 0, 0, 100, 100, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);
retb = PolyDraw(hdc, polydraw_pts, polydraw_tps, 2);
ok(retb, "PolyDraw failed, error %#lx\n", GetLastError());
EndPath(hdc);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
}
static void test_closefigure(void) {
......
......@@ -871,6 +871,8 @@ static BOOL windrv_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
static BOOL windrv_CreateDC( PHYSDEV *dev, LPCWSTR device, LPCWSTR output, const DEVMODEW *devmode )
{
struct windrv_physdev *physdev = calloc( 1, sizeof(*physdev) );
PHYSDEV dibdrv;
DC *dc;
if (!physdev) return FALSE;
......@@ -879,7 +881,9 @@ static BOOL windrv_CreateDC( PHYSDEV *dev, LPCWSTR device, LPCWSTR output, const
free( physdev );
return FALSE;
}
physdev->dibdrv = get_dibdrv_pdev( *dev );
dc = get_physdev_dc( *dev );
dibdrv = find_dc_driver( dc, &dib_driver );
physdev->dibdrv = get_dibdrv_pdev( dibdrv );
push_dc_driver( dev, &physdev->dev, &window_driver );
return TRUE;
}
......
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