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
8 * Copyright 2000 Juergen Schmied
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <stdlib.h> /* abs() */
29 #include <sys/types.h>
39 #include "wine/winbase16.h"
40 #include "cursoricon.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(icon
);
49 BYTE bWidth
; /* Width, in pixels, of the image */
50 BYTE bHeight
; /* Height, in pixels, of the image */
51 BYTE bColorCount
; /* Number of colors in image (0 if >=8bpp) */
52 BYTE bReserved
; /* Reserved ( must be 0) */
53 WORD wPlanes
; /* Color Planes */
54 WORD wBitCount
; /* Bits per pixel */
55 DWORD dwBytesInRes
; /* How many bytes in this resource? */
56 DWORD dwImageOffset
; /* Where in the file is this image? */
57 } icoICONDIRENTRY
, *LPicoICONDIRENTRY
;
61 WORD idReserved
; /* Reserved (must be 0) */
62 WORD idType
; /* Resource Type (RES_ICON or RES_CURSOR) */
63 WORD idCount
; /* How many images */
64 icoICONDIRENTRY idEntries
[1]; /* An entry for each image (idCount of 'em) */
65 } icoICONDIR
, *LPicoICONDIR
;
70 static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry
)
72 TRACE("width = 0x%08x height = 0x%08x\n", entry
->bWidth
, entry
->bHeight
);
73 TRACE("colors = 0x%08x planes = 0x%08x\n", entry
->bColorCount
, entry
->wPlanes
);
74 TRACE("bitcount = 0x%08x bytesinres = 0x%08lx offset = 0x%08lx\n",
75 entry
->wBitCount
, entry
->dwBytesInRes
, entry
->dwImageOffset
);
77 static void dumpIcoDir ( LPicoICONDIR entry
)
79 TRACE("type = 0x%08x count = 0x%08x\n", entry
->idType
, entry
->idCount
);
83 /**********************************************************************
86 * Find an entry by id in a resource directory
87 * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
89 static const IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY
*dir
,
90 WORD id
, const void *root
)
92 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
95 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
96 min
= dir
->NumberOfNamedEntries
;
97 max
= min
+ dir
->NumberOfIdEntries
- 1;
100 pos
= (min
+ max
) / 2;
101 if (entry
[pos
].u1
.s2
.Id
== id
)
102 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
[pos
].u2
.s3
.OffsetToDirectory
);
103 if (entry
[pos
].u1
.s2
.Id
> id
) max
= pos
- 1;
109 /**********************************************************************
112 * Find a default entry in a resource directory
113 * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
115 static const IMAGE_RESOURCE_DIRECTORY
*find_entry_default( const IMAGE_RESOURCE_DIRECTORY
*dir
,
118 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
119 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
120 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
->u2
.s3
.OffsetToDirectory
);
123 /*************************************************************************
124 * USER32_GetResourceTable
126 static DWORD
USER32_GetResourceTable(LPBYTE peimage
,DWORD pesize
,LPBYTE
*retptr
)
128 IMAGE_DOS_HEADER
* mz_header
;
130 TRACE("%p %p\n", peimage
, retptr
);
134 mz_header
= (IMAGE_DOS_HEADER
*) peimage
;
136 if (mz_header
->e_magic
!= IMAGE_DOS_SIGNATURE
)
138 if (mz_header
->e_cblp
== 1) /* .ICO file ? */
140 *retptr
= (LPBYTE
)-1; /* ICONHEADER.idType, must be 1 */
144 return 0; /* failed */
146 if (mz_header
->e_lfanew
>= pesize
) {
147 return 0; /* failed, happens with PKZIP DOS Exes for instance. */
149 if (*((DWORD
*)(peimage
+ mz_header
->e_lfanew
)) == IMAGE_NT_SIGNATURE
)
150 return IMAGE_NT_SIGNATURE
;
152 if (*((WORD
*)(peimage
+ mz_header
->e_lfanew
)) == IMAGE_OS2_SIGNATURE
)
154 IMAGE_OS2_HEADER
* ne_header
;
156 ne_header
= (IMAGE_OS2_HEADER
*)(peimage
+ mz_header
->e_lfanew
);
158 if (ne_header
->ne_magic
!= IMAGE_OS2_SIGNATURE
)
161 if( (ne_header
->ne_restab
- ne_header
->ne_rsrctab
) <= sizeof(NE_TYPEINFO
) )
162 *retptr
= (LPBYTE
)-1;
164 *retptr
= peimage
+ mz_header
->e_lfanew
+ ne_header
->ne_rsrctab
;
166 return IMAGE_OS2_SIGNATURE
;
168 return 0; /* failed */
170 /*************************************************************************
171 * USER32_LoadResource
173 static BYTE
* USER32_LoadResource( LPBYTE peimage
, NE_NAMEINFO
* pNInfo
, WORD sizeShift
, ULONG
*uSize
)
175 TRACE("%p %p 0x%08x\n", peimage
, pNInfo
, sizeShift
);
177 *uSize
= (DWORD
)pNInfo
->length
<< sizeShift
;
178 return peimage
+ ((DWORD
)pNInfo
->offset
<< sizeShift
);
181 /*************************************************************************
184 static BYTE
* ICO_LoadIcon( LPBYTE peimage
, LPicoICONDIRENTRY lpiIDE
, ULONG
*uSize
)
186 TRACE("%p %p\n", peimage
, lpiIDE
);
188 *uSize
= lpiIDE
->dwBytesInRes
;
189 return peimage
+ lpiIDE
->dwImageOffset
;
192 /*************************************************************************
193 * ICO_GetIconDirectory
195 * Reads .ico file and build phony ICONDIR struct
196 * see http://www.microsoft.com/win32dev/ui/icons.htm
198 #define HEADER_SIZE (sizeof(CURSORICONDIR) - sizeof (CURSORICONDIRENTRY))
199 #define HEADER_SIZE_FILE (sizeof(icoICONDIR) - sizeof (icoICONDIRENTRY))
201 static BYTE
* ICO_GetIconDirectory( LPBYTE peimage
, LPicoICONDIR
* lplpiID
, ULONG
*uSize
)
203 CURSORICONDIR
* lpcid
; /* icon resource in resource-dir format */
204 CURSORICONDIR
* lpID
; /* icon resource in resource format */
207 TRACE("%p %p\n", peimage
, lplpiID
);
209 lpcid
= (CURSORICONDIR
*)peimage
;
211 if( lpcid
->idReserved
|| (lpcid
->idType
!= 1) || (!lpcid
->idCount
) )
214 /* allocate the phony ICONDIR structure */
215 *uSize
= lpcid
->idCount
* sizeof(CURSORICONDIRENTRY
) + HEADER_SIZE
;
216 if( (lpID
= (CURSORICONDIR
*)HeapAlloc(GetProcessHeap(),0, *uSize
) ))
218 /* copy the header */
219 lpID
->idReserved
= lpcid
->idReserved
;
220 lpID
->idType
= lpcid
->idType
;
221 lpID
->idCount
= lpcid
->idCount
;
223 /* copy the entries */
224 for( i
=0; i
< lpcid
->idCount
; i
++ )
226 memcpy((void*)&(lpID
->idEntries
[i
]),(void*)&(lpcid
->idEntries
[i
]), sizeof(CURSORICONDIRENTRY
) - 2);
227 lpID
->idEntries
[i
].wResId
= i
;
230 *lplpiID
= (LPicoICONDIR
)peimage
;
236 /*************************************************************************
237 * ICO_ExtractIconExW [internal]
240 * nIcons = 0: returns number of Icons in file
243 * failure:0; success: number of icons in file (nIcons = 0) or nr of icons retrieved
245 static UINT
ICO_ExtractIconExW(
246 LPCWSTR lpszExeFileName
,
259 UINT16 iconDirCount
= 0,iconCount
= 0;
265 TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName
), nIconIndex
, nIcons
, pIconId
, flags
);
267 hFile
= CreateFileW( lpszExeFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
268 if (hFile
== INVALID_HANDLE_VALUE
) return ret
;
269 fsizel
= GetFileSize(hFile
,&fsizeh
);
272 fmapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
273 CloseHandle( hFile
);
276 WARN("CreateFileMapping error %ld\n", GetLastError() );
280 if ( !(peimage
= MapViewOfFile(fmapping
,FILE_MAP_READ
,0,0,0)))
282 WARN("MapViewOfFile error %ld\n", GetLastError() );
283 CloseHandle( fmapping
);
286 CloseHandle( fmapping
);
288 sig
= USER32_GetResourceTable(peimage
,fsizel
,&pData
);
291 if( sig
==IMAGE_OS2_SIGNATURE
|| sig
==1 ) /* .ICO file */
294 NE_TYPEINFO
*pTInfo
= (NE_TYPEINFO
*)(pData
+ 2);
295 NE_NAMEINFO
*pIconStorage
= NULL
;
296 NE_NAMEINFO
*pIconDir
= NULL
;
297 LPicoICONDIR lpiID
= NULL
;
299 TRACE("-- OS2/icon Signature (0x%08lx)\n", sig
);
301 if( pData
== (BYTE
*)-1 )
303 /* FIXME: pCIDir is allocated on the heap - memory leak */
304 pCIDir
= ICO_GetIconDirectory(peimage
, &lpiID
, &uSize
); /* check for .ICO file */
307 iconDirCount
= 1; iconCount
= lpiID
->idCount
;
308 TRACE("-- icon found %p 0x%08lx 0x%08x 0x%08x\n", pCIDir
, uSize
, iconDirCount
, iconCount
);
311 else while( pTInfo
->type_id
&& !(pIconStorage
&& pIconDir
) )
313 if( pTInfo
->type_id
== NE_RSCTYPE_GROUP_ICON
) /* find icon directory and icon repository */
315 iconDirCount
= pTInfo
->count
;
316 pIconDir
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
317 TRACE("\tfound directory - %i icon families\n", iconDirCount
);
319 if( pTInfo
->type_id
== NE_RSCTYPE_ICON
)
321 iconCount
= pTInfo
->count
;
322 pIconStorage
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
323 TRACE("\ttotal icons - %i\n", iconCount
);
325 pTInfo
= (NE_TYPEINFO
*)((char*)(pTInfo
+1)+pTInfo
->count
*sizeof(NE_NAMEINFO
));
328 if( (pIconStorage
&& pIconDir
) || lpiID
) /* load resources and create icons */
334 else if( nIconIndex
< iconDirCount
)
337 if( nIcons
> iconDirCount
- nIconIndex
)
338 nIcons
= iconDirCount
- nIconIndex
;
340 for( i
= nIconIndex
; i
< nIconIndex
+ nIcons
; i
++ )
342 /* .ICO files have only one icon directory */
343 if( lpiID
== NULL
) /* *.ico */
344 pCIDir
= USER32_LoadResource( peimage
, pIconDir
+ i
, *(WORD
*)pData
, &uSize
);
345 RetPtr
[i
-nIconIndex
] = (HICON
)LookupIconIdFromDirectoryEx( pCIDir
, TRUE
, cxDesired
, cyDesired
, flags
);
348 for( icon
= nIconIndex
; icon
< nIconIndex
+ nIcons
; icon
++ )
352 pCIDir
= ICO_LoadIcon( peimage
, lpiID
->idEntries
+ (int)RetPtr
[icon
-nIconIndex
], &uSize
);
354 for ( i
= 0; i
< iconCount
; i
++ )
355 if ( pIconStorage
[i
].id
== ((int)RetPtr
[icon
-nIconIndex
] | 0x8000) )
356 pCIDir
= USER32_LoadResource( peimage
, pIconStorage
+ i
,*(WORD
*)pData
, &uSize
);
359 RetPtr
[icon
- nIconIndex
] = (HICON
)CreateIconFromResourceEx(pCIDir
, uSize
, TRUE
, 0x00030000, cxDesired
, cyDesired
, flags
);
361 RetPtr
[icon
- nIconIndex
] = 0;
363 ret
= icon
- nIconIndex
; /* return number of retrieved icons */
370 else if( sig
== IMAGE_NT_SIGNATURE
)
373 PIMAGE_DOS_HEADER dheader
;
374 PIMAGE_NT_HEADERS pe_header
;
375 PIMAGE_SECTION_HEADER pe_sections
;
376 const IMAGE_RESOURCE_DIRECTORY
*rootresdir
,*iconresdir
,*icongroupresdir
;
377 const IMAGE_RESOURCE_DATA_ENTRY
*idataent
,*igdataent
;
378 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*xresent
;
381 dheader
= (PIMAGE_DOS_HEADER
)peimage
;
382 pe_header
= (PIMAGE_NT_HEADERS
)(peimage
+dheader
->e_lfanew
); /* it is a pe header, USER32_GetResourceTable checked that */
383 pe_sections
= (PIMAGE_SECTION_HEADER
)(((char*)pe_header
)+sizeof(*pe_header
)); /* probably makes problems with short PE headers...*/
386 /* search for the root resource directory */
387 for (i
=0;i
<pe_header
->FileHeader
.NumberOfSections
;i
++)
389 if (pe_sections
[i
].Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
391 if (fsizel
< pe_sections
[i
].PointerToRawData
+pe_sections
[i
].SizeOfRawData
) {
392 FIXME("File %s too short (section is at %ld bytes, real size is %ld)\n",
393 debugstr_w(lpszExeFileName
),
394 pe_sections
[i
].PointerToRawData
+pe_sections
[i
].SizeOfRawData
,
399 /* FIXME: doesn't work when the resources are not in a separate section */
400 if (pe_sections
[i
].VirtualAddress
== pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
)
402 rootresdir
= (PIMAGE_RESOURCE_DIRECTORY
)(peimage
+pe_sections
[i
].PointerToRawData
);
409 WARN("haven't found section for resource directory.\n");
410 goto end
; /* failure */
413 /* search for the group icon directory */
414 if (!(icongroupresdir
= find_entry_by_id(rootresdir
, LOWORD(RT_GROUP_ICONW
), rootresdir
)))
416 WARN("No Icongroupresourcedirectory!\n");
417 goto end
; /* failure */
419 iconDirCount
= icongroupresdir
->NumberOfNamedEntries
+ icongroupresdir
->NumberOfIdEntries
;
421 /* only number of icons requested */
425 goto end
; /* success */
430 /* search resource id */
432 int iId
= abs(nIconIndex
);
433 PIMAGE_RESOURCE_DIRECTORY_ENTRY xprdeTmp
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(icongroupresdir
+1);
435 while(n
<iconDirCount
&& xprdeTmp
)
437 if(xprdeTmp
->u1
.s2
.Id
== iId
)
447 WARN("resource id %d not found\n", iId
);
448 goto end
; /* failure */
453 /* check nIconIndex to be in range */
454 if (nIconIndex
>= iconDirCount
)
456 WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex
,iconDirCount
);
457 goto end
; /* failure */
461 /* assure we don't get too much */
462 if( nIcons
> iconDirCount
- nIconIndex
)
463 nIcons
= iconDirCount
- nIconIndex
;
465 /* starting from specified index */
466 xresent
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(icongroupresdir
+1) + nIconIndex
;
468 for (i
=0; i
< nIcons
; i
++,xresent
++)
470 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
472 /* go down this resource entry, name */
473 resdir
= (PIMAGE_RESOURCE_DIRECTORY
)((DWORD
)rootresdir
+(xresent
->u2
.s3
.OffsetToDirectory
));
475 /* default language (0) */
476 resdir
= find_entry_default(resdir
,rootresdir
);
477 igdataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)resdir
;
479 /* lookup address in mapped image for virtual address */
482 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
484 if (igdataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
486 if (igdataent
->OffsetToData
+igdataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
489 if (igdataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
+igdataent
->Size
> fsizel
) {
490 FIXME("overflow in PE lookup (%s has len %ld, have offset %ld), short file?\n", debugstr_w(lpszExeFileName
), fsizel
,
491 igdataent
->OffsetToData
- pe_sections
[j
].VirtualAddress
+ pe_sections
[j
].PointerToRawData
+ igdataent
->Size
);
492 goto end
; /* failure */
494 igdata
= peimage
+(igdataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
499 FIXME("no matching real address for icongroup!\n");
500 goto end
; /* failure */
502 RetPtr
[i
] = (HICON
)LookupIconIdFromDirectoryEx(igdata
, TRUE
, cxDesired
, cyDesired
, flags
);
506 *pIconId
= LOWORD(*RetPtr
);
508 if (!(iconresdir
=find_entry_by_id(rootresdir
,LOWORD(RT_ICONW
),rootresdir
)))
510 WARN("No Iconresourcedirectory!\n");
511 goto end
; /* failure */
514 for (i
=0; i
<nIcons
; i
++)
516 const IMAGE_RESOURCE_DIRECTORY
*xresdir
;
517 xresdir
= find_entry_by_id(iconresdir
,LOWORD(RetPtr
[i
]),rootresdir
);
518 xresdir
= find_entry_default(xresdir
,rootresdir
);
519 idataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)xresdir
;
522 /* map virtual to address in image */
523 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
525 if (idataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
527 if (idataent
->OffsetToData
+idataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
529 idata
= peimage
+(idataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
533 WARN("no matching real address found for icondata!\n");
537 RetPtr
[i
] = (HICON
) CreateIconFromResourceEx(idata
,idataent
->Size
,TRUE
,0x00030000, cxDesired
, cyDesired
, flags
);
539 ret
= i
; /* return number of retrieved icons */
540 } /* if(sig == IMAGE_NT_SIGNATURE) */
543 UnmapViewOfFile(peimage
); /* success */
547 /***********************************************************************
548 * PrivateExtractIconsW [USER32.@]
551 * nIndex = 1: a small and a large icon are extracted.
552 * the higher word of sizeXY contains the size of the small icon, the lower
553 * word the size of the big icon. phicon points to HICON[2].
556 * 1) should also support 16 bit EXE + DLLs, cursor and animated cursor as well
558 * 2) should return according to MSDN
559 * phicons == NULL : the number of icons in file or 0 on error
560 * phicons != NULL : the number of icons extracted or 0xFFFFFFFF on error
561 * does return in Win2000
562 * when file valid the number of icons or 0 on any error
563 * when file invalid and phicon == NULL returns 0
564 * when file invalid and phicon != NULL returns 0xFFFFFFFF
566 * *pIconID is always set to 0 when file invalid
567 * *pIconID is always set to 0xFFFFFFFF for valid icon and cursor files
568 * *pIconID is set to actual identifier for valid dll/exes or -1 on error
571 UINT WINAPI
PrivateExtractIconsW (
576 HICON
* phicon
, /* [out] pointer to array of HICON handles */
577 UINT
* pIconId
, /* [out] pointer to returned icon identifier which fits best */
578 UINT nIcons
, /* [in] number of icons to retrieve */
579 UINT flags
) /* [in] LR_* flags used by LoadImage */
582 TRACE("%s %d %dx%d %p %p %d 0x%08x\n",
583 debugstr_w(lpwstrFile
), nIndex
, sizeX
, sizeY
, phicon
, pIconId
, nIcons
, flags
);
585 if (pIconId
) /* Invalidate icon identifier on entry */
586 *pIconId
= 0xFFFFFFFF;
589 return ICO_ExtractIconExW(lpwstrFile
, NULL
, nIndex
, 0, sizeX
& 0xffff, sizeY
& 0xffff, pIconId
, flags
);
591 if ((nIcons
== 2) && HIWORD(sizeX
) && HIWORD(sizeY
))
593 ret
= ICO_ExtractIconExW(lpwstrFile
, phicon
, nIndex
, 1, sizeX
& 0xffff, sizeY
& 0xffff, pIconId
, flags
);
594 if (!SUCCEEDED(ret
)) return ret
;
595 ret
= ICO_ExtractIconExW(lpwstrFile
, phicon
+1, nIndex
, 1, (sizeX
>>16) & 0xffff, (sizeY
>>16) & 0xffff, pIconId
, flags
);
597 ret
= ICO_ExtractIconExW(lpwstrFile
, phicon
, nIndex
, nIcons
, sizeX
& 0xffff, sizeY
& 0xffff, pIconId
, flags
);
601 /***********************************************************************
602 * PrivateExtractIconsA [USER32.@]
605 UINT WINAPI
PrivateExtractIconsA (
611 UINT
* piconid
, /* [out] pointer to returned icon identifier which fits best */
612 UINT nIcons
, /* [in] number of icons to retrieve */
613 UINT flags
) /* [in] LR_* flags used by LoadImage */
616 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpstrFile
, -1, NULL
, 0);
617 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
619 MultiByteToWideChar(CP_ACP
, 0, lpstrFile
, -1, lpwstrFile
, len
);
620 ret
= PrivateExtractIconsW(lpwstrFile
, nIndex
, sizeX
, sizeY
, phicon
, piconid
, nIcons
, flags
);
622 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
626 /***********************************************************************
627 * PrivateExtractIconExW [USER32.@]
629 * if nIcons = -1 it returns the number of icons in any case !!!
631 HRESULT WINAPI
PrivateExtractIconExW (
638 DWORD cyicon
, cysmicon
, cxicon
, cxsmicon
;
641 TRACE("%s 0x%08lx %p %p 0x%08x\n",
642 debugstr_w(lpwstrFile
),nIndex
,phIconLarge
, phIconSmall
, nIcons
);
644 if (nIndex
== 1 && phIconSmall
&& phIconLarge
)
647 cxicon
= GetSystemMetrics(SM_CXICON
);
648 cyicon
= GetSystemMetrics(SM_CYICON
);
649 cxsmicon
= GetSystemMetrics(SM_CXSMICON
);
650 cysmicon
= GetSystemMetrics(SM_CYSMICON
);
652 ret
= PrivateExtractIconsW ( lpwstrFile
, nIndex
, cxicon
| (cxsmicon
<<16), cyicon
| (cysmicon
<<16),
653 (HICON
*) &hIcon
, 0, 2, 0 );
654 *phIconLarge
= hIcon
[0];
655 *phIconSmall
= hIcon
[1];
663 /* extract n small icons */
664 cxsmicon
= GetSystemMetrics(SM_CXSMICON
);
665 cysmicon
= GetSystemMetrics(SM_CYSMICON
);
666 ret
= PrivateExtractIconsW ( lpwstrFile
, nIndex
, cxsmicon
, cysmicon
, phIconSmall
, 0, nIcons
, 0 );
670 /* extract n large icons */
671 cxicon
= GetSystemMetrics(SM_CXICON
);
672 cyicon
= GetSystemMetrics(SM_CYICON
);
673 ret
= PrivateExtractIconsW ( lpwstrFile
, nIndex
, cxicon
, cyicon
, phIconLarge
, 0, nIcons
, 0 );
678 /* get the number of icons */
679 return PrivateExtractIconsW ( lpwstrFile
, 0, 0, 0, 0, 0, 0, 0 );
682 /***********************************************************************
683 * PrivateExtractIconExA [USER32.@]
685 HRESULT WINAPI
PrivateExtractIconExA (
693 INT len
= MultiByteToWideChar( CP_ACP
, 0, lpstrFile
, -1, NULL
, 0 );
694 LPWSTR lpwstrFile
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
696 TRACE("%s 0x%08lx %p %p 0x%08x\n", lpstrFile
, nIndex
, phIconLarge
, phIconSmall
, nIcons
);
698 MultiByteToWideChar( CP_ACP
, 0, lpstrFile
, -1, lpwstrFile
, len
);
699 ret
= PrivateExtractIconExW(lpwstrFile
,nIndex
,phIconLarge
, phIconSmall
, nIcons
);
700 HeapFree(GetProcessHeap(), 0, lpwstrFile
);