[USER32] Fix F1'97 Demo icon not showing in explorer (#5268)

Fixes the F1'97 Demo program (a racing game) not showing an icon in explorer.
This fixes a very special kind of icons which are embedded into the
executable by ancient Watcom C/C++ compilers.
Windows XP/2k3sp2 can show that icon.
Windows Vista/7 cannot show that icon.

Due to the different behavior of the various Windows versions, we
also added a testcase for our bots to protect that functionality in the future,
we committed that test by 0.4.15-dev-7076-g c00d41d91c (#6020)

JIRA issue: CORE-10726
This commit is contained in:
Doug Lyons 2023-11-27 11:02:08 -06:00 committed by GitHub
parent f630bbce0a
commit 75c67f9b51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -743,9 +743,78 @@ static UINT ICO_ExtractIconExW(
xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
if( !xresdir )
{
#ifdef __REACTOS__
/* XP/2K3 can decode icons this way. Vista/7 cannot. This handles
* damaged Resources in 'Icon Group' by falling back to 'Icon' resources.
* Older Watcom C/C++ compilers can generate such a case */
const IMAGE_RESOURCE_DIRECTORY *resdir;
WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
/* Try to get an icon by walking the files Resource Section */
if (iconresdir->NumberOfIdEntries > 0)
{
xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)
(ULONG_PTR)(iconresdir + 1);
}
else
{
RetPtr[i] = 0;
continue;
}
/* Get the Resource Directory */
resdir = (const IMAGE_RESOURCE_DIRECTORY *)
((const char *)rootresdir + xresent->OffsetToDirectory);
if (resdir->NumberOfIdEntries > 0) // Do we have entries
{
xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)
(ULONG_PTR)(resdir + 1);
}
else
{
RetPtr[i] = 0;
continue;
}
/* Retrieve the data entry and find its address */
igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)
((const char *)rootresdir + xresent->OffsetToData);
idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage),
(HMODULE)peimage, igdataent->OffsetToData, NULL);
if (!idata)
{
RetPtr[i] = 0;
continue;
}
/* Check to see if this looks like an icon bitmap */
if (idata[0] == sizeof(BITMAPINFOHEADER))
{
BITMAPINFOHEADER bmih;
RtlCopyMemory(&bmih, idata, sizeof(BITMAPINFOHEADER));
/* Do the Width and Height look correct for an icon */
if ((bmih.biWidth * 2) == bmih.biHeight)
{
RetPtr[0] = CreateIconFromResourceEx(idata, igdataent->Size,
TRUE, 0x00030000, cx1, cy1, flags);
if (cx2 && cy2)
RetPtr[1] = CreateIconFromResourceEx(idata, idataent->Size,
TRUE, 0x00030000, cx2, cy2, flags);
ret = 1; // Set number of icons found
goto end; // Success so Exit
}
}
else
{
RetPtr[i] = 0;
continue;
}
#else
WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
RetPtr[i]=0;
continue;
#endif
}
xresdir = find_entry_default(xresdir, rootresdir);
idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;