ReactOS 0.4.15-dev-5836-g942b022
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
37typedef 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
49typedef 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
57typedef struct
58{
61 WORD flags;
62 WORD id;
64 WORD usage;
66
67typedef struct
68{
70 WORD count;
71 DWORD resloader;
73
74// From: James Houghtaling
75// https://www.moon-soft.com/program/FORMAT/windows/ani.htm
76typedef 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
88
89#define NE_RSCTYPE_ICON 0x8003
90#define NE_RSCTYPE_GROUP_ICON 0x800e
91
92#include <poppack.h>
93
94#if 0
95static 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}
102static 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
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{
155 return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry->OffsetToDirectory);
156}
157
158/*************************************************************************
159 * USER32_GetResourceTable
160 */
161static 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 */
208static 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 */
219static 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 */
232static 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;
291 DWORD sig;
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 */
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__
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#ifdef __REACTOS__
620 /* Check for boundary limit (and overflow) */
621 if (((ULONG_PTR)(rootresdir + 1) < (ULONG_PTR)rootresdir) ||
622 ((ULONG_PTR)(rootresdir + 1) > (ULONG_PTR)peimage + fsizel))
623 {
624 goto end;
625 }
626#endif
627
628 /* search for the group icon directory */
629 if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir)))
630 {
631 WARN("No Icongroupresourcedirectory!\n");
632 goto end; /* failure */
633 }
634 iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries;
635
636 /* only number of icons requested */
637 if( !pIconId )
638 {
639 ret = iconDirCount;
640 goto end; /* success */
641 }
642
643 if( nIconIndex < 0 )
644 {
645 /* search resource id */
646 int n = 0;
647 int iId = abs(nIconIndex);
648 const IMAGE_RESOURCE_DIRECTORY_ENTRY* xprdeTmp = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1);
649
650 while(n<iconDirCount && xprdeTmp)
651 {
652 if(xprdeTmp->Id == iId)
653 {
654 nIconIndex = n;
655 break;
656 }
657 n++;
658 xprdeTmp++;
659 }
660 if (nIconIndex < 0)
661 {
662 WARN("resource id %d not found\n", iId);
663 goto end; /* failure */
664 }
665 }
666 else
667 {
668 /* check nIconIndex to be in range */
669 if (nIconIndex >= iconDirCount)
670 {
671 WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
672 goto end; /* failure */
673 }
674 }
675
676 /* assure we don't get too much */
677 if( nIcons > iconDirCount - nIconIndex )
678 nIcons = iconDirCount - nIconIndex;
679
680 /* starting from specified index */
681 xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex;
682
683 for (i=0; i < nIcons; i++,xresent++)
684 {
685 const IMAGE_RESOURCE_DIRECTORY *resdir;
686
687 /* go down this resource entry, name */
688 resdir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)rootresdir + xresent->OffsetToDirectory);
689
690 /* default language (0) */
691 resdir = find_entry_default(resdir,rootresdir);
692 igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;
693
694 /* lookup address in mapped image for virtual address */
695 igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL);
696 if (!igdata)
697 {
698 FIXME("no matching real address for icongroup!\n");
699 goto end; /* failure */
700 }
701 pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags);
702 if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags);
703 }
704
705 if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir)))
706 {
707 WARN("No Iconresourcedirectory!\n");
708 goto end; /* failure */
709 }
710
711 for (i=0; i<nIcons; i++)
712 {
713 const IMAGE_RESOURCE_DIRECTORY *xresdir;
714 xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
715 if( !xresdir )
716 {
717 WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
718 RetPtr[i]=0;
719 continue;
720 }
721 xresdir = find_entry_default(xresdir, rootresdir);
722 idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;
723
724 idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL);
725 if (!idata)
726 {
727 WARN("no matching real address found for icondata!\n");
728 RetPtr[i]=0;
729 continue;
730 }
731 RetPtr[i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx1, cy1, flags);
732 if (cx2 && cy2)
733 RetPtr[++i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx2, cy2, flags);
734 }
735 ret = i; /* return number of retrieved icons */
736 } /* if(sig == IMAGE_NT_SIGNATURE) */
737
738end:
739 UnmapViewOfFile(peimage); /* success */
740 return ret;
741}
742
743/***********************************************************************
744 * PrivateExtractIconsW [USER32.@]
745 *
746 * NOTES
747 * If HIWORD(sizeX) && HIWORD(sizeY) 2 * ((nIcons + 1) MOD 2) icons are
748 * returned, with the LOWORD size icon first and the HIWORD size icon
749 * second.
750 * Also the Windows equivalent does extract icons in a strange way if
751 * nIndex is negative. Our implementation treats a negative nIndex as
752 * looking for that resource identifier for the first icon to retrieve.
753 *
754 * FIXME:
755 * should also support 16 bit EXE + DLLs, cursor and animated cursor as
756 * well as bitmap files.
757 */
758
760 LPCWSTR lpwstrFile,
761 int nIndex,
762 int sizeX,
763 int sizeY,
764 HICON * phicon, /* [out] pointer to array of nIcons HICON handles */
765 UINT* pIconId, /* [out] pointer to array of nIcons icon identifiers or NULL */
766 UINT nIcons, /* [in] number of icons to retrieve */
767 UINT flags ) /* [in] LR_* flags used by LoadImage */
768{
769 TRACE("%s %d %dx%d %p %p %d 0x%08x\n",
770 debugstr_w(lpwstrFile), nIndex, sizeX, sizeY, phicon, pIconId, nIcons, flags);
771
772 if ((nIcons & 1) && HIWORD(sizeX) && HIWORD(sizeY))
773 {
774 WARN("Uneven number %d of icons requested for small and large icons!\n", nIcons);
775 }
776 return ICO_ExtractIconExW(lpwstrFile, phicon, nIndex, nIcons, sizeX, sizeY, pIconId, flags);
777}
778
779/***********************************************************************
780 * PrivateExtractIconsA [USER32.@]
781 */
782
784 LPCSTR lpstrFile,
785 int nIndex,
786 int sizeX,
787 int sizeY,
788 HICON * phicon, /* [out] pointer to array of nIcons HICON handles */
789 UINT* piconid, /* [out] pointer to array of nIcons icon identifiers or NULL */
790 UINT nIcons, /* [in] number of icons to retrieve */
791 UINT flags ) /* [in] LR_* flags used by LoadImage */
792{
793 UINT ret;
794 INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
795 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
796#ifdef __REACTOS__
797 if (lpwstrFile == NULL)
798 return 0;
799#endif
800
801 MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len);
802 ret = PrivateExtractIconsW(lpwstrFile, nIndex, sizeX, sizeY, phicon, piconid, nIcons, flags);
803
804 HeapFree(GetProcessHeap(), 0, lpwstrFile);
805 return ret;
806}
807
808/***********************************************************************
809 * PrivateExtractIconExW [USER32.@]
810 * NOTES
811 * if nIndex == -1 it returns the number of icons in any case !!!
812 */
814 LPCWSTR lpwstrFile,
815 int nIndex,
816 HICON * phIconLarge,
817 HICON * phIconSmall,
818 UINT nIcons )
819{
820 DWORD cyicon, cysmicon, cxicon, cxsmicon;
821 UINT ret = 0;
822
823 TRACE("%s %d %p %p %d\n",
824 debugstr_w(lpwstrFile),nIndex,phIconLarge, phIconSmall, nIcons);
825
826 if (nIndex == -1)
827 /* get the number of icons */
828 return ICO_ExtractIconExW(lpwstrFile, NULL, 0, 0, 0, 0, NULL, LR_DEFAULTCOLOR);
829
830 if (nIcons == 1 && phIconSmall && phIconLarge)
831 {
832 HICON hIcon[2];
833 cxicon = GetSystemMetrics(SM_CXICON);
834 cyicon = GetSystemMetrics(SM_CYICON);
835 cxsmicon = GetSystemMetrics(SM_CXSMICON);
836 cysmicon = GetSystemMetrics(SM_CYSMICON);
837
838 ret = ICO_ExtractIconExW(lpwstrFile, hIcon, nIndex, 2, cxicon | (cxsmicon<<16),
839 cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR);
840 *phIconLarge = hIcon[0];
841 *phIconSmall = hIcon[1];
842 return ret;
843 }
844
845 if (phIconSmall)
846 {
847 /* extract n small icons */
848 cxsmicon = GetSystemMetrics(SM_CXSMICON);
849 cysmicon = GetSystemMetrics(SM_CYSMICON);
850 ret = ICO_ExtractIconExW(lpwstrFile, phIconSmall, nIndex, nIcons, cxsmicon,
851 cysmicon, NULL, LR_DEFAULTCOLOR);
852 }
853 if (phIconLarge)
854 {
855 /* extract n large icons */
856 cxicon = GetSystemMetrics(SM_CXICON);
857 cyicon = GetSystemMetrics(SM_CYICON);
858 ret = ICO_ExtractIconExW(lpwstrFile, phIconLarge, nIndex, nIcons, cxicon,
859 cyicon, NULL, LR_DEFAULTCOLOR);
860 }
861 return ret;
862}
863
864/***********************************************************************
865 * PrivateExtractIconExA [USER32.@]
866 */
868 LPCSTR lpstrFile,
869 int nIndex,
870 HICON * phIconLarge,
871 HICON * phIconSmall,
872 UINT nIcons )
873{
874 UINT ret;
875 INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
876 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
877#ifdef __REACTOS__
878 if (lpwstrFile == NULL)
879 return 0;
880#endif
881
882 TRACE("%s %d %p %p %d\n", lpstrFile, nIndex, phIconLarge, phIconSmall, nIcons);
883
884 MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len);
885 ret = PrivateExtractIconExW(lpwstrFile, nIndex, phIconLarge, phIconSmall, nIcons);
886 HeapFree(GetProcessHeap(), 0, lpwstrFile);
887 return ret;
888}
DWORD Id
unsigned short UINT16
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned int dir
Definition: maze.c:112
#define WIDTHBYTES(i)
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define PAGE_READONLY
Definition: compat.h:138
#define UnmapViewOfFile
Definition: compat.h:746
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
#define RtlImageDirectoryEntryToData
Definition: compat.h:809
#define GENERIC_READ
Definition: compat.h:135
#define RtlImageRvaToVa
Definition: compat.h:807
#define RtlImageNtHeader
Definition: compat.h:806
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define MapViewOfFile
Definition: compat.h:745
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
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
ULONG RGBQUAD
Definition: precomp.h:50
static const IMAGE_RESOURCE_DIRECTORY * find_entry_default(const IMAGE_RESOURCE_DIRECTORY *dir, const void *root)
Definition: exticon.c:150
struct taganiheader aniheader
struct icoICONDIRENTRY * LPicoICONDIRENTRY
UINT WINAPI PrivateExtractIconExW(LPCWSTR lpwstrFile, int nIndex, HICON *phIconLarge, HICON *phIconSmall, UINT nIcons)
Definition: exticon.c:813
#define ARRAY_SIZE(x)
Definition: exticon.c:28
static BYTE * USER32_LoadResource(LPBYTE peimage, NE_NAMEINFO *pNInfo, WORD sizeShift, ULONG *uSize)
Definition: exticon.c:208
UINT WINAPI PrivateExtractIconsA(LPCSTR lpstrFile, int nIndex, int sizeX, int sizeY, HICON *phicon, UINT *piconid, UINT nIcons, UINT flags)
Definition: exticon.c:783
static BYTE * ICO_GetIconDirectory(LPBYTE peimage, LPicoICONDIR *lplpiID, ULONG *uSize)
Definition: exticon.c:232
static UINT ICO_ExtractIconExW(LPCWSTR lpszExeFileName, HICON *RetPtr, INT nIconIndex, UINT nIcons, UINT cxDesired, UINT cyDesired, UINT *pIconId, UINT flags)
Definition: exticon.c:278
#define NE_RSCTYPE_ICON
Definition: exticon.c:89
static DWORD USER32_GetResourceTable(LPBYTE peimage, DWORD pesize, LPBYTE *retptr)
Definition: exticon.c:161
DWORD get_best_icon_file_offset(const LPBYTE dir, DWORD dwFileSize, int cxDesired, int cyDesired, BOOL bIcon, DWORD fuLoad, POINT *ptHotSpot)
UINT WINAPI PrivateExtractIconsW(LPCWSTR lpwstrFile, int nIndex, int sizeX, int sizeY, HICON *phicon, UINT *pIconId, UINT nIcons, UINT flags)
Definition: exticon.c:759
static const IMAGE_RESOURCE_DIRECTORY * find_entry_by_id(const IMAGE_RESOURCE_DIRECTORY *dir, WORD id, const void *root)
Definition: exticon.c:124
struct icoICONDIR * LPicoICONDIR
#define NE_RSCTYPE_GROUP_ICON
Definition: exticon.c:90
static BYTE * ICO_LoadIcon(LPBYTE peimage, LPicoICONDIRENTRY lpiIDE, ULONG *uSize)
Definition: exticon.c:219
UINT WINAPI PrivateExtractIconExA(LPCSTR lpstrFile, int nIndex, HICON *phIconLarge, HICON *phIconSmall, UINT nIcons)
Definition: exticon.c:867
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint index
Definition: glext.h:6031
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
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
type_id
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_w
Definition: kernel32.h:32
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HICON
Definition: imagelist.c:84
#define min(a, b)
Definition: monoChain.cc:55
DWORD dwFileSize
Definition: more.c:40
HICON hIcon
Definition: msconfig.c:44
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define SEC_COMMIT
Definition: mmtypes.h:99
#define DWORD
Definition: nt_native.h:44
struct _ICONIMAGE * LPICONIMAGE
#define LOWORD(l)
Definition: pedump.c:82
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define RT_ICON
Definition: pedump.c:365
#define IMAGE_OS2_SIGNATURE
Definition: pedump.c:90
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
#define RT_GROUP_ICON
Definition: pedump.c:375
#define IMAGE_DIRECTORY_ENTRY_RESOURCE
Definition: pedump.c:261
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
#define TRACE(s)
Definition: solgame.cpp:4
DWORD biSizeImage
Definition: amvideo.idl:36
WORD idReserved
Definition: ntusrtyp.h:99
CURSORICONDIRENTRY idEntries[1]
Definition: ntusrtyp.h:102
WORD idCount
Definition: ntusrtyp.h:101
WORD offset
Definition: typelib.c:81
WORD length
Definition: typelib.c:82
WORD type_id
Definition: typelib.c:91
WORD count
Definition: typelib.c:92
Definition: pedump.c:458
DWORD OffsetToData
Definition: pedump.c:459
DWORD Size
Definition: pedump.c:460
Definition: pedump.c:414
ULONG OffsetToDirectory
Definition: ntimage.h:194
USHORT Id
Definition: ntimage.h:189
WORD wBitCount
Definition: exticon.c:44
DWORD dwImageOffset
Definition: exticon.c:46
BYTE bColorCount
Definition: exticon.c:41
WORD wPlanes
Definition: exticon.c:43
DWORD dwBytesInRes
Definition: exticon.c:45
BYTE bReserved
Definition: exticon.c:42
BYTE bHeight
Definition: exticon.c:40
WORD idCount
Definition: exticon.c:53
WORD idReserved
Definition: exticon.c:51
icoICONDIRENTRY idEntries[1]
Definition: exticon.c:54
WORD idType
Definition: exticon.c:52
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
DWORD cbsizeof
Definition: exticon.c:78
DWORD flags
Definition: exticon.c:86
DWORD csteps
Definition: exticon.c:80
DWORD jifrate
Definition: exticon.c:85
DWORD cy
Definition: exticon.c:82
DWORD cx
Definition: exticon.c:81
DWORD cplanes
Definition: exticon.c:84
DWORD cframes
Definition: exticon.c:79
DWORD cbitcount
Definition: exticon.c:83
#define max(a, b)
Definition: svc.c:63
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
#define MAKEWORD(a, b)
Definition: typedefs.h:248
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
int ret
#define ZeroMemory
Definition: winbase.h:1670
DWORD WINAPI GetLastError(void)
Definition: except.c:1040
#define CopyMemory
Definition: winbase.h:1668
#define WINAPI
Definition: msvc.h:6
#define SM_CYSMICON
Definition: winuser.h:1007
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)
#define SM_CXSMICON
Definition: winuser.h:1006
#define SM_CYICON
Definition: winuser.h:967
int WINAPI LookupIconIdFromDirectoryEx(_In_reads_bytes_(sizeof(NEWHEADER)) PBYTE, _In_ BOOL, _In_ int, _In_ int, _In_ UINT)
#define LR_DEFAULTCOLOR
Definition: winuser.h:1081
#define SM_CXICON
Definition: winuser.h:966
int WINAPI GetSystemMetrics(_In_ int)
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2022
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193