1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Test for LoadImageW using DLL compiled with MSVC
5  * COPYRIGHT:   Copyright 2024 Doug Lyons <douglyons@douglyons.com>
6  *
7  * NOTES:
8  * Works on ReactOS, but not on Windows 2003 Server SP2.
9  */
10 
11 #include "precomp.h"
12 #include "resource.h"
13 #include <stdio.h>
14 #include <versionhelpers.h>
15 
FileExistsW(PCWSTR FileName)16 BOOL FileExistsW(PCWSTR FileName)
17 {
18     DWORD Attribute = GetFileAttributesW(FileName);
19 
20     return (Attribute != INVALID_FILE_ATTRIBUTES &&
21             !(Attribute & FILE_ATTRIBUTE_DIRECTORY));
22 }
23 
ResourceToFileW(INT i,PCWSTR FileName)24 BOOL ResourceToFileW(INT i, PCWSTR FileName)
25 {
26     FILE *fout;
27     HGLOBAL hData;
28     HRSRC hRes;
29     PVOID pResLock;
30     UINT iSize;
31 
32     if (FileExistsW(FileName))
33     {
34         /* We should only be using %temp% paths, so deleting here should be OK */
35         printf("Deleting '%S' that already exists.\n", FileName);
36         DeleteFileW(FileName);
37     }
38 
39     hRes = FindResourceW(NULL, MAKEINTRESOURCEW(i), MAKEINTRESOURCEW(RT_RCDATA));
40     if (hRes == NULL)
41     {
42         skip("Could not locate resource (%d). Exiting now\n", i);
43         return FALSE;
44     }
45 
46     iSize = SizeofResource(NULL, hRes);
47 
48     hData = LoadResource(NULL, hRes);
49     if (hData == NULL)
50     {
51         skip("Could not load resource (%d). Exiting now\n", i);
52         return FALSE;
53     }
54 
55     // Lock the resource into global memory.
56     pResLock = LockResource(hData);
57     if (pResLock == NULL)
58     {
59         skip("Could not lock resource (%d). Exiting now\n", i);
60         return FALSE;
61     }
62 
63     fout = _wfopen(FileName, L"wb");
64     fwrite(pResLock, iSize, 1, fout);
65     fclose(fout);
66     return TRUE;
67 }
68 
69 static struct
70 {
71     PCWSTR FileName;
72     INT ResourceId;
73 } DataFiles[] =
74 {
75     {L"%SystemRoot%\\bin\\image.dll", IDR_DLL_NORMAL},
76 };
77 
78 
START_TEST(LoadImageGCC)79 START_TEST(LoadImageGCC)
80 {
81     UINT i;
82     WCHAR PathBuffer[MAX_PATH];
83     static HBITMAP hBmp;
84     HANDLE handle;
85     HDC hdcMem;
86     BITMAP bitmap;
87     BITMAPINFO bmi;
88     HGLOBAL hMem;
89     LPVOID lpBits;
90     CHAR img[8] = { 0 };
91     UINT size;
92 
93     /* Windows 2003 cannot run this test. Testman shows CRASH, so skip it. */
94     if (!IsReactOS())
95         return;
96 
97     /* Extract Data Files */
98     for (i = 0; i < _countof(DataFiles); ++i)
99     {
100         ExpandEnvironmentStringsW(DataFiles[i].FileName, PathBuffer, _countof(PathBuffer));
101 
102         if (!ResourceToFileW(DataFiles[i].ResourceId, PathBuffer))
103         {
104             printf("ResourceToFile Failed. Exiting now\n");
105             goto Cleanup;
106         }
107     }
108 
109     handle = LoadLibraryExW(PathBuffer, NULL, LOAD_LIBRARY_AS_DATAFILE);
110     hBmp = (HBITMAP)LoadImage(handle, MAKEINTRESOURCE(130), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
111 
112     hdcMem = CreateCompatibleDC(NULL);
113     SelectObject(hdcMem, hBmp);
114     GetObject(hBmp, sizeof(BITMAP), &bitmap);
115 
116     memset(&bmi, 0, sizeof(bmi));
117     memset(&bmi, 0, sizeof(bmi));
118     bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
119     bmi.bmiHeader.biWidth       = bitmap.bmWidth;
120     bmi.bmiHeader.biHeight      = bitmap.bmHeight;
121     bmi.bmiHeader.biPlanes      = bitmap.bmPlanes;
122     bmi.bmiHeader.biBitCount    = bitmap.bmBitsPixel;
123     bmi.bmiHeader.biCompression = BI_RGB;
124     bmi.bmiHeader.biSizeImage   = 0;
125 
126     size = ((bitmap.bmWidth * bmi.bmiHeader.biBitCount + 31) / 32) * 4 * bitmap.bmHeight;
127 
128     hMem = GlobalAlloc(GMEM_MOVEABLE, size);
129     lpBits = GlobalLock(hMem);
130     GetDIBits(hdcMem, hBmp, 0, bitmap.bmHeight, lpBits, &bmi, DIB_RGB_COLORS);
131 
132     /* Get first 8 bytes of second row of bits from bitmap */
133     memcpy(img, (VOID *)((INT_PTR)lpBits + 4 * bitmap.bmWidth), 8);
134 
135     ok(img[0] == 0, "Byte 0 Bad. Got 0x%02x, expected 0\n", img[0] & 0xff);
136     ok(img[1] == 0, "Byte 1 Bad. Got 0x%02x, expected 0\n", img[1] & 0xff);
137     ok(img[2] == 0, "Byte 2 Bad. Got 0x%02x, expected 0\n", img[2] & 0xff);
138     ok(img[3] == 0, "Byte 3 Bad. Got 0x%02x, expected 0\n", img[3] & 0xff);
139 
140     GlobalUnlock(hMem);
141     GlobalFree(hMem);
142 
143     DeleteDC(hdcMem);
144 
145 Cleanup:
146     for (i = 0; i < _countof(DataFiles); ++i)
147     {
148         ExpandEnvironmentStringsW(DataFiles[i].FileName, PathBuffer, _countof(PathBuffer));
149         DeleteFileW(PathBuffer);
150     }
151 }
152