ReactOS  0.4.15-dev-5452-g3c95c95
exticon.c
Go to the documentation of this file.
1 /*
2  * icon extracting
3  *
4  * taken and slightly changed from shell
5  * this should replace the icon extraction code in shell32 and shell16 once
6  * it needs a serious test for compliance with the native API
7  *
8  * Copyright 2000 Juergen Schmied
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <user32.h>
26 
27 #ifndef ARRAY_SIZE
28 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
29 #endif
30 
31 /* Start of Hack section */
32 
34 
35 #include <pshpack1.h>
36 
37 typedef struct
38 {
39  BYTE bWidth; /* Width, in pixels, of the image */
40  BYTE bHeight; /* Height, in pixels, of the image */
41  BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
42  BYTE bReserved; /* Reserved ( must be 0) */
43  WORD wPlanes; /* Color Planes */
44  WORD wBitCount; /* Bits per pixel */
45  DWORD dwBytesInRes; /* How many bytes in this resource? */
46  DWORD dwImageOffset; /* Where in the file is this image? */
48 
49 typedef struct
50 {
51  WORD idReserved; /* Reserved (must be 0) */
52  WORD idType; /* Resource Type (RES_ICON or RES_CURSOR) */
53  WORD idCount; /* How many images */
54  icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
56 
57 typedef struct
58 {
59  WORD offset;
60  WORD length;
61  WORD flags;
62  WORD id;
63  WORD handle;
64  WORD usage;
65 } NE_NAMEINFO;
66 
67 typedef struct
68 {
69  WORD type_id;
70  WORD count;
71  DWORD resloader;
72 } NE_TYPEINFO;
73 
74 // From: James Houghtaling
75 // https://www.moon-soft.com/program/FORMAT/windows/ani.htm
76 typedef struct taganiheader
77 {
78  DWORD cbsizeof; // num bytes in aniheader (36 bytes)
79  DWORD cframes; // number of unique icons in this cursor
80  DWORD csteps; // number of blits before the animation cycles
81  DWORD cx; // reserved, must be zero.
82  DWORD cy; // reserved, must be zero.
83  DWORD cbitcount; // reserved, must be zero.
84  DWORD cplanes; // reserved, must be zero.
85  DWORD jifrate; // default jiffies (1/60th sec) if rate chunk not present.
86  DWORD flags; // animation flag
87 } aniheader;
88 
89 #define NE_RSCTYPE_ICON 0x8003
90 #define NE_RSCTYPE_GROUP_ICON 0x800e
91 
92 #include <poppack.h>
93 
94 #if 0
95 static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry )
96 {
97  TRACE("width = 0x%08x height = 0x%08x\n", entry->bWidth, entry->bHeight);
98  TRACE("colors = 0x%08x planes = 0x%08x\n", entry->bColorCount, entry->wPlanes);
99  TRACE("bitcount = 0x%08x bytesinres = 0x%08lx offset = 0x%08lx\n",
100  entry->wBitCount, entry->dwBytesInRes, entry->dwImageOffset);
101 }
102 static void dumpIcoDir ( LPicoICONDIR entry )
103 {
104  TRACE("type = 0x%08x count = 0x%08x\n", entry->idType, entry->idCount);
105 }
106 #endif
107 
108 #ifndef WINE
111  int cxDesired,
112  int cyDesired,
113  BOOL bIcon,
114  DWORD fuLoad,
115  POINT *ptHotSpot);
116 #endif
117 
118 /**********************************************************************
119  * find_entry_by_id
120  *
121  * Find an entry by id in a resource directory
122  * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
123  */
125  WORD id, const void *root )
126 {
128  int min, max, pos;
129 
130  entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
131  min = dir->NumberOfNamedEntries;
132  max = min + dir->NumberOfIdEntries - 1;
133  while (min <= max)
134  {
135  pos = (min + max) / 2;
136  if (entry[pos].Id == id)
137  return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].OffsetToDirectory);
138  if (entry[pos].Id > id) max = pos - 1;
139  else min = pos + 1;
140  }
141  return NULL;
142 }
143 
144 /**********************************************************************
145  * find_entry_default
146  *
147  * Find a default entry in a resource directory
148  * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
149  */
151  const void *root )
152 {
154  entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
155  return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry->OffsetToDirectory);
156 }
157 
158 /*************************************************************************
159  * USER32_GetResourceTable
160  */
161 static DWORD USER32_GetResourceTable(LPBYTE peimage,DWORD pesize,LPBYTE *retptr)
162 {
163  IMAGE_DOS_HEADER * mz_header;
164 
165  TRACE("%p %p\n", peimage, retptr);
166 
167  *retptr = NULL;
168 
169  mz_header = (IMAGE_DOS_HEADER*) peimage;
170 
171  if (mz_header->e_magic != IMAGE_DOS_SIGNATURE)
172  {
173  if (mz_header->e_cblp == 1 || mz_header->e_cblp == 2) /* .ICO or .CUR file ? */
174  {
175  *retptr = (LPBYTE)-1; /* ICONHEADER.idType, must be 1 */
176  return mz_header->e_cblp;
177  }
178  else
179  return 0; /* failed */
180  }
181  if (mz_header->e_lfanew >= pesize) {
182  return 0; /* failed, happens with PKZIP DOS Exes for instance. */
183  }
184  if (*((DWORD*)(peimage + mz_header->e_lfanew)) == IMAGE_NT_SIGNATURE )
185  return IMAGE_NT_SIGNATURE;
186 
187  if (*((WORD*)(peimage + mz_header->e_lfanew)) == IMAGE_OS2_SIGNATURE )
188  {
189  IMAGE_OS2_HEADER * ne_header;
190 
191  ne_header = (IMAGE_OS2_HEADER*)(peimage + mz_header->e_lfanew);
192 
193  if (ne_header->ne_magic != IMAGE_OS2_SIGNATURE)
194  return 0;
195 
196  if( (ne_header->ne_restab - ne_header->ne_rsrctab) <= sizeof(NE_TYPEINFO) )
197  *retptr = (LPBYTE)-1;
198  else
199  *retptr = peimage + mz_header->e_lfanew + ne_header->ne_rsrctab;
200 
201  return IMAGE_OS2_SIGNATURE;
202  }
203  return 0; /* failed */
204 }
205 /*************************************************************************
206  * USER32_LoadResource
207  */
208 static BYTE * USER32_LoadResource( LPBYTE peimage, NE_NAMEINFO* pNInfo, WORD sizeShift, ULONG *uSize)
209 {
210  TRACE("%p %p 0x%08x\n", peimage, pNInfo, sizeShift);
211 
212  *uSize = (DWORD)pNInfo->length << sizeShift;
213  return peimage + ((DWORD)pNInfo->offset << sizeShift);
214 }
215 
216 /*************************************************************************
217  * ICO_LoadIcon
218  */
219 static BYTE * ICO_LoadIcon( LPBYTE peimage, LPicoICONDIRENTRY lpiIDE, ULONG *uSize)
220 {
221  TRACE("%p %p\n", peimage, lpiIDE);
222 
223  *uSize = lpiIDE->dwBytesInRes;
224  return peimage + lpiIDE->dwImageOffset;
225 }
226 
227 /*************************************************************************
228  * ICO_GetIconDirectory
229  *
230  * Reads .ico file and build phony ICONDIR struct
231  */
232 static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG *uSize )
233 {
234  CURSORICONDIR * lpcid; /* icon resource in resource-dir format */
235  CURSORICONDIR * lpID; /* icon resource in resource format */
236  int i;
237 
238  TRACE("%p %p\n", peimage, lplpiID);
239 
240  lpcid = (CURSORICONDIR*)peimage;
241 
242  if( lpcid->idReserved || (lpcid->idType != 1) || (!lpcid->idCount) )
243  return 0;
244 
245  /* allocate the phony ICONDIR structure */
246  *uSize = FIELD_OFFSET(CURSORICONDIR, idEntries[lpcid->idCount]);
247  if( (lpID = HeapAlloc(GetProcessHeap(),0, *uSize) ))
248  {
249  /* copy the header */
250  lpID->idReserved = lpcid->idReserved;
251  lpID->idType = lpcid->idType;
252  lpID->idCount = lpcid->idCount;
253 
254  /* copy the entries */
255  for( i=0; i < lpcid->idCount; i++ )
256  {
257  memcpy(&lpID->idEntries[i], &lpcid->idEntries[i], sizeof(CURSORICONDIRENTRY) - 2);
258  lpID->idEntries[i].wResId = i;
259  }
260 
261  *lplpiID = (LPicoICONDIR)peimage;
262  return (BYTE *)lpID;
263  }
264  return 0;
265 }
266 
267 /*************************************************************************
268  * ICO_ExtractIconExW [internal]
269  *
270  * NOTES
271  * nIcons = 0: returns number of Icons in file
272  *
273  * returns
274  * invalid file: -1
275  * failure:0;
276  * success: number of icons in file (nIcons = 0) or nr of icons retrieved
277  */
279  LPCWSTR lpszExeFileName,
280  HICON * RetPtr,
281  INT nIconIndex,
282  UINT nIcons,
283  UINT cxDesired,
284  UINT cyDesired,
285  UINT *pIconId,
286  UINT flags)
287 {
288  UINT ret = 0;
289  UINT cx1, cx2, cy1, cy2;
290  LPBYTE pData;
291  DWORD sig;
292  HANDLE hFile;
293  UINT16 iconDirCount = 0,iconCount = 0;
294  LPBYTE peimage;
295  HANDLE fmapping;
296  DWORD fsizeh,fsizel;
297 #ifdef __REACTOS__
298  WCHAR szExpandedExePath[MAX_PATH];
299 #endif
300  WCHAR szExePath[MAX_PATH];
301  DWORD dwSearchReturn;
302 
303  TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName), nIconIndex, nIcons, pIconId, flags);
304 
305 #ifdef __REACTOS__
306  if (RetPtr)
307  *RetPtr = NULL;
308 
309  if (ExpandEnvironmentStringsW(lpszExeFileName, szExpandedExePath, ARRAY_SIZE(szExpandedExePath)))
310  lpszExeFileName = szExpandedExePath;
311 #endif
312 
313  dwSearchReturn = SearchPathW(NULL, lpszExeFileName, NULL, ARRAY_SIZE(szExePath), szExePath, NULL);
314  if ((dwSearchReturn == 0) || (dwSearchReturn > ARRAY_SIZE(szExePath)))
315  {
316  WARN("File %s not found or path too long\n", debugstr_w(lpszExeFileName));
317  return -1;
318  }
319 
321  if (hFile == INVALID_HANDLE_VALUE) return ret;
322  fsizel = GetFileSize(hFile,&fsizeh);
323 
324  /* Map the file */
325  fmapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
327  if (!fmapping)
328  {
329  WARN("CreateFileMapping error %ld\n", GetLastError() );
330  return 0xFFFFFFFF;
331  }
332 
333  if (!(peimage = MapViewOfFile(fmapping, FILE_MAP_READ, 0, 0, 0)))
334  {
335  WARN("MapViewOfFile error %ld\n", GetLastError() );
336  CloseHandle(fmapping);
337  return 0xFFFFFFFF;
338  }
339  CloseHandle(fmapping);
340 
341 #ifdef __REACTOS__
342  /* Check if we have a min size of 2 headers RIFF & 'icon'
343  * at 8 chars each plus an anih header of 36 byptes.
344  * Also, is this resource an animjated icon/cursor (RIFF) */
345  if ((fsizel >= 52) && !memcmp(peimage, "RIFF", 4))
346  {
347  UINT anihOffset;
348  UINT anihMax;
349  /* Get size of the animation data */
350  ULONG uSize = MAKEWORD(peimage[4], peimage[5]);
351 
352  /* Check if uSize is reasonable with respect to fsizel */
353  if ((uSize < strlen("anih")) || (uSize > fsizel))
354  goto end;
355 
356  /* Look though the reported size less search string length */
357  anihMax = uSize - strlen("anih");
358  /* Search for 'anih' indicating animation header */
359  for (anihOffset = 0; anihOffset < anihMax; anihOffset++)
360  {
361  if (memcmp(&peimage[anihOffset], "anih", 4) == 0)
362  break;
363  }
364 
365  if (anihOffset + sizeof(aniheader) > fsizel)
366  goto end;
367 
368  /* Get count of images for return value */
369  ret = MAKEWORD(peimage[anihOffset + 12], peimage[anihOffset + 13]);
370 
371  TRACE("RIFF File with '%u' images at Offset '%u'.\n", ret, anihOffset);
372 
373  cx1 = LOWORD(cxDesired);
374  cy1 = LOWORD(cyDesired);
375 
376  if (RetPtr)
377  {
378  RetPtr[0] = CreateIconFromResourceEx(peimage, uSize, TRUE, 0x00030000, cx1, cy1, flags);
379  }
380  goto end;
381  }
382 #endif
383 
384  cx1 = LOWORD(cxDesired);
385  cx2 = HIWORD(cxDesired);
386  cy1 = LOWORD(cyDesired);
387  cy2 = HIWORD(cyDesired);
388 
389  if (pIconId) /* Invalidate first icon identifier */
390  *pIconId = 0xFFFFFFFF;
391 
392  if (!pIconId) /* if no icon identifier array present use the icon handle array as intermediate storage */
393  pIconId = (UINT*)RetPtr;
394 
395  sig = USER32_GetResourceTable(peimage, fsizel, &pData);
396 
397 /* NE exe/dll */
398  if (sig==IMAGE_OS2_SIGNATURE)
399  {
400  BYTE *pCIDir = 0;
401  NE_TYPEINFO *pTInfo = (NE_TYPEINFO*)(pData + 2);
402  NE_NAMEINFO *pIconStorage = NULL;
403  NE_NAMEINFO *pIconDir = NULL;
404  LPicoICONDIR lpiID = NULL;
405  ULONG uSize = 0;
406 
407  TRACE("-- OS2/icon Signature (0x%08x)\n", sig);
408 
409  if (pData == (BYTE*)-1)
410  {
411  pCIDir = ICO_GetIconDirectory(peimage, &lpiID, &uSize); /* check for .ICO file */
412  if (pCIDir)
413  {
414  iconDirCount = 1; iconCount = lpiID->idCount;
415  TRACE("-- icon found %p 0x%08x 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount);
416  }
417  }
418  else while (pTInfo->type_id && !(pIconStorage && pIconDir))
419  {
420  if (pTInfo->type_id == NE_RSCTYPE_GROUP_ICON) /* find icon directory and icon repository */
421  {
422  iconDirCount = pTInfo->count;
423  pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
424  TRACE("\tfound directory - %i icon families\n", iconDirCount);
425  }
426  if (pTInfo->type_id == NE_RSCTYPE_ICON)
427  {
428  iconCount = pTInfo->count;
429  pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
430  TRACE("\ttotal icons - %i\n", iconCount);
431  }
432  pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
433  }
434 
435  if ((pIconStorage && pIconDir) || lpiID) /* load resources and create icons */
436  {
437  if (nIcons == 0)
438  {
439  ret = iconDirCount;
440  if (lpiID) /* *.ico file, deallocate heap pointer*/
441  HeapFree(GetProcessHeap(), 0, pCIDir);
442  }
443  else if (nIconIndex < iconDirCount)
444  {
445  UINT16 i, icon;
446  if (nIcons > iconDirCount - nIconIndex)
447  nIcons = iconDirCount - nIconIndex;
448 
449  for (i = 0; i < nIcons; i++)
450  {
451  /* .ICO files have only one icon directory */
452  if (lpiID == NULL) /* not *.ico */
453  pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize);
454  pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, cx1, cy1, flags);
455  if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, cx2, cy2, flags);
456  }
457  if (lpiID) /* *.ico file, deallocate heap pointer*/
458  HeapFree(GetProcessHeap(), 0, pCIDir);
459 
460  for (icon = 0; icon < nIcons; icon++)
461  {
462  pCIDir = NULL;
463  if (lpiID)
464  pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize);
465  else
466  for (i = 0; i < iconCount; i++)
467  if (pIconStorage[i].id == ((int)pIconId[icon] | 0x8000) )
468  pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize);
469 
470  if (pCIDir)
471  {
472  RetPtr[icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
473  cx1, cy1, flags);
474  if (cx2 && cy2)
475  RetPtr[++icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
476  cx2, cy2, flags);
477  }
478  else
479  RetPtr[icon] = 0;
480  }
481  ret = icon; /* return number of retrieved icons */
482  }
483  }
484  }
485  else
486  if (sig == 1 || sig == 2) /* .ICO or .CUR file */
487  {
488  TRACE("-- icon Signature (0x%08x)\n", sig);
489 
490  if (pData == (BYTE*)-1)
491  {
492  INT cx[2] = {cx1, cx2}, cy[2] = {cy1, cy2};
493  INT index;
494 
495  for(index = 0; index < (cx2 || cy2 ? 2 : 1); index++)
496  {
497  DWORD dataOffset;
498  LPBYTE imageData;
499  POINT hotSpot;
500 #ifndef __REACTOS__
502 #endif
503 
504  dataOffset = get_best_icon_file_offset(peimage, fsizel, cx[index], cy[index], sig == 1, flags, sig == 1 ? NULL : &hotSpot);
505 
506  if (dataOffset)
507  {
508  HICON icon;
509  WORD *cursorData = NULL;
510 #ifdef __REACTOS__
511  BITMAPINFOHEADER bi;
512  DWORD cbColorTable = 0, cbTotal;
513 #endif
514 
515  imageData = peimage + dataOffset;
516 #ifdef __REACTOS__
517  /* Calculate the size of color table */
518  ZeroMemory(&bi, sizeof(bi));
519  CopyMemory(&bi, imageData, sizeof(BITMAPCOREHEADER));
520  if (bi.biBitCount <= 8)
521  {
522  if (bi.biSize >= sizeof(BITMAPINFOHEADER))
523  {
524  CopyMemory(&bi, imageData, sizeof(BITMAPINFOHEADER));
525  if (bi.biClrUsed)
526  cbColorTable = bi.biClrUsed * sizeof(RGBQUAD);
527  else
528  cbColorTable = (1 << bi.biBitCount) * sizeof(RGBQUAD);
529  }
530  else if (bi.biSize == sizeof(BITMAPCOREHEADER))
531  {
532  cbColorTable = (1 << bi.biBitCount) * sizeof(RGBTRIPLE);
533  }
534  }
535 
536  /* biSizeImage is the size of the raw bitmap data.
537  * https://en.wikipedia.org/wiki/BMP_file_format */
538  if (bi.biSizeImage == 0)
539  {
540  /* Calculate image size */
541 #define WIDTHBYTES(width, bits) (((width) * (bits) + 31) / 32 * 4)
542  bi.biSizeImage = WIDTHBYTES(bi.biWidth, bi.biBitCount) * (bi.biHeight / 2);
543  bi.biSizeImage += WIDTHBYTES(bi.biWidth, 1) * (bi.biHeight / 2);
544 #undef WIDTHBYTES
545  }
546 
547  /* Calculate total size */
548  cbTotal = bi.biSize + cbColorTable + bi.biSizeImage;
549 #else
550  entry = (LPICONIMAGE)(imageData);
551 #endif
552 
553  if(sig == 2)
554  {
555  /* we need to prepend the bitmap data with hot spots for CreateIconFromResourceEx */
556 #ifdef __REACTOS__
557  cursorData = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WORD) + cbTotal);
558 #else
559  cursorData = HeapAlloc(GetProcessHeap(), 0, entry->icHeader.biSizeImage + 2 * sizeof(WORD));
560 #endif
561 
562  if(!cursorData)
563  continue;
564 
565  cursorData[0] = hotSpot.x;
566  cursorData[1] = hotSpot.y;
567 
568 #ifdef __REACTOS__
569  CopyMemory(cursorData + 2, imageData, cbTotal);
570 #else
571  memcpy(cursorData + 2, imageData, entry->icHeader.biSizeImage);
572 #endif
573 
574  imageData = (LPBYTE)cursorData;
575  }
576 
577 #ifdef __REACTOS__
578  icon = CreateIconFromResourceEx(imageData, cbTotal, sig == 1, 0x00030000, cx[index], cy[index], flags);
579 #else
580  icon = CreateIconFromResourceEx(imageData, entry->icHeader.biSizeImage, sig == 1, 0x00030000, cx[index], cy[index], flags);
581 #endif
582 
583  HeapFree(GetProcessHeap(), 0, cursorData);
584 
585  if (icon)
586  {
587  if (RetPtr)
588  RetPtr[index] = icon;
589  else
590  DestroyIcon(icon);
591 
592  iconCount = 1;
593  break;
594  }
595  }
596  }
597  }
598  ret = iconCount; /* return number of retrieved icons */
599  }
600 /* end ico file */
601 
602 /* exe/dll */
603  else if( sig == IMAGE_NT_SIGNATURE )
604  {
605  BYTE *idata, *igdata;
606  const IMAGE_RESOURCE_DIRECTORY *rootresdir, *iconresdir, *icongroupresdir;
607  const IMAGE_RESOURCE_DATA_ENTRY *idataent, *igdataent;
608  const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
609  ULONG size;
610  UINT i;
611 
613  if (!rootresdir)
614  {
615  WARN("haven't found section for resource directory.\n");
616  goto end;
617  }
618 
619  /* search for the group icon directory */
620  if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir)))
621  {
622  WARN("No Icongroupresourcedirectory!\n");
623  goto end; /* failure */
624  }
625  iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries;
626 
627  /* only number of icons requested */
628  if( !pIconId )
629  {
630  ret = iconDirCount;
631  goto end; /* success */
632  }
633 
634  if( nIconIndex < 0 )
635  {
636  /* search resource id */
637  int n = 0;
638  int iId = abs(nIconIndex);
639  const IMAGE_RESOURCE_DIRECTORY_ENTRY* xprdeTmp = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1);
640 
641  while(n<iconDirCount && xprdeTmp)
642  {
643  if(xprdeTmp->Id == iId)
644  {
645  nIconIndex = n;
646  break;
647  }
648  n++;
649  xprdeTmp++;
650  }
651  if (nIconIndex < 0)
652  {
653  WARN("resource id %d not found\n", iId);
654  goto end; /* failure */
655  }
656  }
657  else
658  {
659  /* check nIconIndex to be in range */
660  if (nIconIndex >= iconDirCount)
661  {
662  WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
663  goto end; /* failure */
664  }
665  }
666 
667  /* assure we don't get too much */
668  if( nIcons > iconDirCount - nIconIndex )
669  nIcons = iconDirCount - nIconIndex;
670 
671  /* starting from specified index */
672  xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex;
673 
674  for (i=0; i < nIcons; i++,xresent++)
675  {
676  const IMAGE_RESOURCE_DIRECTORY *resdir;
677 
678  /* go down this resource entry, name */
679  resdir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)rootresdir + xresent->OffsetToDirectory);
680 
681  /* default language (0) */
682  resdir = find_entry_default(resdir,rootresdir);
683  igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;
684 
685  /* lookup address in mapped image for virtual address */
686  igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL);
687  if (!igdata)
688  {
689  FIXME("no matching real address for icongroup!\n");
690  goto end; /* failure */
691  }
692  pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags);
693  if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags);
694  }
695 
696  if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir)))
697  {
698  WARN("No Iconresourcedirectory!\n");
699  goto end; /* failure */
700  }
701 
702  for (i=0; i<nIcons; i++)
703  {
704  const IMAGE_RESOURCE_DIRECTORY *xresdir;
705  xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
706  if( !xresdir )
707  {
708  WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
709  RetPtr[i]=0;
710  continue;
711  }
712  xresdir = find_entry_default(xresdir, rootresdir);
713  idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;
714 
715  idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL);
716  if (!idata)
717  {
718  WARN("no matching real address found for icondata!\n");
719  RetPtr[i]=0;
720  continue;
721  }
722  RetPtr[i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx1, cy1, flags);
723  if (cx2 && cy2)
724  RetPtr[++i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx2, cy2, flags);
725  }
726  ret = i; /* return number of retrieved icons */
727  } /* if(sig == IMAGE_NT_SIGNATURE) */
728 
729 end:
730  UnmapViewOfFile(peimage); /* success */
731  return ret;
732 }
733 
734 /***********************************************************************
735  * PrivateExtractIconsW [USER32.@]
736  *
737  * NOTES
738  * If HIWORD(sizeX) && HIWORD(sizeY) 2 * ((nIcons + 1) MOD 2) icons are
739  * returned, with the LOWORD size icon first and the HIWORD size icon
740  * second.
741  * Also the Windows equivalent does extract icons in a strange way if
742  * nIndex is negative. Our implementation treats a negative nIndex as
743  * looking for that resource identifier for the first icon to retrieve.
744  *
745  * FIXME:
746  * should also support 16 bit EXE + DLLs, cursor and animated cursor as
747  * well as bitmap files.
748  */
749 
751  LPCWSTR lpwstrFile,
752  int nIndex,
753  int sizeX,
754  int sizeY,
755  HICON * phicon, /* [out] pointer to array of nIcons HICON handles */
756  UINT* pIconId, /* [out] pointer to array of nIcons icon identifiers or NULL */
757  UINT nIcons, /* [in] number of icons to retrieve */
758  UINT flags ) /* [in] LR_* flags used by LoadImage */
759 {
760  TRACE("%s %d %dx%d %p %p %d 0x%08x\n",
761  debugstr_w(lpwstrFile), nIndex, sizeX, sizeY, phicon, pIconId, nIcons, flags);
762 
763  if ((nIcons & 1) && HIWORD(sizeX) && HIWORD(sizeY))
764  {
765  WARN("Uneven number %d of icons requested for small and large icons!\n", nIcons);
766  }
767  return ICO_ExtractIconExW(lpwstrFile, phicon, nIndex, nIcons, sizeX, sizeY, pIconId, flags);
768 }
769 
770 /***********************************************************************
771  * PrivateExtractIconsA [USER32.@]
772  */
773 
775  LPCSTR lpstrFile,
776  int nIndex,
777  int sizeX,
778  int sizeY,
779  HICON * phicon, /* [out] pointer to array of nIcons HICON handles */
780  UINT* piconid, /* [out] pointer to array of nIcons icon identifiers or NULL */
781  UINT nIcons, /* [in] number of icons to retrieve */
782  UINT flags ) /* [in] LR_* flags used by LoadImage */
783 {
784  UINT ret;
785  INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
786  LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
787 #ifdef __REACTOS__
788  if (lpwstrFile == NULL)
789  return 0;
790 #endif
791 
792  MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len);
793  ret = PrivateExtractIconsW(lpwstrFile, nIndex, sizeX, sizeY, phicon, piconid, nIcons, flags);
794 
795  HeapFree(GetProcessHeap(), 0, lpwstrFile);
796  return ret;
797 }
798 
799 /***********************************************************************
800  * PrivateExtractIconExW [USER32.@]
801  * NOTES
802  * if nIndex == -1 it returns the number of icons in any case !!!
803  */
805  LPCWSTR lpwstrFile,
806  int nIndex,
807  HICON * phIconLarge,
808  HICON * phIconSmall,
809  UINT nIcons )
810 {
811  DWORD cyicon, cysmicon, cxicon, cxsmicon;
812  UINT ret = 0;
813 
814  TRACE("%s %d %p %p %d\n",
815  debugstr_w(lpwstrFile),nIndex,phIconLarge, phIconSmall, nIcons);
816 
817  if (nIndex == -1)
818  /* get the number of icons */
819  return ICO_ExtractIconExW(lpwstrFile, NULL, 0, 0, 0, 0, NULL, LR_DEFAULTCOLOR);
820 
821  if (nIcons == 1 && phIconSmall && phIconLarge)
822  {
823  HICON hIcon[2];
824  cxicon = GetSystemMetrics(SM_CXICON);
825  cyicon = GetSystemMetrics(SM_CYICON);
826  cxsmicon = GetSystemMetrics(SM_CXSMICON);
827  cysmicon = GetSystemMetrics(SM_CYSMICON);
828 
829  ret = ICO_ExtractIconExW(lpwstrFile, hIcon, nIndex, 2, cxicon | (cxsmicon<<16),
830  cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR);
831  *phIconLarge = hIcon[0];
832  *phIconSmall = hIcon[1];
833  return ret;
834  }
835 
836  if (phIconSmall)
837  {
838  /* extract n small icons */
839  cxsmicon = GetSystemMetrics(SM_CXSMICON);
840  cysmicon = GetSystemMetrics(SM_CYSMICON);
841  ret = ICO_ExtractIconExW(lpwstrFile, phIconSmall, nIndex, nIcons, cxsmicon,
842  cysmicon, NULL, LR_DEFAULTCOLOR);
843  }
844  if (phIconLarge)
845  {
846  /* extract n large icons */
847  cxicon = GetSystemMetrics(SM_CXICON);
848  cyicon = GetSystemMetrics(SM_CYICON);
849  ret = ICO_ExtractIconExW(lpwstrFile, phIconLarge, nIndex, nIcons, cxicon,
850  cyicon, NULL, LR_DEFAULTCOLOR);
851  }
852  return ret;
853 }
854 
855 /***********************************************************************
856  * PrivateExtractIconExA [USER32.@]
857  */
859  LPCSTR lpstrFile,
860  int nIndex,
861  HICON * phIconLarge,
862  HICON * phIconSmall,
863  UINT nIcons )
864 {
865  UINT ret;
866  INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
867  LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
868 #ifdef __REACTOS__
869  if (lpwstrFile == NULL)
870  return 0;
871 #endif
872 
873  TRACE("%s %d %p %p %d\n", lpstrFile, nIndex, phIconLarge, phIconSmall, nIcons);
874 
875  MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len);
876  ret = PrivateExtractIconExW(lpwstrFile, nIndex, phIconLarge, phIconSmall, nIcons);
877  HeapFree(GetProcessHeap(), 0, lpwstrFile);
878  return ret;
879 }
BYTE bHeight
Definition: exticon.c:40
#define abs(i)
Definition: fconv.c:206
struct taganiheader aniheader
DWORD get_best_icon_file_offset(const LPBYTE dir, DWORD dwFileSize, int cxDesired, int cyDesired, BOOL bIcon, DWORD fuLoad, POINT *ptHotSpot)
#define max(a, b)
Definition: svc.c:63
#define RT_GROUP_ICON
Definition: pedump.c:375
static HICON
Definition: imagelist.c:84
#define CloseHandle
Definition: compat.h:739
WORD offset
Definition: typelib.c:81
UINT WINAPI PrivateExtractIconsW(LPCWSTR lpwstrFile, int nIndex, int sizeX, int sizeY, HICON *phicon, UINT *pIconId, UINT nIcons, UINT flags)
Definition: exticon.c:750
WORD idCount
Definition: exticon.c:53
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define MapViewOfFile
Definition: compat.h:745
BYTE bColorCount
Definition: exticon.c:41
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
int WINAPI LookupIconIdFromDirectoryEx(_In_reads_bytes_(sizeof(NEWHEADER)) PBYTE, _In_ BOOL, _In_ int, _In_ int, _In_ UINT)
WORD idCount
Definition: ntusrtyp.h:101
ULONG OffsetToDirectory
Definition: ntimage.h:194
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MAKEWORD(a, b)
Definition: typedefs.h:248
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2022
#define TRUE
Definition: types.h:120
WORD idType
Definition: exticon.c:52
#define CP_ACP
Definition: compat.h:109
GLuint GLuint GLsizei count
Definition: gl.h:1545
UINT WINAPI PrivateExtractIconExW(LPCWSTR lpwstrFile, int nIndex, HICON *phIconLarge, HICON *phIconSmall, UINT nIcons)
Definition: exticon.c:804
#define WARN(fmt,...)
Definition: debug.h:112
DWORD dwFileSize
Definition: more.c:40
#define RtlImageRvaToVa
Definition: compat.h:807
struct _ICONIMAGE * LPICONIMAGE
GLdouble n
Definition: glext.h:7729
#define ARRAY_SIZE(x)
Definition: exticon.c:28
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define ZeroMemory
Definition: winbase.h:1670
#define SM_CYSMICON
Definition: winuser.h:1007
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:58
static BYTE * ICO_LoadIcon(LPBYTE peimage, LPicoICONDIRENTRY lpiIDE, ULONG *uSize)
Definition: exticon.c:219
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD Id
DWORD cframes
Definition: exticon.c:79
WORD idReserved
Definition: ntusrtyp.h:99
DWORD dwImageOffset
Definition: exticon.c:46
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
unsigned char * LPBYTE
Definition: typedefs.h:53
#define SEC_COMMIT
Definition: mmtypes.h:99
DWORD cbitcount
Definition: exticon.c:83
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
WINE_DEFAULT_DEBUG_CHANNEL(icon)
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:111
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define SM_CXICON
Definition: winuser.h:966
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:585
Definition: pedump.c:457
#define FILE_MAP_READ
Definition: compat.h:776
GLuint index
Definition: glext.h:6031
unsigned int dir
Definition: maze.c:112
const char * LPCSTR
Definition: xmlstorage.h:183
#define OPEN_EXISTING
Definition: compat.h:775
BYTE bReserved
Definition: exticon.c:42
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
DWORD OffsetToData
Definition: pedump.c:459
#define NE_RSCTYPE_ICON
Definition: exticon.c:89
#define WIDTHBYTES(i)
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:736
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
ULONG RGBQUAD
Definition: precomp.h:50
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
GLintptr offset
Definition: glext.h:5920
static UINT ICO_ExtractIconExW(LPCWSTR lpszExeFileName, HICON *RetPtr, INT nIconIndex, UINT nIcons, UINT cxDesired, UINT cyDesired, UINT *pIconId, UINT flags)
Definition: exticon.c:278
DWORD cx
Definition: exticon.c:81
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
#define CopyMemory
Definition: winbase.h:1668
#define RT_ICON
Definition: pedump.c:365
unsigned short WORD
Definition: ntddk_ex.h:93
int WINAPI GetSystemMetrics(_In_ int)
unsigned long DWORD
Definition: ntddk_ex.h:95
HICON WINAPI CreateIconFromResourceEx(_In_reads_bytes_(dwResSize) PBYTE presbits, _In_ DWORD dwResSize, _In_ BOOL fIcon, _In_ DWORD dwVer, _In_ int cxDesired, _In_ int cyDesired, _In_ UINT Flags)
DWORD biSizeImage
Definition: amvideo.idl:36
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
WORD idReserved
Definition: exticon.c:51
GLbitfield flags
Definition: glext.h:7161
type_id
#define SM_CXSMICON
Definition: winuser.h:1006
GLuint GLuint end
Definition: gl.h:1545
USHORT Id
Definition: ntimage.h:189
int ret
#define SM_CYICON
Definition: winuser.h:967
#define index(s, c)
Definition: various.h:29
#define RtlImageDirectoryEntryToData
Definition: compat.h:809
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
uint32_t entry
Definition: isohybrid.c:63
#define NE_RSCTYPE_GROUP_ICON
Definition: exticon.c:90
DWORD cplanes
Definition: exticon.c:84
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define IMAGE_OS2_SIGNATURE
Definition: pedump.c:90
static const IMAGE_RESOURCE_DIRECTORY * find_entry_default(const IMAGE_RESOURCE_DIRECTORY *dir, const void *root)
Definition: exticon.c:150
#define GENERIC_READ
Definition: compat.h:135
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned char BYTE
Definition: xxhash.c:193
WORD length
Definition: typelib.c:82
DWORD WINAPI SearchPathW(IN LPCWSTR lpPath OPTIONAL, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart OPTIONAL)
Definition: path.c:1298
Definition: pedump.c:413
DWORD flags
Definition: exticon.c:86
DWORD csteps
Definition: exticon.c:80
static BYTE * ICO_GetIconDirectory(LPBYTE peimage, LPicoICONDIR *lplpiID, ULONG *uSize)
Definition: exticon.c:232
WORD count
Definition: typelib.c:92
static const IMAGE_RESOURCE_DIRECTORY * find_entry_by_id(const IMAGE_RESOURCE_DIRECTORY *dir, WORD id, const void *root)
Definition: exticon.c:124
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HICON hIcon
Definition: msconfig.c:44
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
DWORD cy
Definition: exticon.c:82
unsigned short UINT16
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
WORD type_id
Definition: typelib.c:91
#define PAGE_READONLY
Definition: compat.h:138
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
DWORD jifrate
Definition: exticon.c:85
DWORD dwBytesInRes
Definition: exticon.c:45
#define MultiByteToWideChar
Definition: compat.h:110
#define RtlImageNtHeader
Definition: compat.h:806
#define CreateFileW
Definition: compat.h:741
_Out_opt_ int * cx
Definition: commctrl.h:585
DWORD cbsizeof
Definition: exticon.c:78
static DWORD USER32_GetResourceTable(LPBYTE peimage, DWORD pesize, LPBYTE *retptr)
Definition: exticon.c:161
CURSORICONDIRENTRY idEntries[1]
Definition: ntusrtyp.h:102
#define HIWORD(l)
Definition: typedefs.h:247
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
UINT WINAPI PrivateExtractIconsA(LPCSTR lpstrFile, int nIndex, int sizeX, int sizeY, HICON *phicon, UINT *piconid, UINT nIcons, UINT flags)
Definition: exticon.c:774
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define IMAGE_DIRECTORY_ENTRY_RESOURCE
Definition: pedump.c:261
struct icoICONDIR * LPicoICONDIR
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1827
static BYTE * USER32_LoadResource(LPBYTE peimage, NE_NAMEINFO *pNInfo, WORD sizeShift, ULONG *uSize)
Definition: exticon.c:208
#define LR_DEFAULTCOLOR
Definition: winuser.h:1081
#define UnmapViewOfFile
Definition: compat.h:746
UINT WINAPI PrivateExtractIconExA(LPCSTR lpstrFile, int nIndex, HICON *phIconLarge, HICON *phIconSmall, UINT nIcons)
Definition: exticon.c:858
icoICONDIRENTRY idEntries[1]
Definition: exticon.c:54
WORD wPlanes
Definition: exticon.c:43
#define LOWORD(l)
Definition: pedump.c:82
struct icoICONDIRENTRY * LPicoICONDIRENTRY
#define HeapFree(x, y, z)
Definition: compat.h:735
WORD wBitCount
Definition: exticon.c:44
DWORD Size
Definition: pedump.c:460