[USER32_APITEST] Test MSVC rc.exe compiled 32-bpp BI_BITFIELD bmp (#6755)

* Cleanup and Changes based on reviewer comments
* For failure, show returned and expected values

CORE-17005
This commit is contained in:
Doug Lyons 2024-04-27 13:30:51 -05:00 committed by GitHub
parent ab72bc06d6
commit ffd060295d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 338 additions and 0 deletions

View file

@ -1,3 +1,4 @@
add_subdirectory(makeimg)
list(APPEND SOURCE
AttachThreadInput.c
@ -30,6 +31,7 @@ list(APPEND SOURCE
KbdLayout.c
keybd_event.c
LoadImage.c
LoadImageGCC.c
LookupIconIdFromDirectoryEx.c
MessageStateAnalyzer.c
NextDlgItem.c

View file

@ -0,0 +1,151 @@
/*
* PROJECT: ReactOS API tests
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Test for LoadImageW using DLL compiled with MSVC
* COPYRIGHT: Copyright 2024 Doug Lyons <douglyons@douglyons.com>
*
* NOTES:
* Works on ReactOS, but not on Windows 2003 Server SP2.
*/
#include "precomp.h"
#include "resource.h"
#include <stdio.h>
#include <versionhelpers.h>
BOOL FileExistsW(PCWSTR FileName)
{
DWORD Attribute = GetFileAttributesW(FileName);
return (Attribute != INVALID_FILE_ATTRIBUTES &&
!(Attribute & FILE_ATTRIBUTE_DIRECTORY));
}
BOOL ResourceToFileW(INT i, PCWSTR FileName)
{
FILE *fout;
HGLOBAL hData;
HRSRC hRes;
PVOID pResLock;
UINT iSize;
if (FileExistsW(FileName))
{
/* We should only be using %temp% paths, so deleting here should be OK */
printf("Deleting '%S' that already exists.\n", FileName);
DeleteFileW(FileName);
}
hRes = FindResourceW(NULL, MAKEINTRESOURCEW(i), MAKEINTRESOURCEW(RT_RCDATA));
if (hRes == NULL)
{
skip("Could not locate resource (%d). Exiting now\n", i);
return FALSE;
}
iSize = SizeofResource(NULL, hRes);
hData = LoadResource(NULL, hRes);
if (hData == NULL)
{
skip("Could not load resource (%d). Exiting now\n", i);
return FALSE;
}
// Lock the resource into global memory.
pResLock = LockResource(hData);
if (pResLock == NULL)
{
skip("Could not lock resource (%d). Exiting now\n", i);
return FALSE;
}
fout = _wfopen(FileName, L"wb");
fwrite(pResLock, iSize, 1, fout);
fclose(fout);
return TRUE;
}
static struct
{
PCWSTR FileName;
INT ResourceId;
} DataFiles[] =
{
{L"%SystemRoot%\\bin\\image.dll", IDR_DLL_NORMAL},
};
START_TEST(LoadImageGCC)
{
UINT i;
WCHAR PathBuffer[MAX_PATH];
static HBITMAP hBmp;
HANDLE handle;
HDC hdcMem;
BITMAP bitmap;
BITMAPINFO bmi;
HGLOBAL hMem;
LPVOID lpBits;
CHAR img[8] = { 0 };
UINT size;
/* Windows 2003 cannot run this test. Testman shows CRASH, so skip it. */
if (!IsReactOS())
return;
/* Extract Data Files */
for (i = 0; i < _countof(DataFiles); ++i)
{
ExpandEnvironmentStringsW(DataFiles[i].FileName, PathBuffer, _countof(PathBuffer));
if (!ResourceToFileW(DataFiles[i].ResourceId, PathBuffer))
{
printf("ResourceToFile Failed. Exiting now\n");
goto Cleanup;
}
}
handle = LoadLibraryExW(PathBuffer, NULL, LOAD_LIBRARY_AS_DATAFILE);
hBmp = (HBITMAP)LoadImage(handle, MAKEINTRESOURCE(130), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
hdcMem = CreateCompatibleDC(NULL);
SelectObject(hdcMem, hBmp);
GetObject(hBmp, sizeof(BITMAP), &bitmap);
memset(&bmi, 0, sizeof(bmi));
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bitmap.bmWidth;
bmi.bmiHeader.biHeight = bitmap.bmHeight;
bmi.bmiHeader.biPlanes = bitmap.bmPlanes;
bmi.bmiHeader.biBitCount = bitmap.bmBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
size = ((bitmap.bmWidth * bmi.bmiHeader.biBitCount + 31) / 32) * 4 * bitmap.bmHeight;
hMem = GlobalAlloc(GMEM_MOVEABLE, size);
lpBits = GlobalLock(hMem);
GetDIBits(hdcMem, hBmp, 0, bitmap.bmHeight, lpBits, &bmi, DIB_RGB_COLORS);
/* Get first 8 bytes of second row of bits from bitmap */
memcpy(img, (VOID *)((INT_PTR)lpBits + 4 * bitmap.bmWidth), 8);
ok(img[0] == 0, "Byte 0 Bad. Got 0x%02x, expected 0\n", img[0] & 0xff);
ok(img[1] == 0, "Byte 1 Bad. Got 0x%02x, expected 0\n", img[1] & 0xff);
ok(img[2] == 0, "Byte 2 Bad. Got 0x%02x, expected 0\n", img[2] & 0xff);
ok(img[3] == 0, "Byte 3 Bad. Got 0x%02x, expected 0\n", img[3] & 0xff);
GlobalUnlock(hMem);
GlobalFree(hMem);
DeleteDC(hdcMem);
Cleanup:
for (i = 0; i < _countof(DataFiles); ++i)
{
ExpandEnvironmentStringsW(DataFiles[i].FileName, PathBuffer, _countof(PathBuffer));
DeleteFileW(PathBuffer);
}
}

Binary file not shown.

View file

@ -0,0 +1,13 @@
PROJECT(MAKEIMG)
add_executable(showimg showimg.c)
set_module_type(showimg win32gui UNICODE)
add_importlibs(showimg gdi32 user32 shell32 msvcrt kernel32 ntdll)
add_library(image MODULE image.rc)
set_module_type(image win32dll ENTRYPOINT 0)
add_rostests_file(TARGET showimg)
add_rostests_file(TARGET image)

View file

@ -0,0 +1,4 @@
#define IDB_TEST 130
IDB_TEST BITMAP "test.bmp"

View file

@ -0,0 +1,14 @@
For reference see https://jira.reactos.org/browse/CORE-17005
This should be compiled using MSVC to create the image.dll file for testing.
Also, it creates an interactive showimg.exe program that can be used to verify this file.
After the creation of the image.dll file using MSVC it can be used to create user32_apitest:LoadImageGCC.
Simply copy the MSVC created 'image.dll' into the 'modules\rostests\apitests\user32' subdirectory to use it.
This file already exists there so that this step is not necessary, but only presents another option.
Unfortunately, this test will not work correctly using Windows 2003 Server SP2.
I have not looked into the details of why this is the case, but it works under ReactOS.
This is what is important for now in any case.
Doug Lyons
April 16, 2024

View file

@ -0,0 +1,150 @@
// Released to the Public Domain by Doug Lyons on April 16th, 2024.
#include <windows.h>
#include <stdio.h>
WCHAR szWindowClass[] = L"testclass";
static LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hBmp;
HANDLE handle;
CHAR buffer[32];
switch (message)
{
case WM_CREATE:
{
handle = LoadLibraryExW(L"image.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
sprintf(buffer, "%p", handle);
MessageBoxA(NULL, buffer, "handle", 0);
hBmp = (HBITMAP)LoadImage(handle, MAKEINTRESOURCE(130), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
sprintf(buffer, "%p", hBmp);
MessageBoxA(NULL, buffer, "Bmp", 0);
sprintf(buffer, "%ld", GetLastError());
MessageBoxA(NULL, buffer, "LastError", 0);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc, hdcMem;
BITMAP bitmap;
BITMAPINFO bmi;
hdc = BeginPaint(hWnd, &ps);
HGLOBAL hMem;
LPVOID lpBits;
hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hBmp);
GetObject(hBmp, sizeof(BITMAP), &bitmap);
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bitmap.bmWidth;
bmi.bmiHeader.biHeight = bitmap.bmHeight;
bmi.bmiHeader.biPlanes = bitmap.bmPlanes;
bmi.bmiHeader.biBitCount = bitmap.bmBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
hMem = GlobalAlloc(GMEM_MOVEABLE, ((bitmap.bmWidth *
bmi.bmiHeader.biBitCount + 31) / 32) * 4 * bitmap.bmHeight);
lpBits = GlobalLock(hMem);
GetDIBits(hdc, hBmp, 0, bitmap.bmHeight, lpBits, &bmi, DIB_RGB_COLORS);
// increasing the multiplier makes the image larger
StretchDIBits(hdc, 0, 0, bitmap.bmWidth * 3, bitmap.bmHeight * 3, 0, 0,
bitmap.bmWidth, bitmap.bmHeight,lpBits, &bmi, DIB_RGB_COLORS, SRCCOPY);
GlobalUnlock(hMem);
GlobalFree(hMem);
DeleteDC(hdcMem);
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
static ATOM
MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
static BOOL
InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindowEx(0,
szWindowClass,
L"Bmp test",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
300,
120,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int WINAPI
wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
if (!InitInstance(hInstance, nCmdShow))
return FALSE;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -4,3 +4,4 @@
#define IDR_ICONS_PNG 2000
#define IDR_ICONS_NORMAL 2001
#define IDR_EXE_NORMAL 2002
#define IDR_DLL_NORMAL 2003

View file

@ -32,6 +32,7 @@ extern void func_InitializeLpkHooks(void);
extern void func_KbdLayout(void);
extern void func_keybd_event(void);
extern void func_LoadImage(void);
extern void func_LoadImageGCC(void);
extern void func_LookupIconIdFromDirectoryEx(void);
extern void func_MessageStateAnalyzer(void);
extern void func_NextDlgItem(void);
@ -91,6 +92,7 @@ const struct test winetest_testlist[] =
{ "KbdLayout", func_KbdLayout },
{ "keybd_event", func_keybd_event },
{ "LoadImage", func_LoadImage },
{ "LoadImageGCC", func_LoadImageGCC },
{ "LookupIconIdFromDirectoryEx", func_LookupIconIdFromDirectoryEx },
{ "MessageStateAnalyzer", func_MessageStateAnalyzer },
{ "NextDlgItem", func_NextDlgItem },

View file

@ -11,6 +11,7 @@ TESTCURSOR CURSOR "test.cur"
IDR_ICONS_PNG RCDATA "ROS.ico"
IDR_ICONS_NORMAL RCDATA "sysicon.ico"
IDR_EXE_NORMAL RCDATA "cpimg2e.exe"
IDR_DLL_NORMAL RCDATA "image.dll"
TESTDIALOG DIALOG 0,0, 200,200
CLASS "TestDialogClass"