diff --git a/win32ss/gdi/gdi32/objects/bitmap.c b/win32ss/gdi/gdi32/objects/bitmap.c index 332aacb31ec..e3813d3e561 100644 --- a/win32ss/gdi/gdi32/objects/bitmap.c +++ b/win32ss/gdi/gdi32/objects/bitmap.c @@ -565,8 +565,10 @@ CreateDIBitmap( goto Exit; } - /* Top-down DIBs have a negative height. */ - Height = abs(Height); + /* Preserve the height sign. Top-down DIBs have a negative height and + * must result in a top-down DDB, as on Windows. Otherwise display + * drivers receive a bottom-up surface with a negative lDelta and crash, + * see CORE-18825. */ // For Icm support. // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr)) diff --git a/win32ss/gdi/ntgdi/bitmaps.c b/win32ss/gdi/ntgdi/bitmaps.c index dd7aa4486e1..10ea4d29bd1 100644 --- a/win32ss/gdi/ntgdi/bitmaps.c +++ b/win32ss/gdi/ntgdi/bitmaps.c @@ -289,12 +289,18 @@ IntCreateCompatibleBitmap( if (Dc->dctype != DCTYPE_MEMORY) { PSURFACE psurf; - - Bmp = GreCreateBitmap(abs(Width), - abs(Height), - Planes ? Planes : 1, - Bpp ? Bpp : Dc->ppdev->gdiinfo.cBitsPixel, - NULL); + ULONG cPlanes = Planes ? Planes : 1; + ULONG cBitsPixel = Bpp ? Bpp : Dc->ppdev->gdiinfo.cBitsPixel; + + /* A negative height means top-down (see CORE-18825) */ + Bmp = GreCreateBitmapEx(abs(Width), + abs(Height), + 0, /* Auto width */ + BitmapFormat(cBitsPixel * cPlanes, BI_RGB), + (Height < 0) ? BMF_TOPDOWN : 0, + 0, /* Auto size */ + NULL, + DDB_SURFACE); if (Bmp == NULL) { DPRINT1("Failed to allocate a bitmap!\n"); @@ -327,12 +333,18 @@ IntCreateCompatibleBitmap( if (Count == sizeof(BITMAP)) { PSURFACE psurfBmp; - - Bmp = GreCreateBitmap(abs(Width), - abs(Height), - Planes ? Planes : 1, - Bpp ? Bpp : dibs.dsBm.bmBitsPixel, - NULL); + ULONG cPlanes = Planes ? Planes : 1; + ULONG cBitsPixel = Bpp ? Bpp : dibs.dsBm.bmBitsPixel; + + /* A negative height means top-down (see CORE-18825) */ + Bmp = GreCreateBitmapEx(abs(Width), + abs(Height), + 0, /* Auto width */ + BitmapFormat(cBitsPixel * cPlanes, BI_RGB), + (Height < 0) ? BMF_TOPDOWN : 0, + 0, /* Auto size */ + NULL, + DDB_SURFACE); if (Bmp == NULL) { DPRINT1("Failed to allocate a bitmap!\n"); diff --git a/win32ss/user/user32/windows/cursoricon.c b/win32ss/user/user32/windows/cursoricon.c index e900060f83b..d40db914056 100644 --- a/win32ss/user/user32/windows/cursoricon.c +++ b/win32ss/user/user32/windows/cursoricon.c @@ -678,16 +678,19 @@ create_alpha_bitmap( ptr[2] = (ptr[2] * alpha) / 255; } - /* Create the bitmap. Set the bitmap info to have the right width and height */ + /* Create the bitmap. Set the bitmap info to have the right width and height. + A negative height creates a top-down bitmap, which is what the alpha + cursor bitmap must be (display drivers expect a positive lDelta, + see CORE-18825). */ if(src_info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { ((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcWidth = width; - ((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcHeight = height; + ((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcHeight = -height; } else { src_info->bmiHeader.biWidth = width; - src_info->bmiHeader.biHeight = height; + src_info->bmiHeader.biHeight = -height; } /* Directly create a 32-bits DDB (thanks to undocumented CreateDIBitmap flag). */ alpha = CreateDIBitmap(hdcScreen, NULL, 2, NULL, src_info, DIB_RGB_COLORS);