user32: Fix icon extraction from non-native PE executables. (try 2)

Hans Leidekker hans at codeweavers.com
Thu Jun 6 12:30:05 CDT 2013


This version uses the RtlImage* functions. It doesn't preserve all
validation checks.
---
 dlls/user32/exticon.c |   87 ++++++++++---------------------------------------
 1 file changed, 17 insertions(+), 70 deletions(-)

diff --git a/dlls/user32/exticon.c b/dlls/user32/exticon.c
index 5b9d681..0dbbef1 100644
--- a/dlls/user32/exticon.c
+++ b/dlls/user32/exticon.c
@@ -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;
-
-	  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 */
-	  }
+        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;
+
+        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;
-- 
1.7.10.4






More information about the wine-patches mailing list