2 * shell icon cache (SIC)
6 #include "wine/winuser16.h"
7 #include "wine/winbase16.h"
9 #include "cursoricon.h"
13 #include "sysmetrics.h"
14 #include "winversion.h"
20 #include "shell32_main.h"
22 DEFAULT_DEBUG_CHANNEL(shell
)
28 BYTE bWidth
; /* Width, in pixels, of the image */
29 BYTE bHeight
; /* Height, in pixels, of the image */
30 BYTE bColorCount
; /* Number of colors in image (0 if >=8bpp) */
31 BYTE bReserved
; /* Reserved ( must be 0) */
32 WORD wPlanes
; /* Color Planes */
33 WORD wBitCount
; /* Bits per pixel */
34 DWORD dwBytesInRes
; /* How many bytes in this resource? */
35 DWORD dwImageOffset
; /* Where in the file is this image? */
36 } icoICONDIRENTRY
, *LPicoICONDIRENTRY
;
40 WORD idReserved
; /* Reserved (must be 0) */
41 WORD idType
; /* Resource Type (RES_ICON or RES_CURSOR) */
42 WORD idCount
; /* How many images */
43 icoICONDIRENTRY idEntries
[1]; /* An entry for each image (idCount of 'em) */
44 } icoICONDIR
, *LPicoICONDIR
;
49 static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry
)
51 TRACE (shell
, "width = 0x%08x height = 0x%08x\n", entry
->bWidth
, entry
->bHeight
);
52 TRACE (shell
, "colors = 0x%08x planes = 0x%08x\n", entry
->bColorCount
, entry
->wPlanes
);
53 TRACE (shell
, "bitcount = 0x%08x bytesinres = 0x%08lx offset = 0x%08lx\n",
54 entry
->wBitCount
, entry
->dwBytesInRes
, entry
->dwImageOffset
);
56 static void dumpIcoDir ( LPicoICONDIR entry
)
58 TRACE (shell
, "type = 0x%08x count = 0x%08x\n", entry
->idType
, entry
->idCount
);
61 /*************************************************************************
62 * SHELL_GetResourceTable
64 static DWORD
SHELL_GetResourceTable(HFILE hFile
, LPBYTE
*retptr
)
65 { IMAGE_DOS_HEADER mz_header
;
69 TRACE(shell
,"0x%08x %p\n", hFile
, retptr
);
72 _llseek( hFile
, 0, SEEK_SET
);
73 if ((_lread(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) || (mz_header
.e_magic
!= IMAGE_DOS_SIGNATURE
))
74 { if (mz_header
.e_cblp
== 1) /* .ICO file ? */
75 { *retptr
= (LPBYTE
)-1; /* ICONHEADER.idType, must be 1 */
79 return 0; /* failed */
81 _llseek( hFile
, mz_header
.e_lfanew
, SEEK_SET
);
83 if (_lread( hFile
, magic
, sizeof(magic
) ) != sizeof(magic
))
86 _llseek( hFile
, mz_header
.e_lfanew
, SEEK_SET
);
88 if (*(DWORD
*)magic
== IMAGE_NT_SIGNATURE
)
89 return IMAGE_NT_SIGNATURE
;
91 if (*(WORD
*)magic
== IMAGE_OS2_SIGNATURE
)
92 { IMAGE_OS2_HEADER ne_header
;
93 LPBYTE pTypeInfo
= (LPBYTE
)-1;
95 if (_lread(hFile
,&ne_header
,sizeof(ne_header
))!=sizeof(ne_header
))
98 if (ne_header
.ne_magic
!= IMAGE_OS2_SIGNATURE
)
101 size
= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
103 if( size
> sizeof(NE_TYPEINFO
) )
104 { pTypeInfo
= (BYTE
*)HeapAlloc( GetProcessHeap(), 0, size
);
106 { _llseek(hFile
, mz_header
.e_lfanew
+ne_header
.resource_tab_offset
, SEEK_SET
);
107 if( _lread( hFile
, (char*)pTypeInfo
, size
) != size
)
108 { HeapFree( GetProcessHeap(), 0, pTypeInfo
);
114 return IMAGE_OS2_SIGNATURE
;
116 return 0; /* failed */
118 /*************************************************************************
121 static BYTE
* SHELL_LoadResource( HFILE hFile
, NE_NAMEINFO
* pNInfo
, WORD sizeShift
, ULONG
*uSize
)
124 TRACE(shell
,"0x%08x %p 0x%08x\n", hFile
, pNInfo
, sizeShift
);
126 *uSize
= (DWORD
)pNInfo
->length
<< sizeShift
;
127 if( (ptr
= (BYTE
*)HeapAlloc(GetProcessHeap(),0, *uSize
) ))
128 { _llseek( hFile
, (DWORD
)pNInfo
->offset
<< sizeShift
, SEEK_SET
);
129 _lread( hFile
, (char*)ptr
, pNInfo
->length
<< sizeShift
);
135 /*************************************************************************
138 static BYTE
* ICO_LoadIcon( HFILE hFile
, LPicoICONDIRENTRY lpiIDE
, ULONG
*uSize
)
141 TRACE(shell
,"0x%08x %p\n", hFile
, lpiIDE
);
143 *uSize
= lpiIDE
->dwBytesInRes
;
144 if( (ptr
= (BYTE
*)HeapAlloc(GetProcessHeap(),0, *uSize
)) )
145 { _llseek( hFile
, lpiIDE
->dwImageOffset
, SEEK_SET
);
146 _lread( hFile
, (char*)ptr
, lpiIDE
->dwBytesInRes
);
153 /*************************************************************************
154 * ICO_GetIconDirectory
156 * Reads .ico file and build phony ICONDIR struct
157 * see http://www.microsoft.com/win32dev/ui/icons.htm
159 #define HEADER_SIZE (sizeof(CURSORICONDIR) - sizeof (CURSORICONDIRENTRY))
160 #define HEADER_SIZE_FILE (sizeof(icoICONDIR) - sizeof (icoICONDIRENTRY))
162 static BYTE
* ICO_GetIconDirectory( HFILE hFile
, LPicoICONDIR
* lplpiID
, ULONG
*uSize
)
163 { CURSORICONDIR lpcid
; /* icon resource in resource-dir format */
164 LPicoICONDIR lpiID
; /* icon resource in file format */
167 TRACE(shell
,"0x%08x %p\n", hFile
, lplpiID
);
169 _llseek( hFile
, 0, SEEK_SET
);
170 if( _lread(hFile
,(char*)&lpcid
, HEADER_SIZE_FILE
) != HEADER_SIZE_FILE
)
173 if( lpcid
.idReserved
|| (lpcid
.idType
!= 1) || (!lpcid
.idCount
) )
176 i
= lpcid
.idCount
* sizeof(icoICONDIRENTRY
);
177 lpiID
= (LPicoICONDIR
)HeapAlloc( GetProcessHeap(), 0, HEADER_SIZE_FILE
+ i
);
179 if( _lread(hFile
,(char*)lpiID
->idEntries
,i
) == i
)
180 { CURSORICONDIR
* lpID
; /* icon resource in resource format */
181 *uSize
= lpcid
.idCount
* sizeof(CURSORICONDIRENTRY
) + HEADER_SIZE
;
182 if( (lpID
= (CURSORICONDIR
*)HeapAlloc(GetProcessHeap(),0, *uSize
) ))
184 /* copy the header */
185 lpID
->idReserved
= lpiID
->idReserved
= 0;
186 lpID
->idType
= lpiID
->idType
= 1;
187 lpID
->idCount
= lpiID
->idCount
= lpcid
.idCount
;
189 /* copy the entrys */
190 for( i
=0; i
< lpiID
->idCount
; i
++ )
191 { memcpy((void*)&(lpID
->idEntries
[i
]),(void*)&(lpiID
->idEntries
[i
]), sizeof(CURSORICONDIRENTRY
) - 2);
192 lpID
->idEntries
[i
].wResId
= i
;
201 HeapFree( GetProcessHeap(), 0, lpiID
);
205 /*************************************************************************
206 * InternalExtractIcon [SHELL.39]
208 * This abortion is called directly by Progman
209 * fixme: the icon section is broken (don't have a handle for
210 * ICO_GetIconDirectory....)
213 #define ICO_INVALID_FILE 1
214 #define ICO_NO_ICONS 0
216 HGLOBAL WINAPI
ICO_ExtractIconEx(LPCSTR lpszExeFileName
, HICON
* RetPtr
, UINT nIconIndex
, UINT n
, UINT cxDesired
, UINT cyDesired
)
217 { HGLOBAL hRet
= ICO_NO_ICONS
;
221 HFILE hFile
= OpenFile( lpszExeFileName
, &ofs
, OF_READ
);
222 UINT16 iconDirCount
= 0,iconCount
= 0;
227 TRACE(shell
,"(file %s,start %d,extract %d\n", lpszExeFileName
, nIconIndex
, n
);
229 if( hFile
== HFILE_ERROR
|| !n
)
230 return ICO_INVALID_FILE
;
232 sig
= SHELL_GetResourceTable(hFile
,&pData
);
235 if( sig
==IMAGE_OS2_SIGNATURE
|| sig
==1 ) /* .ICO file */
237 NE_TYPEINFO
*pTInfo
= (NE_TYPEINFO
*)(pData
+ 2);
238 NE_NAMEINFO
*pIconStorage
= NULL
;
239 NE_NAMEINFO
*pIconDir
= NULL
;
240 LPicoICONDIR lpiID
= NULL
;
242 TRACE(shell
,"-- OS2/icon Signature (0x%08lx)\n", sig
);
244 if( pData
== (BYTE
*)-1 )
245 { pCIDir
= ICO_GetIconDirectory(hFile
, &lpiID
, &uSize
); /* check for .ICO file */
247 { iconDirCount
= 1; iconCount
= lpiID
->idCount
;
248 TRACE(shell
,"-- icon found %p 0x%08lx 0x%08x 0x%08x\n", pCIDir
, uSize
, iconDirCount
, iconCount
);
251 else while( pTInfo
->type_id
&& !(pIconStorage
&& pIconDir
) )
252 { if( pTInfo
->type_id
== NE_RSCTYPE_GROUP_ICON
) /* find icon directory and icon repository */
253 { iconDirCount
= pTInfo
->count
;
254 pIconDir
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
255 TRACE(shell
,"\tfound directory - %i icon families\n", iconDirCount
);
257 if( pTInfo
->type_id
== NE_RSCTYPE_ICON
)
258 { iconCount
= pTInfo
->count
;
259 pIconStorage
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
260 TRACE(shell
,"\ttotal icons - %i\n", iconCount
);
262 pTInfo
= (NE_TYPEINFO
*)((char*)(pTInfo
+1)+pTInfo
->count
*sizeof(NE_NAMEINFO
));
265 if( (pIconStorage
&& pIconDir
) || lpiID
) /* load resources and create icons */
266 { if( nIconIndex
== (UINT16
)-1 )
267 { RetPtr
[0] = iconDirCount
;
269 else if( nIconIndex
< iconDirCount
)
271 if( n
> iconDirCount
- nIconIndex
)
272 n
= iconDirCount
- nIconIndex
;
274 for( i
= nIconIndex
; i
< nIconIndex
+ n
; i
++ )
275 { /* .ICO files have only one icon directory */
277 if( lpiID
== NULL
) /* *.ico */
278 pCIDir
= SHELL_LoadResource( hFile
, pIconDir
+ i
, *(WORD
*)pData
, &uSize
);
279 RetPtr
[i
-nIconIndex
] = pLookupIconIdFromDirectoryEx( pCIDir
, TRUE
, SYSMETRICS_CXICON
, SYSMETRICS_CYICON
, 0);
280 HeapFree(GetProcessHeap(), 0, pCIDir
);
283 for( icon
= nIconIndex
; icon
< nIconIndex
+ n
; icon
++ )
286 { pCIDir
= ICO_LoadIcon( hFile
, lpiID
->idEntries
+ RetPtr
[icon
-nIconIndex
], &uSize
);
289 { for( i
= 0; i
< iconCount
; i
++ )
290 { if( pIconStorage
[i
].id
== (RetPtr
[icon
-nIconIndex
] | 0x8000) )
291 { pCIDir
= SHELL_LoadResource( hFile
, pIconStorage
+ i
,*(WORD
*)pData
, &uSize
);
296 { RetPtr
[icon
-nIconIndex
] = (HICON
) pCreateIconFromResourceEx(pCIDir
,uSize
,TRUE
,0x00030000, cxDesired
, cyDesired
, LR_DEFAULTCOLOR
);
299 { RetPtr
[icon
-nIconIndex
] = 0;
305 HeapFree( GetProcessHeap(), 0, lpiID
);
307 HeapFree( GetProcessHeap(), 0, pData
);
312 if( sig
== IMAGE_NT_SIGNATURE
)
313 { LPBYTE idata
,igdata
;
314 PIMAGE_DOS_HEADER dheader
;
315 PIMAGE_NT_HEADERS pe_header
;
316 PIMAGE_SECTION_HEADER pe_sections
;
317 PIMAGE_RESOURCE_DIRECTORY rootresdir
,iconresdir
,icongroupresdir
;
318 PIMAGE_RESOURCE_DATA_ENTRY idataent
,igdataent
;
319 PIMAGE_RESOURCE_DIRECTORY_ENTRY xresent
;
322 if ( !(fmapping
= CreateFileMappingA(hFile
,NULL
,PAGE_READONLY
|SEC_COMMIT
,0,0,NULL
)))
323 { WARN(shell
,"failed to create filemap.\n"); /* FIXME, INVALID_HANDLE_VALUE? */
324 hRet
= ICO_INVALID_FILE
;
325 goto end_2
; /* failure */
328 if ( !(peimage
= MapViewOfFile(fmapping
,FILE_MAP_READ
,0,0,0)))
329 { WARN(shell
,"failed to mmap filemap.\n");
330 hRet
= ICO_INVALID_FILE
;
331 goto end_2
; /* failure */
334 dheader
= (PIMAGE_DOS_HEADER
)peimage
;
335 pe_header
= (PIMAGE_NT_HEADERS
)(peimage
+dheader
->e_lfanew
); /* it is a pe header, SHELL_GetResourceTable checked that */
336 pe_sections
= (PIMAGE_SECTION_HEADER
)(((char*)pe_header
)+sizeof(*pe_header
)); /* probably makes problems with short PE headers...*/
339 for (i
=0;i
<pe_header
->FileHeader
.NumberOfSections
;i
++)
340 { if (pe_sections
[i
].Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
342 /* FIXME: doesn't work when the resources are not in a seperate section */
343 if (pe_sections
[i
].VirtualAddress
== pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
)
344 { rootresdir
= (PIMAGE_RESOURCE_DIRECTORY
)((char*)peimage
+pe_sections
[i
].PointerToRawData
);
350 { WARN(shell
,"haven't found section for resource directory.\n");
351 goto end_4
; /* failure */
353 /* search the group icon dir*/
354 if (!(icongroupresdir
= GetResDirEntryW(rootresdir
,RT_GROUP_ICONW
, (DWORD
)rootresdir
,FALSE
)))
355 { WARN(shell
,"No Icongroupresourcedirectory!\n");
356 goto end_4
; /* failure */
358 iconDirCount
= icongroupresdir
->NumberOfNamedEntries
+icongroupresdir
->NumberOfIdEntries
;
360 /* number of icons requested */
361 if( nIconIndex
== -1 )
362 { hRet
= iconDirCount
;
363 goto end_3
; /* success */
366 if (nIconIndex
>= iconDirCount
)
367 { WARN(shell
,"nIconIndex %d is larger than iconDirCount %d\n",nIconIndex
,iconDirCount
);
368 goto end_4
; /* failure */
371 xresent
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(icongroupresdir
+1); /* caller just wanted the number of entries */
373 if( n
> iconDirCount
- nIconIndex
) /* assure we don't get too much ... */
374 { n
= iconDirCount
- nIconIndex
;
377 xresent
= xresent
+nIconIndex
; /* starting from specified index ... */
379 for (i
=0;i
<n
;i
++,xresent
++)
380 { PIMAGE_RESOURCE_DIRECTORY resdir
;
382 /* go down this resource entry, name */
383 resdir
= (PIMAGE_RESOURCE_DIRECTORY
)((DWORD
)rootresdir
+(xresent
->u2
.s
.OffsetToDirectory
));
385 /* default language (0) */
386 resdir
= GetResDirEntryW(resdir
,(LPWSTR
)0,(DWORD
)rootresdir
,TRUE
);
387 igdataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)resdir
;
389 /* lookup address in mapped image for virtual address */
392 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
393 { if (igdataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
395 if (igdataent
->OffsetToData
+igdataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
397 igdata
= peimage
+(igdataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
401 { WARN(shell
,"no matching real address for icongroup!\n");
402 goto end_4
; /* failure */
404 RetPtr
[i
] = (HICON
)pLookupIconIdFromDirectoryEx(igdata
, TRUE
, cxDesired
, cyDesired
, LR_DEFAULTCOLOR
);
407 if (!(iconresdir
=GetResDirEntryW(rootresdir
,RT_ICONW
,(DWORD
)rootresdir
,FALSE
)))
408 { WARN(shell
,"No Iconresourcedirectory!\n");
409 goto end_4
; /* failure */
413 { PIMAGE_RESOURCE_DIRECTORY xresdir
;
414 xresdir
= GetResDirEntryW(iconresdir
,(LPWSTR
)(DWORD
)RetPtr
[i
],(DWORD
)rootresdir
,FALSE
);
415 xresdir
= GetResDirEntryW(xresdir
,(LPWSTR
)0,(DWORD
)rootresdir
,TRUE
);
416 idataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)xresdir
;
419 /* map virtual to address in image */
420 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
421 { if (idataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
423 if (idataent
->OffsetToData
+idataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
425 idata
= peimage
+(idataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
428 { WARN(shell
,"no matching real address found for icondata!\n");
432 RetPtr
[i
] = (HICON
) pCreateIconFromResourceEx(idata
,idataent
->Size
,TRUE
,0x00030000, cxDesired
, cyDesired
, LR_DEFAULTCOLOR
);
434 hRet
= RetPtr
[0]; /* return first icon */
435 goto end_3
; /* sucess */
437 hRet
= ICO_INVALID_FILE
;
438 goto end_1
; /* unknown filetype */
440 /* cleaning up (try & catch would be nicer:-) ) */
441 end_4
: hRet
= 0; /* failure */
442 end_3
: UnmapViewOfFile(peimage
); /* success */
443 end_2
: CloseHandle(fmapping
);
444 end_1
: _lclose( hFile
);
448 /********************** THE ICON CACHE ********************************/
449 HIMAGELIST ShellSmallIconList
= 0;
450 HIMAGELIST ShellBigIconList
= 0;
453 #define INVALID_INDEX -1
456 { LPCSTR sSourceFile
; /* file (not path!) containing the icon */
457 DWORD dwSourceIndex
; /* index within the file, if it is a resoure ID it will be negated */
458 DWORD dwListIndex
; /* index within the iconlist */
459 DWORD dwFlags
; /* GIL_* flags */
461 } SIC_ENTRY
, * LPSIC_ENTRY
;
463 /*****************************************************************************
464 * SIC_CompareEntrys [called by comctl32.dll]
467 * Callback for DPA_Search
469 INT CALLBACK
SIC_CompareEntrys( LPVOID p1
, LPVOID p2
, LPARAM lparam
)
470 { TRACE(shell
,"%p %p\n", p1
, p2
);
472 if (((LPSIC_ENTRY
)p1
)->dwSourceIndex
!= ((LPSIC_ENTRY
)p2
)->dwSourceIndex
) /* first the faster one*/
475 if (strcasecmp(((LPSIC_ENTRY
)p1
)->sSourceFile
,((LPSIC_ENTRY
)p2
)->sSourceFile
))
480 /*****************************************************************************
481 * SIC_IconAppend [internal]
484 * appends a icon pair to the end of the cache
486 static INT
SIC_IconAppend (LPCSTR sSourceFile
, INT dwSourceIndex
, HICON hSmallIcon
, HICON hBigIcon
)
487 { LPSIC_ENTRY lpsice
;
490 TRACE(shell
,"%s %i %x %x\n", sSourceFile
, dwSourceIndex
, hSmallIcon
,hBigIcon
);
492 lpsice
= (LPSIC_ENTRY
) SHAlloc (sizeof (SIC_ENTRY
));
494 lpsice
->sSourceFile
= HEAP_strdupA (GetProcessHeap(), 0, PathFindFilenameA(sSourceFile
));
495 lpsice
->dwSourceIndex
= dwSourceIndex
;
497 index
= pDPA_InsertPtr(hdpa
, 0x7fff, lpsice
);
498 if ( INVALID_INDEX
== index
)
500 return INVALID_INDEX
;
503 index
= pImageList_AddIcon (ShellSmallIconList
, hSmallIcon
);
504 index1
= pImageList_AddIcon (ShellBigIconList
, hBigIcon
);
507 { FIXME(shell
,"iconlists out of sync 0x%x 0x%x\n", index
, index1
);
509 lpsice
->dwListIndex
= index
;
511 return lpsice
->dwListIndex
;
514 /****************************************************************************
515 * SIC_LoadIcon [internal]
518 * gets small/big icon by number from a file
520 static INT
SIC_LoadIcon (LPCSTR sSourceFile
, INT dwSourceIndex
)
521 { HICON hiconLarge
=0;
524 ICO_ExtractIconEx(sSourceFile
, &hiconLarge
, dwSourceIndex
, 1, 32, 32 );
525 ICO_ExtractIconEx(sSourceFile
, &hiconSmall
, dwSourceIndex
, 1, 16, 16 );
528 if ( !hiconLarge
|| !hiconSmall
)
529 { WARN(shell
, "failure loading icon %i from %s (%x %x)\n", dwSourceIndex
, sSourceFile
, hiconLarge
, hiconSmall
);
532 return SIC_IconAppend (sSourceFile
, dwSourceIndex
, hiconSmall
, hiconLarge
);
534 /*****************************************************************************
535 * SIC_GetIconIndex [internal]
538 * sSourceFile [IN] filename of file containing the icon
539 * index [IN] index/resID (negated) in this file
542 * look in the cache for a proper icon. if not available the icon is taken
543 * from the file and cached
545 INT
SIC_GetIconIndex (LPCSTR sSourceFile
, INT dwSourceIndex
)
547 INT index
= INVALID_INDEX
;
549 TRACE(shell
,"%s %i\n", sSourceFile
, dwSourceIndex
);
551 sice
.sSourceFile
= PathFindFilenameA(sSourceFile
);
552 sice
.dwSourceIndex
= dwSourceIndex
;
554 if (NULL
!= pDPA_GetPtr (hdpa
, 0))
555 { index
= pDPA_Search (hdpa
, &sice
, -1L, SIC_CompareEntrys
, 0, 0);
558 if ( INVALID_INDEX
== index
)
559 { return SIC_LoadIcon (sSourceFile
, dwSourceIndex
);
562 TRACE(shell
, "-- found\n");
563 return ((LPSIC_ENTRY
)pDPA_GetPtr(hdpa
, index
))->dwListIndex
;
565 /****************************************************************************
566 * SIC_LoadIcon [internal]
569 * retrives the specified icon from the iconcache. if not found try's to load the icon
571 static HICON WINE_UNUSED
SIC_GetIcon (LPCSTR sSourceFile
, INT dwSourceIndex
, BOOL bSmallIcon
)
574 TRACE(shell
,"%s %i\n", sSourceFile
, dwSourceIndex
);
576 index
= SIC_GetIconIndex(sSourceFile
, dwSourceIndex
);
577 if (INVALID_INDEX
== index
)
578 { return INVALID_INDEX
;
582 return pImageList_GetIcon(ShellSmallIconList
, index
, ILD_NORMAL
);
583 return pImageList_GetIcon(ShellBigIconList
, index
, ILD_NORMAL
);
586 /*****************************************************************************
587 * SIC_Initialize [internal]
590 * hack to load the resources from the shell32.dll under a different dll name
591 * will be removed when the resource-compiler is ready
593 BOOL
SIC_Initialize(void)
594 { CHAR szShellPath
[MAX_PATH
];
595 HGLOBAL hSmRet
, hLgRet
;
596 HICON
*pSmRet
, *pLgRet
;
601 if (hdpa
) /* already initialized?*/
604 hdpa
= pDPA_Create(16);
610 GetSystemDirectoryA(szShellPath
,MAX_PATH
);
611 PathAddBackslashA(szShellPath
);
612 strcat(szShellPath
,"shell32.dll");
614 hSmRet
= GlobalAlloc( GMEM_FIXED
| GMEM_ZEROINIT
, sizeof(HICON
)*40);
615 hLgRet
= GlobalAlloc( GMEM_FIXED
| GMEM_ZEROINIT
, sizeof(HICON
)*40);
617 pSmRet
= (HICON
*)GlobalLock(hSmRet
);
618 pLgRet
= (HICON
*)GlobalLock(hLgRet
);
620 ExtractIconExA ( szShellPath
, 0, pLgRet
, pSmRet
, 40 );
622 ShellSmallIconList
= pImageList_Create(16,16,ILC_COLORDDB
| ILC_MASK
,0,0x20);
623 ShellBigIconList
= pImageList_Create(32,32,ILC_COLORDDB
| ILC_MASK
,0,0x20);
625 for (index
=0; index
<40; index
++)
626 { if (! pSmRet
[index
] )
627 { MSG("*** failure loading resources from %s\n", szShellPath
);
628 MSG("*** this is a hack for loading the internal and external dll at the same time\n");
629 MSG("*** you can ignore it but you will miss some icons in win95 dialogs\n\n");
632 SIC_IconAppend (szShellPath
, index
, pSmRet
[index
], pLgRet
[index
]);
635 GlobalUnlock(hLgRet
);
638 GlobalUnlock(hSmRet
);
641 TRACE(shell
,"hIconSmall=%p hIconBig=%p\n",ShellSmallIconList
, ShellBigIconList
);
645 /*************************************************************************
650 void SIC_Destroy(void)
655 if (hdpa
&& NULL
!= pDPA_GetPtr (hdpa
, 0))
656 { for (i
=0; i
< pDPA_GetPtrCount(hdpa
); ++i
)
657 { lpsice
= pDPA_GetPtr(hdpa
, i
);
663 /*************************************************************************
664 * Shell_GetImageList [SHELL32.71]
667 * imglist[1|2] [OUT] pointer which recive imagelist handles
670 BOOL WINAPI
Shell_GetImageList(HIMAGELIST
* lpBigList
, HIMAGELIST
* lpSmallList
)
671 { TRACE(shell
,"(%p,%p)\n",lpBigList
,lpSmallList
);
673 { *lpBigList
= ShellBigIconList
;
676 { *lpSmallList
= ShellSmallIconList
;
681 /*************************************************************************
682 * PidlToSicIndex [INTERNAL]
685 * sh [IN] IShellFolder
688 * pIndex [OUT] index within the SIC
691 BOOL
PidlToSicIndex (IShellFolder
* sh
, LPITEMIDLIST pidl
, BOOL bBigIcon
, UINT
* pIndex
)
694 char szIconFile
[MAX_PATH
]; /* file containing the icon */
695 INT iSourceIndex
; /* index or resID(negated) in this file */
699 TRACE(shell
,"sf=%p pidl=%p\n", sh
, pidl
);
701 if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh
, 0, 1, &pidl
, &IID_IExtractIconA
, 0, (void **)&ei
)))
703 if (NOERROR
==IExtractIconA_GetIconLocation(ei
, 0, szIconFile
, MAX_PATH
, &iSourceIndex
, &dwFlags
))
704 { *pIndex
= SIC_GetIconIndex(szIconFile
, iSourceIndex
);
707 IExtractIconA_Release(ei
);
710 if (INVALID_INDEX
== *pIndex
) /* default icon when failed */
717 /*************************************************************************
718 * SHMapPIDLToSystemImageListIndex [SHELL32.77]
721 * sh [IN] pointer to an instance of IShellFolder
723 * pIndex [OUT][OPTIONAL] SIC index for big icon
726 UINT WINAPI
SHMapPIDLToSystemImageListIndex(LPSHELLFOLDER sh
, LPITEMIDLIST pidl
, UINT
* pIndex
)
730 WARN(shell
,"(SF=%p,pidl=%p,%p)\n",sh
,pidl
,pIndex
);
734 PidlToSicIndex ( sh
, pidl
, 1, pIndex
);
735 PidlToSicIndex ( sh
, pidl
, 0, &Index
);
739 /*************************************************************************
740 * Shell_GetCachedImageIndex [SHELL32.72]
743 INT WINAPI
Shell_GetCachedImageIndexA(LPCSTR szPath
, INT nIndex
, BOOL bSimulateDoc
)
745 WARN(shell
,"(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath
), nIndex
, bSimulateDoc
);
746 return SIC_GetIconIndex(szPath
, nIndex
);
749 INT WINAPI
Shell_GetCachedImageIndexW(LPCWSTR szPath
, INT nIndex
, BOOL bSimulateDoc
)
751 LPSTR sTemp
= HEAP_strdupWtoA (GetProcessHeap(),0,szPath
);
753 WARN(shell
,"(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath
), nIndex
, bSimulateDoc
);
755 ret
= SIC_GetIconIndex(sTemp
, nIndex
);
756 HeapFree(GetProcessHeap(),0,sTemp
);
760 INT WINAPI
Shell_GetCachedImageIndexAW(LPCVOID szPath
, INT nIndex
, BOOL bSimulateDoc
)
761 { if( VERSION_OsIsUnicode())
762 return Shell_GetCachedImageIndexW(szPath
, nIndex
, bSimulateDoc
);
763 return Shell_GetCachedImageIndexA(szPath
, nIndex
, bSimulateDoc
);
766 /*************************************************************************
767 * ExtracticonExAW [shell32.189]
769 HICON WINAPI
ExtractIconExAW ( LPCVOID lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
770 { if (VERSION_OsIsUnicode())
771 return ExtractIconExW ( lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
772 return ExtractIconExA ( lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
774 /*************************************************************************
775 * ExtracticonExA [shell32.190]
778 * 1 file is not valid
779 * HICON handle of a icon (phiconLarge/Small == NULL)
781 HICON WINAPI
ExtractIconExA ( LPCSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
784 TRACE(shell
,"file=%s idx=%i %p %p num=%i\n", lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
786 if (nIconIndex
==-1) /* Number of icons requested */
787 return ICO_ExtractIconEx(lpszFile
, NULL
, -1, 0, 0, 0 );
791 { ret
= ICO_ExtractIconEx(lpszFile
, phiconLarge
, nIconIndex
, nIcons
, 32, 32 );
793 { ret
= phiconLarge
[0];
797 /* if no pointers given and one icon expected, return the handle directly*/
798 if (!phiconLarge
&& ! phiconSmall
&& nIcons
==1 )
802 { ret
= ICO_ExtractIconEx(lpszFile
, phiconSmall
, nIconIndex
, nIcons
, 16, 16 );
804 { ret
= phiconSmall
[0];
810 /*************************************************************************
811 * ExtracticonExW [shell32.191]
813 HICON WINAPI
ExtractIconExW ( LPCWSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
817 TRACE(shell
,"file=%s idx=%i %p %p num=%i\n", debugstr_w(lpszFile
), nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
819 sFile
= HEAP_strdupWtoA (GetProcessHeap(),0,lpszFile
);
820 ret
= ExtractIconExA ( sFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
821 HeapFree(GetProcessHeap(),0,sFile
);