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
25 /* Remove this once w32api conversion is done */
28 #define _WIN32_IE 0x600
29 #define _WIN32_WINNT 0x501
31 #define __need_offsetof
32 #endif /* __USE_W32API */
36 #include <stdlib.h> /* abs() */
38 #include <sys/types.h>
43 //#define NONAMELESSUNION
44 #define NONAMELESSSTRUCT
51 #include "wine/unicode.h"
52 #include "wine/debug.h"
54 /* Start of Hack section */
55 typedef unsigned short UINT16
;
57 WINE_DEFAULT_DEBUG_CHANNEL(icon
);
63 BYTE bWidth
; /* Width, in pixels, of the image */
64 BYTE bHeight
; /* Height, in pixels, of the image */
65 BYTE bColorCount
; /* Number of colors in image (0 if >=8bpp) */
66 BYTE bReserved
; /* Reserved ( must be 0) */
67 WORD wPlanes
; /* Color Planes */
68 WORD wBitCount
; /* Bits per pixel */
69 DWORD dwBytesInRes
; /* How many bytes in this resource? */
70 DWORD dwImageOffset
; /* Where in the file is this image? */
71 } icoICONDIRENTRY
, *LPicoICONDIRENTRY
;
75 WORD idReserved
; /* Reserved (must be 0) */
76 WORD idType
; /* Resource Type (RES_ICON or RES_CURSOR) */
77 WORD idCount
; /* How many images */
78 icoICONDIRENTRY idEntries
[1]; /* An entry for each image (idCount of 'em) */
79 } icoICONDIR
, *LPicoICONDIR
;
83 static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry
)
85 TRACE("width = 0x%08x height = 0x%08x\n", entry
->bWidth
, entry
->bHeight
);
86 TRACE("colors = 0x%08x planes = 0x%08x\n", entry
->bColorCount
, entry
->wPlanes
);
87 TRACE("bitcount = 0x%08x bytesinres = 0x%08lx offset = 0x%08lx\n",
88 entry
->wBitCount
, entry
->dwBytesInRes
, entry
->dwImageOffset
);
90 static void dumpIcoDir ( LPicoICONDIR entry
)
92 TRACE("type = 0x%08x count = 0x%08x\n", entry
->idType
, entry
->idCount
);
96 /**********************************************************************
99 * Find an entry by id in a resource directory
100 * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
102 static const IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY
*dir
,
103 WORD id
, const void *root
)
105 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
108 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
109 min
= dir
->NumberOfNamedEntries
;
110 max
= min
+ dir
->NumberOfIdEntries
- 1;
113 pos
= (min
+ max
) / 2;
114 if (entry
[pos
].Id
== id
)
115 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
[pos
].OffsetToDirectory
);
116 if (entry
[pos
].Id
> id
) max
= pos
- 1;
122 /**********************************************************************
125 * Find a default entry in a resource directory
126 * Copied from loader/pe_resource.c (FIXME: should use exported resource functions)
128 static const IMAGE_RESOURCE_DIRECTORY
*find_entry_default( const IMAGE_RESOURCE_DIRECTORY
*dir
,
131 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
132 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
133 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
->OffsetToDirectory
);
136 /*************************************************************************
137 * USER32_GetResourceTable
139 static DWORD
USER32_GetResourceTable(LPBYTE peimage
,DWORD pesize
,LPBYTE
*retptr
)
141 IMAGE_DOS_HEADER
* mz_header
;
143 TRACE("%p %p\n", peimage
, retptr
);
147 mz_header
= (IMAGE_DOS_HEADER
*) peimage
;
149 if (mz_header
->e_magic
!= IMAGE_DOS_SIGNATURE
)
151 if (mz_header
->e_cblp
== 1) /* .ICO file ? */
153 *retptr
= (LPBYTE
)-1; /* ICONHEADER.idType, must be 1 */
157 return 0; /* failed */
159 if (mz_header
->e_lfanew
>= pesize
) {
160 return 0; /* failed, happens with PKZIP DOS Exes for instance. */
162 if (*((DWORD
*)(peimage
+ mz_header
->e_lfanew
)) == IMAGE_NT_SIGNATURE
)
163 return IMAGE_NT_SIGNATURE
;
165 if (*((WORD
*)(peimage
+ mz_header
->e_lfanew
)) == IMAGE_OS2_SIGNATURE
)
167 IMAGE_OS2_HEADER
* ne_header
;
169 ne_header
= (IMAGE_OS2_HEADER
*)(peimage
+ mz_header
->e_lfanew
);
171 if (ne_header
->ne_magic
!= IMAGE_OS2_SIGNATURE
)
174 if( (ne_header
->ne_restab
- ne_header
->ne_rsrctab
) <= sizeof(NE_TYPEINFO
) )
175 *retptr
= (LPBYTE
)-1;
177 *retptr
= peimage
+ mz_header
->e_lfanew
+ ne_header
->ne_rsrctab
;
179 return IMAGE_OS2_SIGNATURE
;
182 return 0; /* failed */
185 /*************************************************************************
186 * USER32_LoadResource
188 static BYTE
* USER32_LoadResource( LPBYTE peimage
, NE_NAMEINFO
* pNInfo
, WORD sizeShift
, ULONG
*uSize
)
190 TRACE("%p %p 0x%08x\n", peimage
, pNInfo
, sizeShift
);
192 *uSize
= (DWORD
)pNInfo
->length
<< sizeShift
;
193 return peimage
+ ((DWORD
)pNInfo
->offset
<< sizeShift
);
196 /*************************************************************************
199 static BYTE
* ICO_LoadIcon( LPBYTE peimage
, LPicoICONDIRENTRY lpiIDE
, ULONG
*uSize
)
201 TRACE("%p %p\n", peimage
, lpiIDE
);
203 *uSize
= lpiIDE
->dwBytesInRes
;
204 return peimage
+ lpiIDE
->dwImageOffset
;
207 /*************************************************************************
208 * ICO_GetIconDirectory
210 * Reads .ico file and build phony ICONDIR struct
211 * see http://www.microsoft.com/win32dev/ui/icons.htm
213 #define HEADER_SIZE (sizeof(CURSORICONDIR) - sizeof (CURSORICONDIRENTRY))
214 #define HEADER_SIZE_FILE (sizeof(icoICONDIR) - sizeof (icoICONDIRENTRY))
216 static BYTE
* ICO_GetIconDirectory( LPBYTE peimage
, LPicoICONDIR
* lplpiID
, ULONG
*uSize
)
218 CURSORICONDIR
* lpcid
; /* icon resource in resource-dir format */
219 CURSORICONDIR
* lpID
; /* icon resource in resource format */
222 TRACE("%p %p\n", peimage
, lplpiID
);
224 lpcid
= (CURSORICONDIR
*)peimage
;
226 if( lpcid
->idReserved
|| (lpcid
->idType
!= 1) || (!lpcid
->idCount
) )
229 /* allocate the phony ICONDIR structure */
230 *uSize
= lpcid
->idCount
* sizeof(CURSORICONDIRENTRY
) + HEADER_SIZE
;
231 if( (lpID
= (CURSORICONDIR
*)HeapAlloc(GetProcessHeap(),0, *uSize
) ))
233 /* copy the header */
234 lpID
->idReserved
= lpcid
->idReserved
;
235 lpID
->idType
= lpcid
->idType
;
236 lpID
->idCount
= lpcid
->idCount
;
238 /* copy the entries */
239 for( i
=0; i
< lpcid
->idCount
; i
++ )
241 memcpy((void*)&(lpID
->idEntries
[i
]),(void*)&(lpcid
->idEntries
[i
]), sizeof(CURSORICONDIRENTRY
) - 2);
242 lpID
->idEntries
[i
].wResId
= i
;
245 *lplpiID
= (LPicoICONDIR
)peimage
;
251 /*************************************************************************
252 * ICO_ExtractIconExW [internal]
255 * nIcons = 0: returns number of Icons in file
260 * success: number of icons in file (nIcons = 0) or nr of icons retrieved
262 static UINT
ICO_ExtractIconExW(
263 LPCWSTR lpszExeFileName
,
273 UINT cx1
, cx2
, cy1
, cy2
;
277 UINT16 iconDirCount
= 0; //,iconCount = 0;
282 WCHAR szExePath
[MAX_PATH
];
283 DWORD dwSearchReturn
;
285 TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName
), nIconIndex
, nIcons
, pIconId
, flags
);
287 dwSearchReturn
= SearchPathW(NULL
, lpszExeFileName
, NULL
, sizeof(szExePath
) / sizeof(szExePath
[0]), szExePath
, NULL
);
288 if ((dwSearchReturn
== 0) || (dwSearchReturn
> sizeof(szExePath
) / sizeof(szExePath
[0])))
290 WARN("File %s not found or path too long\n", debugstr_w(lpszExeFileName
));
294 hFile
= CreateFileW(szExePath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
295 if (hFile
== INVALID_HANDLE_VALUE
) return ret
;
296 fsizel
= GetFileSize(hFile
,&fsizeh
);
299 fmapping
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
303 WARN("CreateFileMapping error %ld\n", GetLastError() );
307 if (!(peimage
= MapViewOfFile(fmapping
, FILE_MAP_READ
, 0, 0, 0)))
309 WARN("MapViewOfFile error %ld\n", GetLastError() );
310 CloseHandle(fmapping
);
313 CloseHandle(fmapping
);
315 cx1
= LOWORD(cxDesired
);
316 cx2
= HIWORD(cxDesired
) ? HIWORD(cxDesired
) : cx1
;
317 cy1
= LOWORD(cyDesired
);
318 cy2
= HIWORD(cyDesired
) ? HIWORD(cyDesired
) : cy1
;
320 if (pIconId
) /* Invalidate first icon identifier */
321 *pIconId
= 0xFFFFFFFF;
323 if (!pIconId
) /* if no icon identifier array present use the icon handle array as intermediate storage */
324 pIconId
= (UINT
*)RetPtr
;
326 sig
= USER32_GetResourceTable(peimage
, fsizel
, &pData
);
328 /* ico file or NE exe/dll*/
330 if (sig
==IMAGE_OS2_SIGNATURE
|| sig
==1) /* .ICO file */
333 NE_TYPEINFO
*pTInfo
= (NE_TYPEINFO
*)(pData
+ 2);
334 NE_NAMEINFO
*pIconStorage
= NULL
;
335 NE_NAMEINFO
*pIconDir
= NULL
;
336 LPicoICONDIR lpiID
= NULL
;
338 TRACE("-- OS2/icon Signature (0x%08lx)\n", sig
);
340 if (pData
== (BYTE
*)-1)
342 pCIDir
= ICO_GetIconDirectory(peimage
, &lpiID
, &uSize
); /* check for .ICO file */
345 iconDirCount
= 1; iconCount
= lpiID
->idCount
;
346 TRACE("-- icon found %p 0x%08lx 0x%08x 0x%08x\n", pCIDir
, uSize
, iconDirCount
, iconCount
);
349 else while (pTInfo
->type_id
&& !(pIconStorage
&& pIconDir
))
351 if (pTInfo
->type_id
== NE_RSCTYPE_GROUP_ICON
) /* find icon directory and icon repository */
353 iconDirCount
= pTInfo
->count
;
354 pIconDir
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
355 TRACE("\tfound directory - %i icon families\n", iconDirCount
);
357 if (pTInfo
->type_id
== NE_RSCTYPE_ICON
)
359 iconCount
= pTInfo
->count
;
360 pIconStorage
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
361 TRACE("\ttotal icons - %i\n", iconCount
);
363 pTInfo
= (NE_TYPEINFO
*)((char*)(pTInfo
+1)+pTInfo
->count
*sizeof(NE_NAMEINFO
));
366 if ((pIconStorage
&& pIconDir
) || lpiID
) /* load resources and create icons */
371 if (lpiID
&& pCIDir
) /* *.ico file, deallocate heap pointer*/
372 HeapFree(GetProcessHeap(), 0, pCIDir
);
374 else if (nIconIndex
< iconDirCount
)
377 if (nIcons
> iconDirCount
- nIconIndex
)
378 nIcons
= iconDirCount
- nIconIndex
;
380 for (i
= 0; i
< nIcons
; i
++)
382 /* .ICO files have only one icon directory */
383 if (lpiID
== NULL
) /* not *.ico */
384 pCIDir
= USER32_LoadResource(peimage
, pIconDir
+ i
+ nIconIndex
, *(WORD
*)pData
, &uSize
);
385 pIconId
[i
] = LookupIconIdFromDirectoryEx(pCIDir
, TRUE
, (i
& 1) ? cx2
: cx1
, (i
& 1) ? cy2
: cy1
, flags
);
387 if (lpiID
&& pCIDir
) /* *.ico file, deallocate heap pointer*/
388 HeapFree(GetProcessHeap(), 0, pCIDir
);
390 for (icon
= 0; icon
< nIcons
; icon
++)
394 pCIDir
= ICO_LoadIcon(peimage
, lpiID
->idEntries
+ (int)pIconId
[icon
], &uSize
);
396 for (i
= 0; i
< iconCount
; i
++)
397 if (pIconStorage
[i
].id
== ((int)pIconId
[icon
] | 0x8000) )
398 pCIDir
= USER32_LoadResource(peimage
, pIconStorage
+ i
, *(WORD
*)pData
, &uSize
);
401 RetPtr
[icon
] = (HICON
)CreateIconFromResourceEx(pCIDir
, uSize
, TRUE
, 0x00030000,
402 (icon
& 1) ? cx2
: cx1
, (icon
& 1) ? cy2
: cy1
, flags
);
406 ret
= icon
; /* return number of retrieved icons */
413 else if( sig
== IMAGE_NT_SIGNATURE
)
415 if( sig
== IMAGE_NT_SIGNATURE
)
418 PIMAGE_DOS_HEADER dheader
;
419 PIMAGE_NT_HEADERS pe_header
;
420 PIMAGE_SECTION_HEADER pe_sections
;
421 const IMAGE_RESOURCE_DIRECTORY
*rootresdir
,*iconresdir
,*icongroupresdir
;
422 const IMAGE_RESOURCE_DATA_ENTRY
*idataent
,*igdataent
;
423 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*xresent
;
426 dheader
= (PIMAGE_DOS_HEADER
)peimage
;
427 pe_header
= (PIMAGE_NT_HEADERS
)(peimage
+dheader
->e_lfanew
); /* it is a pe header, USER32_GetResourceTable checked that */
428 pe_sections
= (PIMAGE_SECTION_HEADER
)(((char*)pe_header
) + sizeof(DWORD
) + sizeof(IMAGE_FILE_HEADER
)
429 + pe_header
->FileHeader
.SizeOfOptionalHeader
);
432 /* search for the root resource directory */
433 for (i
=0;i
<pe_header
->FileHeader
.NumberOfSections
;i
++)
435 if (pe_sections
[i
].Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
437 if (fsizel
< pe_sections
[i
].PointerToRawData
+pe_sections
[i
].SizeOfRawData
) {
438 FIXME("File %s too short (section is at %ld bytes, real size is %ld)\n",
439 debugstr_w(lpszExeFileName
),
440 pe_sections
[i
].PointerToRawData
+pe_sections
[i
].SizeOfRawData
,
445 /* FIXME: doesn't work when the resources are not in a separate section */
446 if (pe_sections
[i
].VirtualAddress
== pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
)
448 rootresdir
= (PIMAGE_RESOURCE_DIRECTORY
)(peimage
+pe_sections
[i
].PointerToRawData
);
455 WARN("haven't found section for resource directory.\n");
456 goto end
; /* failure */
459 /* search for the group icon directory */
460 if (!(icongroupresdir
= find_entry_by_id(rootresdir
, LOWORD(RT_GROUP_ICON
), rootresdir
)))
462 WARN("No Icongroupresourcedirectory!\n");
463 goto end
; /* failure */
465 iconDirCount
= icongroupresdir
->NumberOfNamedEntries
+ icongroupresdir
->NumberOfIdEntries
;
467 /* only number of icons requested */
471 goto end
; /* success */
476 /* search resource id */
478 int iId
= abs(nIconIndex
);
479 PIMAGE_RESOURCE_DIRECTORY_ENTRY xprdeTmp
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(icongroupresdir
+1);
481 while(n
<iconDirCount
&& xprdeTmp
)
483 if(xprdeTmp
->Id
== iId
)
493 WARN("resource id %d not found\n", iId
);
494 goto end
; /* failure */
499 /* check nIconIndex to be in range */
500 if (nIconIndex
>= iconDirCount
)
502 WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex
,iconDirCount
);
503 goto end
; /* failure */
507 /* assure we don't get too much */
508 if( nIcons
/ 2 > iconDirCount
- nIconIndex
)
509 nIcons
= 2 * (iconDirCount
- nIconIndex
);
511 /* starting from specified index */
512 xresent
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(icongroupresdir
+1) + nIconIndex
;
514 for (i
=0; i
< nIcons
; i
++)
516 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
518 /* go down this resource entry, name */
519 resdir
= (PIMAGE_RESOURCE_DIRECTORY
)((DWORD
)rootresdir
+(xresent
->OffsetToDirectory
));
521 /* default language (0) */
522 resdir
= find_entry_default(resdir
,rootresdir
);
523 igdataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)resdir
;
525 /* lookup address in mapped image for virtual address */
528 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
530 if (igdataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
532 if (igdataent
->OffsetToData
+igdataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
535 if (igdataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
+igdataent
->Size
> fsizel
) {
536 FIXME("overflow in PE lookup (%s has len %ld, have offset %ld), short file?\n", debugstr_w(lpszExeFileName
), fsizel
,
537 igdataent
->OffsetToData
- pe_sections
[j
].VirtualAddress
+ pe_sections
[j
].PointerToRawData
+ igdataent
->Size
);
538 goto end
; /* failure */
540 igdata
= peimage
+(igdataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
545 FIXME("no matching real address for icongroup!\n");
546 goto end
; /* failure */
548 pIconId
[i
] = LookupIconIdFromDirectoryEx(igdata
, TRUE
, (i
& 1) ? cx2
: cx1
, (i
& 1) ? cy2
: cy1
, flags
);
549 if (i
& 1) xresent
++;
552 if (!(iconresdir
=find_entry_by_id(rootresdir
,LOWORD(RT_ICON
),rootresdir
)))
554 WARN("No Iconresourcedirectory!\n");
555 goto end
; /* failure */
558 for (i
=0; i
<nIcons
; i
++)
560 const IMAGE_RESOURCE_DIRECTORY
*xresdir
;
561 xresdir
= find_entry_by_id(iconresdir
, LOWORD(pIconId
[i
]), rootresdir
);
562 xresdir
= find_entry_default(xresdir
, rootresdir
);
563 idataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)xresdir
;
566 /* map virtual to address in image */
567 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
569 if (idataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
571 if (idataent
->OffsetToData
+idataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
573 idata
= peimage
+(idataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
577 WARN("no matching real address found for icondata!\n");
581 RetPtr
[i
] = (HICON
) CreateIconFromResourceEx(idata
,idataent
->Size
,TRUE
,0x00030000,
582 (i
& 1) ? cx2
: cx1
, (i
& 1) ? cy2
: cy1
, flags
);
584 ret
= i
; /* return number of retrieved icons */
585 } /* if(sig == IMAGE_NT_SIGNATURE) */
588 UnmapViewOfFile(peimage
); /* success */
592 /***********************************************************************
593 * PrivateExtractIconsW [USER32.@]
597 * If HIWORD(sizeX) && HIWORD(sizeY) 2 * ((nIcons + 1) MOD 2) icons are
598 * returned, with the LOWORD size icon first and the HIWORD size icon
600 * Also the Windows equivalent does extract icons in a strange way if
601 * nIndex is negative. Our implementation treats a negative nIndex as
602 * looking for that resource identifier for the first icon to retrieve.
605 * should also support 16 bit EXE + DLLs, cursor and animated cursor as
606 * well as bitmap files.
609 UINT WINAPI
PrivateExtractIconsW (
614 HICON
* phicon
, /* [out] pointer to array of nIcons HICON handles */
615 UINT
* pIconId
, /* [out] pointer to array of nIcons icon identifiers or NULL */
616 UINT nIcons
, /* [in] number of icons to retrieve */
617 UINT flags
) /* [in] LR_* flags used by LoadImage */
619 TRACE("%s %d %dx%d %p %p %d 0x%08x\n",
620 debugstr_w(lpwstrFile
), nIndex
, sizeX
, sizeY
, phicon
, pIconId
, nIcons
, flags
);
622 if ((nIcons
& 1) && HIWORD(sizeX
) && HIWORD(sizeY
))
624 WARN("Uneven number %d of icons requested for small and large icons!", nIcons
);
626 return ICO_ExtractIconExW(lpwstrFile
, phicon
, nIndex
, nIcons
, sizeX
, sizeY
, pIconId
, flags
);
629 /***********************************************************************
630 * PrivateExtractIconsA [USER32.@]
634 UINT WINAPI
PrivateExtractIconsA (
639 HICON
* phicon
, /* [out] pointer to array of nIcons HICON handles */
640 UINT
* piconid
, /* [out] pointer to array of nIcons icon identifiers or NULL */
641 UINT nIcons
, /* [in] number of icons to retrieve */
642 UINT flags
) /* [in] LR_* flags used by LoadImage */
645 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpstrFile
, -1, NULL
, 0);
646 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
648 MultiByteToWideChar(CP_ACP
, 0, lpstrFile
, -1, lpwstrFile
, len
);
649 ret
= PrivateExtractIconsW(lpwstrFile
, nIndex
, sizeX
, sizeY
, phicon
, piconid
, nIcons
, flags
);
651 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
655 /***********************************************************************
656 * PrivateExtractIconExW [USER32.@]
659 * if nIndex == -1 it returns the number of icons in any case !!!
661 UINT WINAPI
PrivateExtractIconExW (
668 DWORD cyicon
, cysmicon
, cxicon
, cxsmicon
;
671 TRACE("%s %d %p %p %d\n",
672 debugstr_w(lpwstrFile
),nIndex
,phIconLarge
, phIconSmall
, nIcons
);
675 /* get the number of icons */
676 return ICO_ExtractIconExW(lpwstrFile
, NULL
, 0, 0, 0, 0, NULL
, LR_DEFAULTCOLOR
);
678 if (nIcons
== 1 && phIconSmall
&& phIconLarge
)
681 cxicon
= GetSystemMetrics(SM_CXICON
);
682 cyicon
= GetSystemMetrics(SM_CYICON
);
683 cxsmicon
= GetSystemMetrics(SM_CXSMICON
);
684 cysmicon
= GetSystemMetrics(SM_CYSMICON
);
686 ret
= ICO_ExtractIconExW(lpwstrFile
, (HICON
*) &hIcon
, nIndex
, 2, cxicon
| (cxsmicon
<<16),
687 cyicon
| (cysmicon
<<16), NULL
, LR_DEFAULTCOLOR
);
688 *phIconLarge
= (1 <= ret
? hIcon
[0] : NULL
);
689 *phIconSmall
= (2 <= ret
? hIcon
[1] : NULL
);
695 /* extract n small icons */
696 cxsmicon
= GetSystemMetrics(SM_CXSMICON
);
697 cysmicon
= GetSystemMetrics(SM_CYSMICON
);
698 ret
= ICO_ExtractIconExW(lpwstrFile
, phIconSmall
, nIndex
, nIcons
, cxsmicon
,
699 cysmicon
, NULL
, LR_DEFAULTCOLOR
);
703 /* extract n large icons */
704 cxicon
= GetSystemMetrics(SM_CXICON
);
705 cyicon
= GetSystemMetrics(SM_CYICON
);
706 ret
= ICO_ExtractIconExW(lpwstrFile
, phIconLarge
, nIndex
, nIcons
, cxicon
,
707 cyicon
, NULL
, LR_DEFAULTCOLOR
);
712 /***********************************************************************
713 * PrivateExtractIconExA [USER32.@]
716 UINT WINAPI
PrivateExtractIconExA (
724 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpstrFile
, -1, NULL
, 0);
725 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
727 TRACE("%s %d %p %p %d\n", lpstrFile
, nIndex
, phIconLarge
, phIconSmall
, nIcons
);
729 MultiByteToWideChar(CP_ACP
, 0, lpstrFile
, -1, lpwstrFile
, len
);
730 ret
= PrivateExtractIconExW(lpwstrFile
, nIndex
, phIconLarge
, phIconSmall
, nIcons
);
731 HeapFree(GetProcessHeap(), 0, lpwstrFile
);