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

oldstable
Hans Leidekker 2013-06-06 19:30:05 +02:00 committed by Alexandre Julliard
parent d25be83c0a
commit ba40509f90
1 changed files with 16 additions and 69 deletions

View File

@ -420,47 +420,19 @@ static UINT ICO_ExtractIconExW(
/* exe/dll */
else if( sig == IMAGE_NT_SIGNATURE )
{
LPBYTE idata,igdata;
PIMAGE_DOS_HEADER dheader;
PIMAGE_NT_HEADERS pe_header;
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;
UINT i, j;
BYTE *idata, *igdata;
const IMAGE_RESOURCE_DIRECTORY *rootresdir, *iconresdir, *icongroupresdir;
const IMAGE_RESOURCE_DATA_ENTRY *idataent, *igdataent;
const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
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;
}
}
if (!rootresdir)
{
WARN("haven't found section for resource directory.\n");
goto end; /* failure */
}
rootresdir = RtlImageDirectoryEntryToData((HMODULE)peimage, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
if (!rootresdir)
{
WARN("haven't found section for resource directory.\n");
goto end;
}
/* search for the group icon directory */
if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir)))
@ -529,24 +501,8 @@ static UINT ICO_ExtractIconExW(
igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;
/* lookup address in mapped image for virtual address */
igdata = 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)
igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL);
if (!igdata)
{
FIXME("no matching real address for icongroup!\n");
goto end; /* failure */
@ -573,18 +529,9 @@ static UINT ICO_ExtractIconExW(
}
xresdir = find_entry_default(xresdir, rootresdir);
idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;
idata = NULL;
/* map virtual to address in image */
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)
idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL);
if (!idata)
{
WARN("no matching real address found for icondata!\n");
RetPtr[i]=0;