ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

exticon.c
Go to the documentation of this file.
00001 /*
00002  *  icon extracting
00003  *
00004  * taken and slightly changed from shell
00005  * this should replace the icon extraction code in shell32 and shell16 once
00006  * it needs a serious test for compliance with the native API
00007  *
00008  * Copyright 2000 Juergen Schmied
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 
00025 #include <user32.h>
00026 
00027 #include <wine/debug.h>
00028 
00029 /* Start of Hack section */
00030 
00031 WINE_DEFAULT_DEBUG_CHANNEL(icon);
00032 
00033 #include "pshpack1.h"
00034 
00035 typedef struct
00036 {
00037     BYTE        bWidth;          /* Width, in pixels, of the image  */
00038     BYTE        bHeight;         /* Height, in pixels, of the image */
00039     BYTE        bColorCount;     /* Number of colors in image (0 if >=8bpp) */
00040     BYTE        bReserved;       /* Reserved ( must be 0)       */
00041     WORD        wPlanes;         /* Color Planes            */
00042     WORD        wBitCount;       /* Bits per pixel          */
00043     DWORD       dwBytesInRes;    /* How many bytes in this resource?    */
00044     DWORD       dwImageOffset;   /* Where in the file is this image?    */
00045 } icoICONDIRENTRY, *LPicoICONDIRENTRY;
00046 
00047 typedef struct
00048 {
00049     WORD            idReserved;   /* Reserved (must be 0) */
00050     WORD            idType;       /* Resource Type (RES_ICON or RES_CURSOR) */
00051     WORD            idCount;      /* How many images */
00052     icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
00053 } icoICONDIR, *LPicoICONDIR;
00054 
00055 #include "poppack.h"
00056 
00057 #if 0
00058 static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry )
00059 {
00060     TRACE("width = 0x%08x height = 0x%08x\n", entry->bWidth, entry->bHeight);
00061     TRACE("colors = 0x%08x planes = 0x%08x\n", entry->bColorCount, entry->wPlanes);
00062     TRACE("bitcount = 0x%08x bytesinres = 0x%08lx offset = 0x%08lx\n",
00063     entry->wBitCount, entry->dwBytesInRes, entry->dwImageOffset);
00064 }
00065 static void dumpIcoDir ( LPicoICONDIR entry )
00066 {
00067     TRACE("type = 0x%08x count = 0x%08x\n", entry->idType, entry->idCount);
00068 }
00069 #endif
00070 
00071 /**********************************************************************
00072  *  find_entry_by_id
00073  *
00074  * Find an entry by id in a resource directory
00075  * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
00076  */
00077 static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY *dir,
00078                                                          WORD id, const void *root )
00079 {
00080     const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
00081     int min, max, pos;
00082 
00083     entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
00084     min = dir->NumberOfNamedEntries;
00085     max = min + dir->NumberOfIdEntries - 1;
00086     while (min <= max)
00087     {
00088         pos = (min + max) / 2;
00089         if (entry[pos].Id == id)
00090             return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].OffsetToDirectory);
00091         if (entry[pos].Id > id) max = pos - 1;
00092         else min = pos + 1;
00093     }
00094     return NULL;
00095 }
00096 
00097 /**********************************************************************
00098  *  find_entry_default
00099  *
00100  * Find a default entry in a resource directory
00101  * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
00102  */
00103 static const IMAGE_RESOURCE_DIRECTORY *find_entry_default( const IMAGE_RESOURCE_DIRECTORY *dir,
00104                                                            const void *root )
00105 {
00106     const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
00107     entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
00108     return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry->OffsetToDirectory);
00109 }
00110 
00111 /*************************************************************************
00112  *              USER32_GetResourceTable
00113  */
00114 static DWORD USER32_GetResourceTable(LPBYTE peimage,DWORD pesize,LPBYTE *retptr)
00115 {
00116     IMAGE_DOS_HEADER    * mz_header;
00117 
00118     TRACE("%p %p\n", peimage, retptr);
00119 
00120     *retptr = NULL;
00121 
00122     mz_header = (IMAGE_DOS_HEADER*) peimage;
00123 
00124     if (mz_header->e_magic != IMAGE_DOS_SIGNATURE)
00125     {
00126       if (mz_header->e_cblp == 1)   /* .ICO file ? */
00127       {
00128         *retptr = (LPBYTE)-1;   /* ICONHEADER.idType, must be 1 */
00129         return 1;
00130       }
00131       else
00132         return 0; /* failed */
00133     }
00134     if (mz_header->e_lfanew >= pesize) {
00135         return 0; /* failed, happens with PKZIP DOS Exes for instance. */
00136     }
00137     if (*((DWORD*)(peimage + mz_header->e_lfanew)) == IMAGE_NT_SIGNATURE )
00138       return IMAGE_NT_SIGNATURE;
00139 #if 0
00140     if (*((WORD*)(peimage + mz_header->e_lfanew)) == IMAGE_OS2_SIGNATURE )
00141     {
00142       IMAGE_OS2_HEADER  * ne_header;
00143 
00144       ne_header = (IMAGE_OS2_HEADER*)(peimage + mz_header->e_lfanew);
00145 
00146       if (ne_header->ne_magic != IMAGE_OS2_SIGNATURE)
00147         return 0;
00148 
00149       if( (ne_header->ne_restab - ne_header->ne_rsrctab) <= sizeof(NE_TYPEINFO) )
00150         *retptr = (LPBYTE)-1;
00151       else
00152         *retptr = peimage + mz_header->e_lfanew + ne_header->ne_rsrctab;
00153 
00154       return IMAGE_OS2_SIGNATURE;
00155     }
00156 #endif
00157     return 0; /* failed */
00158 }
00159 #if 0
00160 /*************************************************************************
00161  *          USER32_LoadResource
00162  */
00163 static BYTE * USER32_LoadResource( LPBYTE peimage, NE_NAMEINFO* pNInfo, WORD sizeShift, ULONG *uSize)
00164 {
00165     TRACE("%p %p 0x%08x\n", peimage, pNInfo, sizeShift);
00166 
00167     *uSize = (DWORD)pNInfo->length << sizeShift;
00168     return peimage + ((DWORD)pNInfo->offset << sizeShift);
00169 }
00170 
00171 /*************************************************************************
00172  *                      ICO_LoadIcon
00173  */
00174 static BYTE * ICO_LoadIcon( LPBYTE peimage, LPicoICONDIRENTRY lpiIDE, ULONG *uSize)
00175 {
00176     TRACE("%p %p\n", peimage, lpiIDE);
00177 
00178     *uSize = lpiIDE->dwBytesInRes;
00179     return peimage + lpiIDE->dwImageOffset;
00180 }
00181 
00182 /*************************************************************************
00183  *                      ICO_GetIconDirectory
00184  *
00185  * Reads .ico file and build phony ICONDIR struct
00186  */
00187 #define HEADER_SIZE     (sizeof(CURSORICONDIR) - sizeof (CURSORICONDIRENTRY))
00188 #define HEADER_SIZE_FILE    (sizeof(icoICONDIR) - sizeof (icoICONDIRENTRY))
00189 
00190 static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG *uSize )
00191 {
00192     CURSORICONDIR   * lpcid;    /* icon resource in resource-dir format */
00193     CURSORICONDIR   * lpID;     /* icon resource in resource format */
00194     int     i;
00195 
00196     TRACE("%p %p\n", peimage, lplpiID);
00197 
00198     lpcid = (CURSORICONDIR*)peimage;
00199 
00200     if( lpcid->idReserved || (lpcid->idType != 1) || (!lpcid->idCount) )
00201       return 0;
00202 
00203     /* allocate the phony ICONDIR structure */
00204     *uSize = lpcid->idCount * sizeof(CURSORICONDIRENTRY) + HEADER_SIZE;
00205     if( (lpID = HeapAlloc(GetProcessHeap(),0, *uSize) ))
00206     {
00207       /* copy the header */
00208       lpID->idReserved = lpcid->idReserved;
00209       lpID->idType = lpcid->idType;
00210       lpID->idCount = lpcid->idCount;
00211 
00212       /* copy the entries */
00213       for( i=0; i < lpcid->idCount; i++ )
00214       {
00215         memcpy(&lpID->idEntries[i], &lpcid->idEntries[i], sizeof(CURSORICONDIRENTRY) - 2);
00216         lpID->idEntries[i].wResId = i;
00217       }
00218 
00219       *lplpiID = (LPicoICONDIR)peimage;
00220       return (BYTE *)lpID;
00221     }
00222     return 0;
00223 }
00224 #endif
00225 /*************************************************************************
00226  *  ICO_ExtractIconExW      [internal]
00227  *
00228  * NOTES
00229  *  nIcons = 0: returns number of Icons in file
00230  *
00231  * returns
00232  *  invalid file: -1
00233  *  failure:0;
00234  *  success: number of icons in file (nIcons = 0) or nr of icons retrieved
00235  */
00236 static UINT ICO_ExtractIconExW(
00237     LPCWSTR lpszExeFileName,
00238     HICON * RetPtr,
00239     INT nIconIndex,
00240     UINT nIcons,
00241     UINT cxDesired,
00242     UINT cyDesired,
00243     UINT *pIconId,
00244     UINT flags)
00245 {
00246     UINT        ret = 0;
00247     UINT        cx1, cx2, cy1, cy2;
00248     LPBYTE      pData;
00249     DWORD       sig;
00250     HANDLE      hFile;
00251     UINT16      iconDirCount = 0; //,iconCount = 0;
00252     LPBYTE      peimage;
00253     HANDLE      fmapping;
00254     DWORD       fsizeh,fsizel;
00255         WCHAR       szExePath[MAX_PATH];
00256         DWORD       dwSearchReturn;
00257 
00258     TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName), nIconIndex, nIcons, pIconId, flags);
00259 
00260         dwSearchReturn = SearchPathW(NULL, lpszExeFileName, NULL, sizeof(szExePath) / sizeof(szExePath[0]), szExePath, NULL);
00261         if ((dwSearchReturn == 0) || (dwSearchReturn > sizeof(szExePath) / sizeof(szExePath[0])))
00262         {
00263             WARN("File %s not found or path too long\n", debugstr_w(lpszExeFileName));
00264             return -1;
00265         }
00266 
00267     hFile = CreateFileW(szExePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
00268     if (hFile == INVALID_HANDLE_VALUE) return ret;
00269     fsizel = GetFileSize(hFile,&fsizeh);
00270 
00271     /* Map the file */
00272     fmapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
00273     CloseHandle(hFile);
00274     if (!fmapping)
00275     {
00276       WARN("CreateFileMapping error %ld\n", GetLastError() );
00277       return 0xFFFFFFFF;
00278     }
00279 
00280     if (!(peimage = MapViewOfFile(fmapping, FILE_MAP_READ, 0, 0, 0)))
00281     {
00282       WARN("MapViewOfFile error %ld\n", GetLastError() );
00283       CloseHandle(fmapping);
00284       return 0xFFFFFFFF;
00285     }
00286     CloseHandle(fmapping);
00287 
00288     cx1 = LOWORD(cxDesired);
00289     cx2 = HIWORD(cxDesired);
00290     cy1 = LOWORD(cyDesired);
00291     cy2 = HIWORD(cyDesired);
00292 
00293     if (pIconId) /* Invalidate first icon identifier */
00294         *pIconId = 0xFFFFFFFF;
00295 
00296     if (!pIconId) /* if no icon identifier array present use the icon handle array as intermediate storage */
00297       pIconId = (UINT*)RetPtr;
00298 
00299     sig = USER32_GetResourceTable(peimage, fsizel, &pData);
00300 
00301 /* ico file or NE exe/dll*/
00302 #if 0
00303     if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */
00304     {
00305       BYTE      *pCIDir = 0;
00306       NE_TYPEINFO   *pTInfo = (NE_TYPEINFO*)(pData + 2);
00307       NE_NAMEINFO   *pIconStorage = NULL;
00308       NE_NAMEINFO   *pIconDir = NULL;
00309       LPicoICONDIR  lpiID = NULL;
00310 
00311       TRACE("-- OS2/icon Signature (0x%08lx)\n", sig);
00312 
00313       if (pData == (BYTE*)-1)
00314       {
00315         pCIDir = ICO_GetIconDirectory(peimage, &lpiID, &uSize); /* check for .ICO file */
00316         if (pCIDir)
00317         {
00318           iconDirCount = 1; iconCount = lpiID->idCount;
00319           TRACE("-- icon found %p 0x%08lx 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount);
00320         }
00321       }
00322       else while (pTInfo->type_id && !(pIconStorage && pIconDir))
00323       {
00324         if (pTInfo->type_id == NE_RSCTYPE_GROUP_ICON)   /* find icon directory and icon repository */
00325         {
00326           iconDirCount = pTInfo->count;
00327           pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
00328           TRACE("\tfound directory - %i icon families\n", iconDirCount);
00329         }
00330         if (pTInfo->type_id == NE_RSCTYPE_ICON)
00331         {
00332           iconCount = pTInfo->count;
00333           pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
00334           TRACE("\ttotal icons - %i\n", iconCount);
00335         }
00336         pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
00337       }
00338 
00339       if ((pIconStorage && pIconDir) || lpiID)    /* load resources and create icons */
00340       {
00341         if (nIcons == 0)
00342         {
00343           ret = iconDirCount;
00344           if (lpiID && pCIDir)  /* *.ico file, deallocate heap pointer*/
00345             HeapFree(GetProcessHeap(), 0, pCIDir);
00346         }
00347         else if (nIconIndex < iconDirCount)
00348         {
00349           UINT16   i, icon;
00350           if (nIcons > iconDirCount - nIconIndex)
00351             nIcons = iconDirCount - nIconIndex;
00352 
00353           for (i = 0; i < nIcons; i++)
00354           {
00355             /* .ICO files have only one icon directory */
00356             if (lpiID == NULL)  /* not *.ico */
00357               pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize);
00358             pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags);
00359           }
00360           if (lpiID && pCIDir)  /* *.ico file, deallocate heap pointer*/
00361             HeapFree(GetProcessHeap(), 0, pCIDir);
00362 
00363           for (icon = 0; icon < nIcons; icon++)
00364           {
00365             pCIDir = NULL;
00366             if (lpiID)
00367               pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize);
00368             else
00369               for (i = 0; i < iconCount; i++)
00370                 if (pIconStorage[i].id == ((int)pIconId[icon] | 0x8000) )
00371                   pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize);
00372 
00373             if (pCIDir)
00374               RetPtr[icon] = (HICON)CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
00375                                                              (icon & 1) ? cx2 : cx1, (icon & 1) ? cy2 : cy1, flags);
00376             else
00377               RetPtr[icon] = 0;
00378           }
00379           ret = icon;   /* return number of retrieved icons */
00380         }
00381       }
00382     }
00383 /* end ico file */
00384 
00385 /* exe/dll */
00386     else if( sig == IMAGE_NT_SIGNATURE )
00387 #endif
00388     if( sig == IMAGE_NT_SIGNATURE )
00389     {
00390       LPBYTE        idata,igdata;
00391       PIMAGE_DOS_HEADER dheader;
00392       PIMAGE_NT_HEADERS pe_header;
00393       PIMAGE_SECTION_HEADER pe_sections;
00394       const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir;
00395       const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent;
00396       const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
00397       UINT  i, j;
00398 
00399       dheader = (PIMAGE_DOS_HEADER)peimage;
00400       pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);     /* it is a pe header, USER32_GetResourceTable checked that */
00401       pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER)
00402                                             + pe_header->FileHeader.SizeOfOptionalHeader);
00403       rootresdir = NULL;
00404 
00405       /* search for the root resource directory */
00406       for (i=0;i<pe_header->FileHeader.NumberOfSections;i++)
00407       {
00408         if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
00409           continue;
00410         if (fsizel < pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData) {
00411               FIXME("File %s too short (section is at %ld bytes, real size is %ld)\n",
00412               debugstr_w(lpszExeFileName),
00413               pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData,
00414               fsizel
00415           );
00416           goto end;
00417         }
00418         /* FIXME: doesn't work when the resources are not in a separate section */
00419         if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)
00420         {
00421           rootresdir = (PIMAGE_RESOURCE_DIRECTORY)(peimage+pe_sections[i].PointerToRawData);
00422           break;
00423         }
00424       }
00425 
00426       if (!rootresdir)
00427       {
00428         WARN("haven't found section for resource directory.\n");
00429         goto end;       /* failure */
00430       }
00431 
00432       /* search for the group icon directory */
00433       if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir)))
00434       {
00435         WARN("No Icongroupresourcedirectory!\n");
00436         goto end;       /* failure */
00437       }
00438       iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries;
00439 
00440       /* only number of icons requested */
00441       if( !pIconId )
00442       {
00443         ret = iconDirCount;
00444         goto end;       /* success */
00445       }
00446 
00447       if( nIconIndex < 0 )
00448       {
00449         /* search resource id */
00450         int n = 0;
00451         int iId = abs(nIconIndex);
00452         const IMAGE_RESOURCE_DIRECTORY_ENTRY* xprdeTmp = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1);
00453 
00454         while(n<iconDirCount && xprdeTmp)
00455         {
00456               if(xprdeTmp->Id ==  iId)
00457               {
00458                   nIconIndex = n;
00459                   break;
00460               }
00461               n++;
00462               xprdeTmp++;
00463         }
00464         if (nIconIndex < 0)
00465         {
00466           WARN("resource id %d not found\n", iId);
00467           goto end;     /* failure */
00468         }
00469       }
00470       else
00471       {
00472         /* check nIconIndex to be in range */
00473         if (nIconIndex >= iconDirCount)
00474         {
00475           WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
00476           goto end;     /* failure */
00477         }
00478       }
00479 
00480       /* assure we don't get too much */
00481       if( nIcons > iconDirCount - nIconIndex )
00482         nIcons = iconDirCount - nIconIndex;
00483 
00484       /* starting from specified index */
00485       xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex;
00486 
00487       for (i=0; i < nIcons; i++,xresent++)
00488       {
00489         const IMAGE_RESOURCE_DIRECTORY *resdir;
00490 
00491         /* go down this resource entry, name */
00492         resdir = (const IMAGE_RESOURCE_DIRECTORY*)((const char *)rootresdir+(xresent->OffsetToDirectory));
00493 
00494         /* default language (0) */
00495         resdir = find_entry_default(resdir,rootresdir);
00496         igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;
00497 
00498         /* lookup address in mapped image for virtual address */
00499         igdata = NULL;
00500 
00501         for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
00502         {
00503           if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
00504             continue;
00505           if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
00506             continue;
00507 
00508           if (igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData+igdataent->Size > fsizel) {
00509             FIXME("overflow in PE lookup (%s has len %ld, have offset %ld), short file?\n", debugstr_w(lpszExeFileName), fsizel,
00510                    igdataent->OffsetToData - pe_sections[j].VirtualAddress + pe_sections[j].PointerToRawData + igdataent->Size);
00511             goto end; /* failure */
00512           }
00513           igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
00514         }
00515 
00516         if (!igdata)
00517         {
00518           FIXME("no matching real address for icongroup!\n");
00519           goto end; /* failure */
00520         }
00521         pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags);
00522             if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags);
00523       }
00524 
00525       if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir)))
00526       {
00527         WARN("No Iconresourcedirectory!\n");
00528         goto end;       /* failure */
00529       }
00530 
00531       for (i=0; i<nIcons; i++)
00532       {
00533         const IMAGE_RESOURCE_DIRECTORY *xresdir;
00534         xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
00535         if (!xresdir)
00536         {
00537           WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
00538           RetPtr[i]=0;
00539           continue;
00540         }
00541         xresdir = find_entry_default(xresdir, rootresdir);
00542         if (!xresdir)
00543         {
00544           WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
00545           RetPtr[i]=0;
00546           continue;
00547         }
00548         idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;
00549         idata = NULL;
00550 
00551         /* map virtual to address in image */
00552         for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
00553         {
00554           if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
00555             continue;
00556           if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
00557             continue;
00558           idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
00559         }
00560         if (!idata)
00561         {
00562           WARN("no matching real address found for icondata!\n");
00563           RetPtr[i]=0;
00564           continue;
00565         }
00566         RetPtr[i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx1, cy1, flags);
00567             if (cx2 && cy2)
00568                 RetPtr[++i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx2, cy2, flags);
00569       }
00570       ret = i;  /* return number of retrieved icons */
00571     }           /* if(sig == IMAGE_NT_SIGNATURE) */
00572 
00573 end:
00574     UnmapViewOfFile(peimage);   /* success */
00575     return ret;
00576 }
00577 
00578 /***********************************************************************
00579  *           PrivateExtractIconsW           [USER32.@]
00580  *
00581  * NOTES
00582  *  If HIWORD(sizeX) && HIWORD(sizeY) 2 * ((nIcons + 1) MOD 2) icons are
00583  *  returned, with the LOWORD size icon first and the HIWORD size icon
00584  *  second.
00585  *  Also the Windows equivalent does extract icons in a strange way if
00586  *  nIndex is negative. Our implementation treats a negative nIndex as
00587  *  looking for that resource identifier for the first icon to retrieve.
00588  *
00589  * FIXME:
00590  *  should also support 16 bit EXE + DLLs, cursor and animated cursor as
00591  *  well as bitmap files.
00592  */
00593 
00594 UINT WINAPI PrivateExtractIconsW (
00595     LPCWSTR lpwstrFile,
00596     int nIndex,
00597     int sizeX,
00598     int sizeY,
00599     HICON * phicon, /* [out] pointer to array of nIcons HICON handles */
00600     UINT* pIconId,  /* [out] pointer to array of nIcons icon identifiers or NULL */
00601     UINT nIcons,    /* [in] number of icons to retrieve */
00602     UINT flags )    /* [in] LR_* flags used by LoadImage */
00603 {
00604     TRACE("%s %d %dx%d %p %p %d 0x%08x\n",
00605           debugstr_w(lpwstrFile), nIndex, sizeX, sizeY, phicon, pIconId, nIcons, flags);
00606 
00607     if ((nIcons & 1) && HIWORD(sizeX) && HIWORD(sizeY))
00608     {
00609       WARN("Uneven number %d of icons requested for small and large icons!\n", nIcons);
00610     }
00611     return ICO_ExtractIconExW(lpwstrFile, phicon, nIndex, nIcons, sizeX, sizeY, pIconId, flags);
00612 }
00613 
00614 /***********************************************************************
00615  *           PrivateExtractIconsA           [USER32.@]
00616  */
00617 
00618 UINT WINAPI PrivateExtractIconsA (
00619     LPCSTR lpstrFile,
00620     int nIndex,
00621     int sizeX,
00622     int sizeY,
00623     HICON * phicon, /* [out] pointer to array of nIcons HICON handles */
00624     UINT* piconid,  /* [out] pointer to array of nIcons icon identifiers or NULL */
00625     UINT nIcons,    /* [in] number of icons to retrieve */
00626     UINT flags )    /* [in] LR_* flags used by LoadImage */
00627 {
00628     UINT ret;
00629     INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
00630     LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00631     if (lpwstrFile == NULL)
00632         return 0;
00633 
00634     MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len);
00635     ret = PrivateExtractIconsW(lpwstrFile, nIndex, sizeX, sizeY, phicon, piconid, nIcons, flags);
00636 
00637     HeapFree(GetProcessHeap(), 0, lpwstrFile);
00638     return ret;
00639 }
00640 
00641 /***********************************************************************
00642  *           PrivateExtractIconExW          [USER32.@]
00643  * NOTES
00644  *  if nIndex == -1 it returns the number of icons in any case !!!
00645  */
00646 UINT WINAPI PrivateExtractIconExW (
00647     LPCWSTR lpwstrFile,
00648     int nIndex,
00649     HICON * phIconLarge,
00650     HICON * phIconSmall,
00651     UINT nIcons )
00652 {
00653     DWORD cyicon, cysmicon, cxicon, cxsmicon;
00654     UINT ret = 0;
00655 
00656     TRACE("%s %d %p %p %d\n",
00657     debugstr_w(lpwstrFile),nIndex,phIconLarge, phIconSmall, nIcons);
00658 
00659     if (nIndex == -1)
00660       /* get the number of icons */
00661       return ICO_ExtractIconExW(lpwstrFile, NULL, 0, 0, 0, 0, NULL, LR_DEFAULTCOLOR);
00662 
00663     if (nIcons == 1 && phIconSmall && phIconLarge)
00664     {
00665       HICON hIcon[2];
00666       cxicon = GetSystemMetrics(SM_CXICON);
00667       cyicon = GetSystemMetrics(SM_CYICON);
00668       cxsmicon = GetSystemMetrics(SM_CXSMICON);
00669       cysmicon = GetSystemMetrics(SM_CYSMICON);
00670 
00671       ret = ICO_ExtractIconExW(lpwstrFile, hIcon, nIndex, 2, cxicon | (cxsmicon<<16),
00672                                cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR);
00673       *phIconLarge = hIcon[0];
00674       *phIconSmall = hIcon[1];
00675       return ret;
00676     }
00677 
00678     if (phIconSmall)
00679     {
00680       /* extract n small icons */
00681       cxsmicon = GetSystemMetrics(SM_CXSMICON);
00682       cysmicon = GetSystemMetrics(SM_CYSMICON);
00683       ret = ICO_ExtractIconExW(lpwstrFile, phIconSmall, nIndex, nIcons, cxsmicon,
00684                                cysmicon, NULL, LR_DEFAULTCOLOR);
00685     }
00686        if (phIconLarge)
00687     {
00688       /* extract n large icons */
00689       cxicon = GetSystemMetrics(SM_CXICON);
00690       cyicon = GetSystemMetrics(SM_CYICON);
00691          ret = ICO_ExtractIconExW(lpwstrFile, phIconLarge, nIndex, nIcons, cxicon,
00692                                cyicon, NULL, LR_DEFAULTCOLOR);
00693     }
00694     return ret;
00695 }
00696 
00697 /***********************************************************************
00698  *           PrivateExtractIconExA          [USER32.@]
00699  */
00700 UINT WINAPI PrivateExtractIconExA (
00701     LPCSTR lpstrFile,
00702     int nIndex,
00703     HICON * phIconLarge,
00704     HICON * phIconSmall,
00705     UINT nIcons )
00706 {
00707     UINT ret;
00708     INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
00709     LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00710     if (lpwstrFile == NULL)
00711         return 0;
00712 
00713     TRACE("%s %d %p %p %d\n", lpstrFile, nIndex, phIconLarge, phIconSmall, nIcons);
00714 
00715     MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len);
00716     ret = PrivateExtractIconExW(lpwstrFile, nIndex, phIconLarge, phIconSmall, nIcons);
00717     HeapFree(GetProcessHeap(), 0, lpwstrFile);
00718     return ret;
00719 }

Generated on Fri May 25 2012 04:37:09 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.