Commit ba40509f authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

user32: Fix icon extraction from non-native PE executables.

parent d25be83c
...@@ -420,46 +420,18 @@ static UINT ICO_ExtractIconExW( ...@@ -420,46 +420,18 @@ static UINT ICO_ExtractIconExW(
/* exe/dll */ /* exe/dll */
else if( sig == IMAGE_NT_SIGNATURE ) else if( sig == IMAGE_NT_SIGNATURE )
{ {
LPBYTE idata,igdata; BYTE *idata, *igdata;
PIMAGE_DOS_HEADER dheader; const IMAGE_RESOURCE_DIRECTORY *rootresdir, *iconresdir, *icongroupresdir;
PIMAGE_NT_HEADERS pe_header; const IMAGE_RESOURCE_DATA_ENTRY *idataent, *igdataent;
PIMAGE_SECTION_HEADER pe_sections;
const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir;
const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent;
const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent; const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
UINT i, j; ULONG size;
UINT i;
dheader = (PIMAGE_DOS_HEADER)peimage;
pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew); /* it is a pe header, USER32_GetResourceTable checked that */
pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER)
+ pe_header->FileHeader.SizeOfOptionalHeader);
rootresdir = NULL;
/* search for the root resource directory */
for (i=0;i<pe_header->FileHeader.NumberOfSections;i++)
{
if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
continue;
if (fsizel < pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData) {
FIXME("File %s too short (section is at %d bytes, real size is %d)\n",
debugstr_w(lpszExeFileName),
pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData,
fsizel
);
goto end;
}
/* FIXME: doesn't work when the resources are not in a separate section */
if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)
{
rootresdir = (PIMAGE_RESOURCE_DIRECTORY)(peimage+pe_sections[i].PointerToRawData);
break;
}
}
rootresdir = RtlImageDirectoryEntryToData((HMODULE)peimage, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
if (!rootresdir) if (!rootresdir)
{ {
WARN("haven't found section for resource directory.\n"); WARN("haven't found section for resource directory.\n");
goto end; /* failure */ goto end;
} }
/* search for the group icon directory */ /* search for the group icon directory */
...@@ -529,23 +501,7 @@ static UINT ICO_ExtractIconExW( ...@@ -529,23 +501,7 @@ static UINT ICO_ExtractIconExW(
igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir; igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;
/* lookup address in mapped image for virtual address */ /* lookup address in mapped image for virtual address */
igdata = NULL; igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL);
for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
{
if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
continue;
if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
continue;
if (igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData+igdataent->Size > fsizel) {
FIXME("overflow in PE lookup (%s has len %d, have offset %d), short file?\n", debugstr_w(lpszExeFileName), fsizel,
igdataent->OffsetToData - pe_sections[j].VirtualAddress + pe_sections[j].PointerToRawData + igdataent->Size);
goto end; /* failure */
}
igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
}
if (!igdata) if (!igdata)
{ {
FIXME("no matching real address for icongroup!\n"); FIXME("no matching real address for icongroup!\n");
...@@ -573,17 +529,8 @@ static UINT ICO_ExtractIconExW( ...@@ -573,17 +529,8 @@ static UINT ICO_ExtractIconExW(
} }
xresdir = find_entry_default(xresdir, rootresdir); xresdir = find_entry_default(xresdir, rootresdir);
idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir; idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;
idata = NULL;
/* map virtual to address in image */ idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL);
for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
{
if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
continue;
if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
continue;
idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
}
if (!idata) if (!idata)
{ {
WARN("no matching real address found for icondata!\n"); WARN("no matching real address found for icondata!\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment