From 75c67f9b515117b730a84800b7c0b5bf65ed192c Mon Sep 17 00:00:00 2001 From: Doug Lyons Date: Mon, 27 Nov 2023 11:02:08 -0600 Subject: [PATCH] [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 c00d41d91c181746563e689d3390228f703053f5 (#6020) JIRA issue: CORE-10726 --- win32ss/user/user32/misc/exticon.c | 69 ++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/win32ss/user/user32/misc/exticon.c b/win32ss/user/user32/misc/exticon.c index 2afd6e6d975..fec6103b2bb 100644 --- a/win32ss/user/user32/misc/exticon.c +++ b/win32ss/user/user32/misc/exticon.c @@ -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;