2 * shell icon cache (SIC)
5 * since dll geting never unloaded the iconcache will never be freed
8 #include "wine/winuser16.h"
9 #include "wine/winbase16.h"
11 #include "cursoricon.h"
15 #include "sysmetrics.h"
16 #include "winversion.h"
20 #include "shell32_main.h"
26 BYTE bWidth
; /* Width, in pixels, of the image */
27 BYTE bHeight
; /* Height, in pixels, of the image */
28 BYTE bColorCount
; /* Number of colors in image (0 if >=8bpp) */
29 BYTE bReserved
; /* Reserved ( must be 0) */
30 WORD wPlanes
; /* Color Planes */
31 WORD wBitCount
; /* Bits per pixel */
32 DWORD dwBytesInRes
; /* How many bytes in this resource? */
33 DWORD dwImageOffset
; /* Where in the file is this image? */
34 } icoICONDIRENTRY
, *LPicoICONDIRENTRY
;
38 WORD idReserved
; /* Reserved (must be 0) */
39 WORD idType
; /* Resource Type (1 for icons) */
40 WORD idCount
; /* How many images? */
41 icoICONDIRENTRY idEntries
[1]; /* An entry for each image (idCount of 'em) */
42 } icoICONDIR
, *LPicoICONDIR
;
46 /*************************************************************************
47 * SHELL_GetResourceTable
49 static DWORD
SHELL_GetResourceTable(HFILE hFile
,LPBYTE
*retptr
)
50 { IMAGE_DOS_HEADER mz_header
;
57 _llseek( hFile
, 0, SEEK_SET
);
58 if ((_lread(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) || (mz_header
.e_magic
!= IMAGE_DOS_SIGNATURE
))
59 { if (mz_header
.e_cblp
== 1) /* .ICO file ? */
60 { *retptr
= (LPBYTE
)-1; /* ICONHEADER.idType, must be 1 */
64 return 0; /* failed */
66 _llseek( hFile
, mz_header
.e_lfanew
, SEEK_SET
);
68 if (_lread( hFile
, magic
, sizeof(magic
) ) != sizeof(magic
))
71 _llseek( hFile
, mz_header
.e_lfanew
, SEEK_SET
);
73 if (*(DWORD
*)magic
== IMAGE_NT_SIGNATURE
)
74 return IMAGE_NT_SIGNATURE
;
76 if (*(WORD
*)magic
== IMAGE_OS2_SIGNATURE
)
77 { IMAGE_OS2_HEADER ne_header
;
78 LPBYTE pTypeInfo
= (LPBYTE
)-1;
80 if (_lread(hFile
,&ne_header
,sizeof(ne_header
))!=sizeof(ne_header
))
83 if (ne_header
.ne_magic
!= IMAGE_OS2_SIGNATURE
)
86 size
= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
88 if( size
> sizeof(NE_TYPEINFO
) )
89 { pTypeInfo
= (BYTE
*)HeapAlloc( GetProcessHeap(), 0, size
);
91 { _llseek(hFile
, mz_header
.e_lfanew
+ne_header
.resource_tab_offset
, SEEK_SET
);
92 if( _lread( hFile
, (char*)pTypeInfo
, size
) != size
)
93 { HeapFree( GetProcessHeap(), 0, pTypeInfo
);
99 return IMAGE_OS2_SIGNATURE
;
101 return 0; /* failed */
103 /*************************************************************************
106 static HGLOBAL16
SHELL_LoadResource(HINSTANCE hInst
, HFILE hFile
, NE_NAMEINFO
* pNInfo
, WORD sizeShift
)
108 HGLOBAL16 handle
= DirectResAlloc16( hInst
, 0x10, (DWORD
)pNInfo
->length
<< sizeShift
);
112 if( (ptr
= (BYTE
*)GlobalLock16( handle
)) )
113 { _llseek( hFile
, (DWORD
)pNInfo
->offset
<< sizeShift
, SEEK_SET
);
114 _lread( hFile
, (char*)ptr
, pNInfo
->length
<< sizeShift
);
120 /*************************************************************************
123 static HGLOBAL16
ICO_LoadIcon(HINSTANCE hInst
, HFILE hFile
, LPicoICONDIRENTRY lpiIDE
)
125 HGLOBAL16 handle
= DirectResAlloc16( hInst
, 0x10, lpiIDE
->dwBytesInRes
);
127 if( (ptr
= (BYTE
*)GlobalLock16( handle
)) )
128 { _llseek( hFile
, lpiIDE
->dwImageOffset
, SEEK_SET
);
129 _lread( hFile
, (char*)ptr
, lpiIDE
->dwBytesInRes
);
135 /*************************************************************************
136 * ICO_GetIconDirectory
138 * Read .ico file and build phony ICONDIR struct for GetIconID
140 static HGLOBAL16
ICO_GetIconDirectory(HINSTANCE hInst
, HFILE hFile
, LPicoICONDIR
* lplpiID
)
141 { WORD id
[3]; /* idReserved, idType, idCount */
146 _llseek( hFile
, 0, SEEK_SET
);
147 if( _lread(hFile
,(char*)id
,sizeof(id
)) != sizeof(id
) )
152 * - see http://www.microsoft.com/win32dev/ui/icons.htm
155 if( id
[0] || id
[1] != 1 || !id
[2] )
158 i
= id
[2]*sizeof(icoICONDIRENTRY
) + sizeof(id
);
160 lpiID
= (LPicoICONDIR
)HeapAlloc( GetProcessHeap(), 0, i
);
162 if( _lread(hFile
,(char*)lpiID
->idEntries
,i
) == i
)
163 { HGLOBAL16 handle
= DirectResAlloc16( hInst
, 0x10,id
[2]*sizeof(ICONDIRENTRY
) + sizeof(id
) );
165 { CURSORICONDIR
* lpID
= (CURSORICONDIR
*)GlobalLock16( handle
);
166 lpID
->idReserved
= lpiID
->idReserved
= id
[0];
167 lpID
->idType
= lpiID
->idType
= id
[1];
168 lpID
->idCount
= lpiID
->idCount
= id
[2];
169 for( i
=0; i
< lpiID
->idCount
; i
++ )
170 { memcpy((void*)(lpID
->idEntries
+ i
),(void*)(lpiID
->idEntries
+ i
), sizeof(ICONDIRENTRY
) - 2);
171 lpID
->idEntries
[i
].icon
.wResId
= i
;
179 HeapFree( GetProcessHeap(), 0, lpiID
);
183 /*************************************************************************
184 * InternalExtractIcon [SHELL.39]
186 * This abortion is called directly by Progman
187 * fixme: the icon section is broken (don't have a handle for
188 * ICO_GetIconDirectory....)
191 #define ICO_INVALID_FILE 1
192 #define ICO_NO_ICONS 0
194 HGLOBAL WINAPI
ICO_ExtractIconEx(LPCSTR lpszExeFileName
, HICON
* RetPtr
, UINT nIconIndex
, UINT n
, UINT cxDesired
, UINT cyDesired
)
195 { HGLOBAL hRet
= ICO_NO_ICONS
;
199 HFILE hFile
= OpenFile( lpszExeFileName
, &ofs
, OF_READ
);
200 UINT16 iconDirCount
= 0,iconCount
= 0;
204 TRACE(shell
,"(file %s,start %d,extract %d\n", lpszExeFileName
, nIconIndex
, n
);
206 if( hFile
== HFILE_ERROR
|| !n
)
207 return ICO_INVALID_FILE
;
209 sig
= SHELL_GetResourceTable(hFile
,&pData
);
212 if( sig
==IMAGE_OS2_SIGNATURE
|| sig
==1 ) /* .ICO file */
214 NE_TYPEINFO
* pTInfo
= (NE_TYPEINFO
*)(pData
+ 2);
215 NE_NAMEINFO
* pIconStorage
= NULL
;
216 NE_NAMEINFO
* pIconDir
= NULL
;
217 LPicoICONDIR lpiID
= NULL
;
219 if( pData
== (BYTE
*)-1 )
220 { hIcon
= ICO_GetIconDirectory(0, hFile
, &lpiID
); /* check for .ICO file */
222 { iconDirCount
= 1; iconCount
= lpiID
->idCount
;
225 else while( pTInfo
->type_id
&& !(pIconStorage
&& pIconDir
) )
226 { if( pTInfo
->type_id
== NE_RSCTYPE_GROUP_ICON
) /* find icon directory and icon repository */
227 { iconDirCount
= pTInfo
->count
;
228 pIconDir
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
229 TRACE(shell
,"\tfound directory - %i icon families\n", iconDirCount
);
231 if( pTInfo
->type_id
== NE_RSCTYPE_ICON
)
232 { iconCount
= pTInfo
->count
;
233 pIconStorage
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
234 TRACE(shell
,"\ttotal icons - %i\n", iconCount
);
236 pTInfo
= (NE_TYPEINFO
*)((char*)(pTInfo
+1)+pTInfo
->count
*sizeof(NE_NAMEINFO
));
239 if( (pIconStorage
&& pIconDir
) || lpiID
) /* load resources and create icons */
240 { if( nIconIndex
== (UINT16
)-1 )
241 { RetPtr
[0] = iconDirCount
;
243 else if( nIconIndex
< iconDirCount
)
245 if( n
> iconDirCount
- nIconIndex
)
246 n
= iconDirCount
- nIconIndex
;
248 for( i
= nIconIndex
; i
< nIconIndex
+ n
; i
++ )
249 { /* .ICO files have only one icon directory */
252 hIcon
= SHELL_LoadResource( 0, hFile
, pIconDir
+ i
, *(WORD
*)pData
);
253 RetPtr
[i
-nIconIndex
] = GetIconID16( hIcon
, 3 );
257 for( icon
= nIconIndex
; icon
< nIconIndex
+ n
; icon
++ )
260 { hIcon
= ICO_LoadIcon( 0, hFile
, lpiID
->idEntries
+ RetPtr
[icon
-nIconIndex
]);
263 { for( i
= 0; i
< iconCount
; i
++ )
264 { if( pIconStorage
[i
].id
== (RetPtr
[icon
-nIconIndex
] | 0x8000) )
265 { hIcon
= SHELL_LoadResource( 0, hFile
, pIconStorage
+ i
,*(WORD
*)pData
);
270 { RetPtr
[icon
-nIconIndex
] = LoadIconHandler16( hIcon
, TRUE
);
273 { RetPtr
[icon
-nIconIndex
] = 0;
279 HeapFree( GetProcessHeap(), 0, lpiID
);
281 HeapFree( GetProcessHeap(), 0, pData
);
286 if( sig
== IMAGE_NT_SIGNATURE
)
287 { LPBYTE idata
,igdata
;
288 PIMAGE_DOS_HEADER dheader
;
289 PIMAGE_NT_HEADERS pe_header
;
290 PIMAGE_SECTION_HEADER pe_sections
;
291 PIMAGE_RESOURCE_DIRECTORY rootresdir
,iconresdir
,icongroupresdir
;
292 PIMAGE_RESOURCE_DATA_ENTRY idataent
,igdataent
;
293 PIMAGE_RESOURCE_DIRECTORY_ENTRY xresent
;
296 if ( !(fmapping
= CreateFileMappingA(hFile
,NULL
,PAGE_READONLY
|SEC_COMMIT
,0,0,NULL
)))
297 { WARN(shell
,"failed to create filemap.\n"); /* FIXME, INVALID_HANDLE_VALUE? */
298 hRet
= ICO_INVALID_FILE
;
299 goto end_2
; /* failure */
302 if ( !(peimage
= MapViewOfFile(fmapping
,FILE_MAP_READ
,0,0,0)))
303 { WARN(shell
,"failed to mmap filemap.\n");
304 hRet
= ICO_INVALID_FILE
;
305 goto end_2
; /* failure */
308 dheader
= (PIMAGE_DOS_HEADER
)peimage
;
309 pe_header
= (PIMAGE_NT_HEADERS
)(peimage
+dheader
->e_lfanew
); /* it is a pe header, SHELL_GetResourceTable checked that */
310 pe_sections
= (PIMAGE_SECTION_HEADER
)(((char*)pe_header
)+sizeof(*pe_header
)); /* probably makes problems with short PE headers...*/
313 for (i
=0;i
<pe_header
->FileHeader
.NumberOfSections
;i
++)
314 { if (pe_sections
[i
].Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
316 /* FIXME: doesn't work when the resources are not in a seperate section */
317 if (pe_sections
[i
].VirtualAddress
== pe_header
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
)
318 { rootresdir
= (PIMAGE_RESOURCE_DIRECTORY
)((char*)peimage
+pe_sections
[i
].PointerToRawData
);
324 { WARN(shell
,"haven't found section for resource directory.\n");
325 goto end_4
; /* failure */
327 /* search the group icon dir*/
328 if (!(icongroupresdir
= GetResDirEntryW(rootresdir
,RT_GROUP_ICONW
, (DWORD
)rootresdir
,FALSE
)))
329 { WARN(shell
,"No Icongroupresourcedirectory!\n");
330 goto end_4
; /* failure */
332 iconDirCount
= icongroupresdir
->NumberOfNamedEntries
+icongroupresdir
->NumberOfIdEntries
;
334 /* number of icons requested */
335 if( nIconIndex
== -1 )
336 { hRet
= iconDirCount
;
337 goto end_3
; /* success */
340 if (nIconIndex
>= iconDirCount
)
341 { WARN(shell
,"nIconIndex %d is larger than iconDirCount %d\n",nIconIndex
,iconDirCount
);
342 goto end_4
; /* failure */
345 xresent
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(icongroupresdir
+1); /* caller just wanted the number of entries */
347 if( n
> iconDirCount
- nIconIndex
) /* assure we don't get too much ... */
348 { n
= iconDirCount
- nIconIndex
;
351 xresent
= xresent
+nIconIndex
; /* starting from specified index ... */
353 for (i
=0;i
<n
;i
++,xresent
++)
354 { PIMAGE_RESOURCE_DIRECTORY resdir
;
356 /* go down this resource entry, name */
357 resdir
= (PIMAGE_RESOURCE_DIRECTORY
)((DWORD
)rootresdir
+(xresent
->u2
.s
.OffsetToDirectory
));
359 /* default language (0) */
360 resdir
= GetResDirEntryW(resdir
,(LPWSTR
)0,(DWORD
)rootresdir
,TRUE
);
361 igdataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)resdir
;
363 /* lookup address in mapped image for virtual address */
366 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
367 { if (igdataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
369 if (igdataent
->OffsetToData
+igdataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
371 igdata
= peimage
+(igdataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
375 { WARN(shell
,"no matching real address for icongroup!\n");
376 goto end_4
; /* failure */
378 RetPtr
[i
] = (HICON
)pLookupIconIdFromDirectoryEx(igdata
, TRUE
, cxDesired
, cyDesired
, LR_DEFAULTCOLOR
);
381 if (!(iconresdir
=GetResDirEntryW(rootresdir
,RT_ICONW
,(DWORD
)rootresdir
,FALSE
)))
382 { WARN(shell
,"No Iconresourcedirectory!\n");
383 goto end_4
; /* failure */
387 { PIMAGE_RESOURCE_DIRECTORY xresdir
;
388 xresdir
= GetResDirEntryW(iconresdir
,(LPWSTR
)(DWORD
)RetPtr
[i
],(DWORD
)rootresdir
,FALSE
);
389 xresdir
= GetResDirEntryW(xresdir
,(LPWSTR
)0,(DWORD
)rootresdir
,TRUE
);
390 idataent
= (PIMAGE_RESOURCE_DATA_ENTRY
)xresdir
;
393 /* map virtual to address in image */
394 for (j
=0;j
<pe_header
->FileHeader
.NumberOfSections
;j
++)
395 { if (idataent
->OffsetToData
< pe_sections
[j
].VirtualAddress
)
397 if (idataent
->OffsetToData
+idataent
->Size
> pe_sections
[j
].VirtualAddress
+pe_sections
[j
].SizeOfRawData
)
399 idata
= peimage
+(idataent
->OffsetToData
-pe_sections
[j
].VirtualAddress
+pe_sections
[j
].PointerToRawData
);
402 { WARN(shell
,"no matching real address found for icondata!\n");
406 RetPtr
[i
] = (HICON
) pCreateIconFromResourceEx(idata
,idataent
->Size
,TRUE
,0x00030000, cxDesired
, cyDesired
, LR_DEFAULTCOLOR
);
408 hRet
= RetPtr
[0]; /* return first icon */
409 goto end_3
; /* sucess */
411 hRet
= ICO_INVALID_FILE
;
412 goto end_1
; /* unknown filetype */
414 /* cleaning up (try & catch would be nicer:-) ) */
415 end_4
: hRet
= 0; /* failure */
416 end_3
: UnmapViewOfFile(peimage
); /* success */
417 end_2
: CloseHandle(fmapping
);
418 end_1
: _lclose( hFile
);
422 /********************** THE ICON CACHE ********************************/
423 HIMAGELIST ShellSmallIconList
= 0;
424 HIMAGELIST ShellBigIconList
= 0;
427 #define INVALID_INDEX -1
430 { LPCSTR sSourceFile
; /* file icon is from */
431 DWORD dwSourceIndex
; /* index within the file */
432 DWORD dwListIndex
; /* index within the iconlist */
433 } SIC_ENTRY
, * LPSIC_ENTRY
;
435 /*****************************************************************************
436 * SIC_CompareEntrys [called by comctl32.dll]
438 * Callback for DPA_Search
440 INT CALLBACK
SIC_CompareEntrys( LPVOID p1
, LPVOID p2
, LPARAM lparam
)
441 { TRACE(shell
,"%p %p\n", p1
, p2
);
443 if (((LPSIC_ENTRY
)p1
)->dwSourceIndex
!= ((LPSIC_ENTRY
)p2
)->dwSourceIndex
) /* first the faster one*/
446 if (strcasecmp(((LPSIC_ENTRY
)p1
)->sSourceFile
,((LPSIC_ENTRY
)p2
)->sSourceFile
))
451 /*****************************************************************************
452 * SIC_IconAppend (internal)
454 * appends a icon pair to the end of the cache
456 static INT
SIC_IconAppend (LPCSTR sSourceFile
, INT dwSourceIndex
, HICON hSmallIcon
, HICON hBigIcon
)
457 { LPSIC_ENTRY lpsice
;
460 TRACE(shell
,"%s %i %x %x\n", sSourceFile
, dwSourceIndex
, hSmallIcon
,hBigIcon
);
462 lpsice
= (LPSIC_ENTRY
) SHAlloc (sizeof (SIC_ENTRY
));
464 lpsice
->sSourceFile
= HEAP_strdupA (GetProcessHeap(),0,sSourceFile
);
465 lpsice
->dwSourceIndex
= dwSourceIndex
;
467 index
= pDPA_InsertPtr(hdpa
, 0x7fff, lpsice
);
468 if ( INVALID_INDEX
== index
)
470 return INVALID_INDEX
;
473 index
= pImageList_AddIcon (ShellSmallIconList
, hSmallIcon
);
474 index1
= pImageList_AddIcon (ShellBigIconList
, hBigIcon
);
477 { FIXME(shell
,"iconlists out of sync 0x%x 0x%x\n", index
, index1
);
479 lpsice
->dwListIndex
= index
;
481 return lpsice
->dwListIndex
;
484 /****************************************************************************
485 * SIC_LoadIcon [internal]
487 * gets small/big icon by number from a file
489 static INT
SIC_LoadIcon (LPCSTR sSourceFile
, INT dwSourceIndex
)
490 { HICON hiconLarge
=0;
493 ICO_ExtractIconEx(sSourceFile
, &hiconLarge
, dwSourceIndex
, 1, 32, 32 );
494 ICO_ExtractIconEx(sSourceFile
, &hiconSmall
, dwSourceIndex
, 1, 16, 16 );
497 if ( !hiconLarge
|| !hiconSmall
)
498 { WARN(shell
, "failure loading icon %i from %s (%x %x)\n", dwSourceIndex
, sSourceFile
, hiconLarge
, hiconSmall
);
501 return SIC_IconAppend (sSourceFile
, dwSourceIndex
, hiconSmall
, hiconLarge
);
503 /*****************************************************************************
504 * SIC_GetIconIndex [internal]
506 * look in the cache for a proper icon. if not available the icon is taken
507 * from the file and cached
509 INT
SIC_GetIconIndex (LPCSTR sSourceFile
, INT dwSourceIndex
)
511 INT index
= INVALID_INDEX
;
513 TRACE(shell
,"%s %i\n", sSourceFile
, dwSourceIndex
);
515 sice
.sSourceFile
= sSourceFile
;
516 sice
.dwSourceIndex
= dwSourceIndex
;
518 if (NULL
!= pDPA_GetPtr (hdpa
, 0))
519 { index
= pDPA_Search (hdpa
, &sice
, -1L, SIC_CompareEntrys
, 0, 0);
522 if ( INVALID_INDEX
== index
)
523 { return SIC_LoadIcon (sSourceFile
, dwSourceIndex
);
526 TRACE(shell
, "-- found\n");
527 return ((LPSIC_ENTRY
)pDPA_GetPtr(hdpa
, index
))->dwListIndex
;
529 /****************************************************************************
530 * SIC_LoadIcon [internal]
532 * retrives the specified icon from the iconcache. if not found try's to load the icon
534 static HICON
SIC_GetIcon (LPCSTR sSourceFile
, INT dwSourceIndex
, BOOL bSmallIcon
)
537 TRACE(shell
,"%s %i\n", sSourceFile
, dwSourceIndex
);
539 index
= SIC_GetIconIndex(sSourceFile
, dwSourceIndex
);
540 if (INVALID_INDEX
== index
)
541 { return INVALID_INDEX
;
545 return pImageList_GetIcon(ShellSmallIconList
, index
, ILD_NORMAL
);
546 return pImageList_GetIcon(ShellBigIconList
, index
, ILD_NORMAL
);
549 /*****************************************************************************
550 * SIC_Initialize [internal]
552 * hack to load the resources from the shell32.dll under a different dll name
553 * will be removed when the resource-compiler is ready
555 BOOL
SIC_Initialize(void)
556 { CHAR szShellPath
[MAX_PATH
];
557 HGLOBAL hSmRet
, hLgRet
;
558 HICON
*pSmRet
, *pLgRet
;
563 if (hdpa
) /* already initialized?*/
566 hdpa
= pDPA_Create(16);
572 GetSystemDirectoryA(szShellPath
,MAX_PATH
);
573 PathAddBackslashA(szShellPath
);
574 strcat(szShellPath
,"shell32.dll");
576 hSmRet
= GlobalAlloc( GMEM_FIXED
| GMEM_ZEROINIT
, sizeof(HICON
)*40);
577 hLgRet
= GlobalAlloc( GMEM_FIXED
| GMEM_ZEROINIT
, sizeof(HICON
)*40);
579 pSmRet
= (HICON
*)GlobalLock(hSmRet
);
580 pLgRet
= (HICON
*)GlobalLock(hLgRet
);
582 ExtractIconExA ( szShellPath
, 0, pLgRet
, pSmRet
, 40 );
584 ShellSmallIconList
= pImageList_Create(16,16,ILC_COLORDDB
| ILC_MASK
,0,0x20);
585 ShellBigIconList
= pImageList_Create(32,32,ILC_COLORDDB
| ILC_MASK
,0,0x20);
587 for (index
=0; index
<40; index
++)
588 { if (! pSmRet
[index
] )
589 { MSG("*** failure loading resources from %s\n", szShellPath
);
590 MSG("*** this is a hack for loading the internal and external dll at the same time\n");
591 MSG("*** you can ignore it but you will miss some icons in win95 dialogs\n\n");
594 SIC_IconAppend (szShellPath
, index
, pSmRet
[index
], pLgRet
[index
]);
597 GlobalUnlock(hLgRet
);
600 GlobalUnlock(hSmRet
);
603 TRACE(shell
,"hIconSmall=%p hIconBig=%p\n",ShellSmallIconList
, ShellBigIconList
);
608 /*************************************************************************
609 * Shell_GetImageList [SHELL32.71]
612 * imglist[1|2] [OUT] pointer which recive imagelist handles
615 DWORD WINAPI
Shell_GetImageList(HIMAGELIST
* lpBigList
, HIMAGELIST
* lpSmallList
)
616 { TRACE(shell
,"(%p,%p)\n",lpBigList
,lpSmallList
);
618 { *lpBigList
= ShellBigIconList
;
621 { *lpSmallList
= ShellSmallIconList
;
627 /*************************************************************************
628 * SHMapPIDLToSystemImageListIndex [SHELL32.77]
631 * x pointer to an instance of IShellFolder
637 DWORD WINAPI
SHMapPIDLToSystemImageListIndex(LPSHELLFOLDER sh
,LPITEMIDLIST pidl
,DWORD z
)
638 { char sTemp
[MAX_PATH
];
639 DWORD dwNr
, ret
= INVALID_INDEX
;
640 LPITEMIDLIST pidltemp
= ILFindLastID(pidl
);
642 WARN(shell
,"(SF=%p,pidl=%p,0x%08lx)\n",sh
,pidl
,z
);
645 if (_ILIsDesktop(pidltemp
))
648 else if (_ILIsMyComputer(pidltemp
))
649 { if (HCR_GetDefaultIcon("CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}", sTemp
, MAX_PATH
, &dwNr
))
650 { ret
= SIC_GetIconIndex(sTemp
, dwNr
);
651 return (( INVALID_INDEX
== ret
) ? 15 : ret
);
654 else if (_ILIsDrive (pidltemp
))
655 { if (HCR_GetDefaultIcon("Drive", sTemp
, MAX_PATH
, &dwNr
))
656 { ret
= SIC_GetIconIndex(sTemp
, dwNr
);
657 return (( INVALID_INDEX
== ret
) ? 8 : ret
);
660 else if (_ILIsFolder (pidltemp
))
661 { if (HCR_GetDefaultIcon("Folder", sTemp
, MAX_PATH
, &dwNr
))
662 { ret
= SIC_GetIconIndex(sTemp
, dwNr
);
663 return (( INVALID_INDEX
== ret
) ? 3 : ret
);
667 if (_ILGetExtension (pidltemp
, sTemp
, MAX_PATH
)) /* object is file */
668 { if ( HCR_MapTypeToValue(sTemp
, sTemp
, MAX_PATH
))
669 { if (HCR_GetDefaultIcon(sTemp
, sTemp
, MAX_PATH
, &dwNr
))
670 { if (!strcmp("%1",sTemp
)) /* icon is in the file */
671 { _ILGetPidlPath(pidl
, sTemp
, MAX_PATH
);
674 ret
= SIC_GetIconIndex(sTemp
, dwNr
);
678 return (( INVALID_INDEX
== ret
) ? 1 : ret
);
681 /*************************************************************************
682 * Shell_GetCachedImageIndex [SHELL32.72]
685 INT WINAPI
Shell_GetCachedImageIndexA(LPCSTR szPath
, INT nIndex
, DWORD z
)
686 { WARN(shell
,"(%s,%08x,%08lx) semi-stub.\n",debugstr_a(szPath
),nIndex
,z
);
687 return SIC_GetIconIndex(szPath
, nIndex
);
690 INT WINAPI
Shell_GetCachedImageIndexW(LPCWSTR szPath
, INT nIndex
, DWORD z
)
692 LPSTR sTemp
= HEAP_strdupWtoA (GetProcessHeap(),0,szPath
);
694 WARN(shell
,"(%s,%08x,%08lx) semi-stub.\n",debugstr_w(szPath
),nIndex
,z
);
696 ret
= SIC_GetIconIndex(sTemp
, nIndex
);
697 HeapFree(GetProcessHeap(),0,sTemp
);
701 INT WINAPI
Shell_GetCachedImageIndexAW(LPCVOID szPath
, INT nIndex
, DWORD z
)
702 { if( VERSION_OsIsUnicode())
703 return Shell_GetCachedImageIndexW(szPath
, nIndex
, z
);
704 return Shell_GetCachedImageIndexA(szPath
, nIndex
, z
);
707 /*************************************************************************
708 * ExtracticonEx32 [shell32.189]
710 HICON WINAPI
ExtractIconExAW ( LPCVOID lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
711 { if (VERSION_OsIsUnicode())
712 return ExtractIconExW ( lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
713 return ExtractIconExA ( lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
715 /*************************************************************************
716 * ExtracticonEx32A [shell32.190]
719 * 1 file is not valid
720 * HICON32 handle of a icon (phiconLarge/Small == NULL)
722 HICON WINAPI
ExtractIconExA ( LPCSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
725 TRACE(shell
,"file=%s idx=%i %p %p num=%i\n", lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
727 if (nIconIndex
==-1) /* Number of icons requested */
728 return ICO_ExtractIconEx(lpszFile
, NULL
, -1, 0, 0, 0 );
732 { ret
= ICO_ExtractIconEx(lpszFile
, phiconLarge
, nIconIndex
, nIcons
, 32, 32 );
734 { ret
= phiconLarge
[0];
738 /* if no pointers given and one icon expected, return the handle directly*/
739 if (!phiconLarge
&& ! phiconSmall
&& nIcons
==1 )
743 { ret
= ICO_ExtractIconEx(lpszFile
, phiconSmall
, nIconIndex
, nIcons
, 16, 16 );
745 { ret
= phiconSmall
[0];
751 /*************************************************************************
752 * ExtracticonEx32W [shell32.191]
754 HICON WINAPI
ExtractIconExW ( LPCWSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
758 TRACE(shell
,"file=%s idx=%i %p %p num=%i\n", debugstr_w(lpszFile
), nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
760 sFile
= HEAP_strdupWtoA (GetProcessHeap(),0,lpszFile
);
761 ret
= ExtractIconExA ( sFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
762 HeapFree(GetProcessHeap(),0,sFile
);