forked from Mirrors/wine-wine
user32: Fix icon extraction from non-native PE executables.
parent
d25be83c0a
commit
ba40509f90
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue