2 * shell icon cache (SIC)
4 * Copyright 1998, 1999 Juergen Schmied
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 #include <sys/types.h>
38 #include "wine/debug.h"
43 #include "shell32_main.h"
44 #include "undocshell.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
49 /********************** THE ICON CACHE ********************************/
51 #define INVALID_INDEX -1
55 LPWSTR sSourceFile
; /* file (not path!) containing the icon */
56 DWORD dwSourceIndex
; /* index within the file, if it is a resource ID it will be negated */
57 DWORD dwListIndex
; /* index within the iconlist */
58 DWORD dwFlags
; /* GIL_* flags */
60 } SIC_ENTRY
, * LPSIC_ENTRY
;
63 static INIT_ONCE sic_init_once
= INIT_ONCE_STATIC_INIT
;
64 static HIMAGELIST ShellSmallIconList
;
65 static HIMAGELIST ShellBigIconList
;
67 static CRITICAL_SECTION SHELL32_SicCS
;
68 static CRITICAL_SECTION_DEBUG critsect_debug
=
71 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
72 0, 0, { (DWORD_PTR
)(__FILE__
": SHELL32_SicCS") }
74 static CRITICAL_SECTION SHELL32_SicCS
= { &critsect_debug
, -1, 0, 0, 0, 0 };
77 static const WCHAR WindowMetrics
[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p','\\',
78 'W','i','n','d','o','w','M','e','t','r','i','c','s',0};
79 static const WCHAR ShellIconSize
[] = {'S','h','e','l','l',' ','I','c','o','n',' ','S','i','z','e',0};
81 #define SIC_COMPARE_LISTINDEX 1
83 /*****************************************************************************
87 * Callback for DPA_Search
89 static INT CALLBACK
SIC_CompareEntries( LPVOID p1
, LPVOID p2
, LPARAM lparam
)
91 LPSIC_ENTRY e1
= p1
, e2
= p2
;
93 TRACE("%p %p %8lx\n", p1
, p2
, lparam
);
95 /* Icons in the cache are keyed by the name of the file they are
96 * loaded from, their resource index and the fact if they have a shortcut
97 * icon overlay or not.
100 if (lparam
& SIC_COMPARE_LISTINDEX
)
101 return e1
->dwListIndex
!= e2
->dwListIndex
;
103 if (e1
->dwSourceIndex
!= e2
->dwSourceIndex
|| /* first the faster one */
104 (e1
->dwFlags
& GIL_FORSHORTCUT
) != (e2
->dwFlags
& GIL_FORSHORTCUT
))
107 if (strcmpiW(e1
->sSourceFile
,e2
->sSourceFile
))
113 /**************************************************************************************
116 * Returns the source file and resource index of an icon with the given imagelist index
118 HRESULT
SIC_get_location( int list_idx
, WCHAR
*file
, DWORD
*size
, int *res_idx
)
120 SIC_ENTRY seek
, *found
;
122 HRESULT hr
= E_INVALIDARG
;
125 seek
.dwListIndex
= list_idx
;
127 EnterCriticalSection( &SHELL32_SicCS
);
129 dpa_idx
= DPA_Search( sic_hdpa
, &seek
, 0, SIC_CompareEntries
, SIC_COMPARE_LISTINDEX
, 0 );
132 found
= (SIC_ENTRY
*)DPA_GetPtr( sic_hdpa
, dpa_idx
);
133 needed
= (strlenW( found
->sSourceFile
) + 1) * sizeof(WCHAR
);
136 memcpy( file
, found
->sSourceFile
, needed
);
137 *res_idx
= found
->dwSourceIndex
;
143 hr
= E_NOT_SUFFICIENT_BUFFER
;
146 LeaveCriticalSection( &SHELL32_SicCS
);
151 /* declare SIC_LoadOverlayIcon() */
152 static int SIC_LoadOverlayIcon(int icon_idx
);
154 /*****************************************************************************
155 * SIC_OverlayShortcutImage [internal]
158 * Creates a new icon as a copy of the passed-in icon, overlaid with a
161 static HICON
SIC_OverlayShortcutImage(HICON SourceIcon
, BOOL large
)
162 { ICONINFO SourceIconInfo
, ShortcutIconInfo
, TargetIconInfo
;
163 HICON ShortcutIcon
, TargetIcon
;
164 BITMAP SourceBitmapInfo
, ShortcutBitmapInfo
;
169 HBITMAP OldSourceBitmap
= NULL
,
170 OldShortcutBitmap
= NULL
,
171 OldTargetBitmap
= NULL
;
173 static int s_imgListIdx
= -1;
175 /* Get information about the source icon and shortcut overlay */
176 if (! GetIconInfo(SourceIcon
, &SourceIconInfo
)
177 || 0 == GetObjectW(SourceIconInfo
.hbmColor
, sizeof(BITMAP
), &SourceBitmapInfo
))
182 /* search for the shortcut icon only once */
183 if (s_imgListIdx
== -1)
184 s_imgListIdx
= SIC_LoadOverlayIcon(- IDI_SHELL_SHORTCUT
);
185 /* FIXME should use icon index 29 instead of the
186 resource id, but not all icons are present yet
187 so we can't use icon indices */
189 if (s_imgListIdx
!= -1)
192 ShortcutIcon
= ImageList_GetIcon(ShellBigIconList
, s_imgListIdx
, ILD_TRANSPARENT
);
194 ShortcutIcon
= ImageList_GetIcon(ShellSmallIconList
, s_imgListIdx
, ILD_TRANSPARENT
);
198 if (NULL
== ShortcutIcon
199 || ! GetIconInfo(ShortcutIcon
, &ShortcutIconInfo
)
200 || 0 == GetObjectW(ShortcutIconInfo
.hbmColor
, sizeof(BITMAP
), &ShortcutBitmapInfo
))
205 TargetIconInfo
= SourceIconInfo
;
206 TargetIconInfo
.hbmMask
= NULL
;
207 TargetIconInfo
.hbmColor
= NULL
;
209 /* Setup the source, shortcut and target masks */
210 SourceDC
= CreateCompatibleDC(NULL
);
211 if (NULL
== SourceDC
) goto fail
;
212 OldSourceBitmap
= SelectObject(SourceDC
, SourceIconInfo
.hbmMask
);
213 if (NULL
== OldSourceBitmap
) goto fail
;
215 ShortcutDC
= CreateCompatibleDC(NULL
);
216 if (NULL
== ShortcutDC
) goto fail
;
217 OldShortcutBitmap
= SelectObject(ShortcutDC
, ShortcutIconInfo
.hbmMask
);
218 if (NULL
== OldShortcutBitmap
) goto fail
;
220 TargetDC
= CreateCompatibleDC(NULL
);
221 if (NULL
== TargetDC
) goto fail
;
222 TargetIconInfo
.hbmMask
= CreateCompatibleBitmap(TargetDC
, SourceBitmapInfo
.bmWidth
,
223 SourceBitmapInfo
.bmHeight
);
224 if (NULL
== TargetIconInfo
.hbmMask
) goto fail
;
225 ScreenDC
= GetDC(NULL
);
226 if (NULL
== ScreenDC
) goto fail
;
227 TargetIconInfo
.hbmColor
= CreateCompatibleBitmap(ScreenDC
, SourceBitmapInfo
.bmWidth
,
228 SourceBitmapInfo
.bmHeight
);
229 ReleaseDC(NULL
, ScreenDC
);
230 if (NULL
== TargetIconInfo
.hbmColor
) goto fail
;
231 OldTargetBitmap
= SelectObject(TargetDC
, TargetIconInfo
.hbmMask
);
232 if (NULL
== OldTargetBitmap
) goto fail
;
234 /* Create the target mask by ANDing the source and shortcut masks */
235 if (! BitBlt(TargetDC
, 0, 0, SourceBitmapInfo
.bmWidth
, SourceBitmapInfo
.bmHeight
,
236 SourceDC
, 0, 0, SRCCOPY
) ||
237 ! BitBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
238 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
239 ShortcutDC
, 0, 0, SRCAND
))
244 /* Setup the source and target xor bitmap */
245 if (NULL
== SelectObject(SourceDC
, SourceIconInfo
.hbmColor
) ||
246 NULL
== SelectObject(TargetDC
, TargetIconInfo
.hbmColor
))
251 /* Copy the source xor bitmap to the target and clear out part of it by using
253 if (! BitBlt(TargetDC
, 0, 0, SourceBitmapInfo
.bmWidth
, SourceBitmapInfo
.bmHeight
,
254 SourceDC
, 0, 0, SRCCOPY
) ||
255 ! BitBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
256 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
257 ShortcutDC
, 0, 0, SRCAND
))
262 if (NULL
== SelectObject(ShortcutDC
, ShortcutIconInfo
.hbmColor
)) goto fail
;
264 /* Now put in the shortcut xor mask */
265 if (! BitBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
266 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
267 ShortcutDC
, 0, 0, SRCINVERT
))
272 /* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set
274 SelectObject(TargetDC
, OldTargetBitmap
);
275 DeleteObject(TargetDC
);
276 SelectObject(ShortcutDC
, OldShortcutBitmap
);
277 DeleteObject(ShortcutDC
);
278 SelectObject(SourceDC
, OldSourceBitmap
);
279 DeleteObject(SourceDC
);
281 /* Create the icon using the bitmaps prepared earlier */
282 TargetIcon
= CreateIconIndirect(&TargetIconInfo
);
284 /* CreateIconIndirect copies the bitmaps, so we can release our bitmaps now */
285 DeleteObject(TargetIconInfo
.hbmColor
);
286 DeleteObject(TargetIconInfo
.hbmMask
);
291 /* Clean up scratch resources we created */
292 if (NULL
!= OldTargetBitmap
) SelectObject(TargetDC
, OldTargetBitmap
);
293 if (NULL
!= TargetIconInfo
.hbmColor
) DeleteObject(TargetIconInfo
.hbmColor
);
294 if (NULL
!= TargetIconInfo
.hbmMask
) DeleteObject(TargetIconInfo
.hbmMask
);
295 if (NULL
!= TargetDC
) DeleteObject(TargetDC
);
296 if (NULL
!= OldShortcutBitmap
) SelectObject(ShortcutDC
, OldShortcutBitmap
);
297 if (NULL
!= ShortcutDC
) DeleteObject(ShortcutDC
);
298 if (NULL
!= OldSourceBitmap
) SelectObject(SourceDC
, OldSourceBitmap
);
299 if (NULL
!= SourceDC
) DeleteObject(SourceDC
);
304 /*****************************************************************************
305 * SIC_IconAppend [internal]
308 * appends an icon pair to the end of the cache
310 static INT
SIC_IconAppend (LPCWSTR sSourceFile
, INT dwSourceIndex
, HICON hSmallIcon
, HICON hBigIcon
, DWORD dwFlags
)
311 { LPSIC_ENTRY lpsice
;
312 INT ret
, index
, index1
;
313 WCHAR path
[MAX_PATH
];
314 TRACE("%s %i %p %p\n", debugstr_w(sSourceFile
), dwSourceIndex
, hSmallIcon
,hBigIcon
);
316 lpsice
= SHAlloc(sizeof(SIC_ENTRY
));
318 GetFullPathNameW(sSourceFile
, MAX_PATH
, path
, NULL
);
319 lpsice
->sSourceFile
= HeapAlloc( GetProcessHeap(), 0, (strlenW(path
)+1)*sizeof(WCHAR
) );
320 strcpyW( lpsice
->sSourceFile
, path
);
322 lpsice
->dwSourceIndex
= dwSourceIndex
;
323 lpsice
->dwFlags
= dwFlags
;
325 EnterCriticalSection(&SHELL32_SicCS
);
327 index
= DPA_InsertPtr(sic_hdpa
, 0x7fff, lpsice
);
328 if ( INVALID_INDEX
== index
)
330 HeapFree(GetProcessHeap(), 0, lpsice
->sSourceFile
);
336 index
= ImageList_AddIcon (ShellSmallIconList
, hSmallIcon
);
337 index1
= ImageList_AddIcon (ShellBigIconList
, hBigIcon
);
341 FIXME("iconlists out of sync 0x%x 0x%x\n", index
, index1
);
343 lpsice
->dwListIndex
= index
;
344 ret
= lpsice
->dwListIndex
;
347 LeaveCriticalSection(&SHELL32_SicCS
);
351 static BOOL
get_imagelist_icon_size(int list
, SIZE
*size
)
353 HIMAGELIST image_list
;
355 if (list
< SHIL_LARGE
|| list
> SHIL_SMALL
) return FALSE
;
356 image_list
= (list
== SHIL_LARGE
) ? ShellBigIconList
: ShellSmallIconList
;
358 return ImageList_GetIconSize( image_list
, &size
->cx
, &size
->cy
);
361 /****************************************************************************
362 * SIC_LoadIcon [internal]
365 * gets small/big icon by number from a file
367 static INT
SIC_LoadIcon (LPCWSTR sSourceFile
, INT dwSourceIndex
, DWORD dwFlags
)
371 HICON hiconLargeShortcut
;
372 HICON hiconSmallShortcut
;
376 get_imagelist_icon_size( SHIL_LARGE
, &size
);
377 PrivateExtractIconsW( sSourceFile
, dwSourceIndex
, size
.cx
, size
.cy
, &hiconLarge
, 0, 1, 0 );
378 get_imagelist_icon_size( SHIL_SMALL
, &size
);
379 PrivateExtractIconsW( sSourceFile
, dwSourceIndex
, size
.cx
, size
.cy
, &hiconSmall
, 0, 1, 0 );
381 if ( !hiconLarge
|| !hiconSmall
)
383 WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex
, debugstr_w(sSourceFile
), hiconLarge
, hiconSmall
);
387 if (0 != (dwFlags
& GIL_FORSHORTCUT
))
389 hiconLargeShortcut
= SIC_OverlayShortcutImage(hiconLarge
, TRUE
);
390 hiconSmallShortcut
= SIC_OverlayShortcutImage(hiconSmall
, FALSE
);
391 if (NULL
!= hiconLargeShortcut
&& NULL
!= hiconSmallShortcut
)
393 DestroyIcon( hiconLarge
);
394 DestroyIcon( hiconSmall
);
395 hiconLarge
= hiconLargeShortcut
;
396 hiconSmall
= hiconSmallShortcut
;
400 WARN("Failed to create shortcut overlaid icons\n");
401 if (NULL
!= hiconLargeShortcut
) DestroyIcon(hiconLargeShortcut
);
402 if (NULL
!= hiconSmallShortcut
) DestroyIcon(hiconSmallShortcut
);
403 dwFlags
&= ~ GIL_FORSHORTCUT
;
407 ret
= SIC_IconAppend( sSourceFile
, dwSourceIndex
, hiconSmall
, hiconLarge
, dwFlags
);
408 DestroyIcon( hiconLarge
);
409 DestroyIcon( hiconSmall
);
413 static int get_shell_icon_size(void)
416 DWORD value
= 32, size
= sizeof(buf
), type
;
419 if (!RegOpenKeyW( HKEY_CURRENT_USER
, WindowMetrics
, &key
))
421 if (!RegQueryValueExW( key
, ShellIconSize
, NULL
, &type
, (BYTE
*)buf
, &size
) && type
== REG_SZ
)
423 if (size
== sizeof(buf
)) buf
[size
/ sizeof(WCHAR
) - 1] = 0;
424 value
= atoiW( buf
);
431 /*****************************************************************************
432 * SIC_Initialize [internal]
434 static BOOL WINAPI
SIC_Initialize( INIT_ONCE
*once
, void *param
, void **context
)
437 int cx_small
, cy_small
;
438 int cx_large
, cy_large
;
440 if (!IsProcessDPIAware())
442 cx_large
= cy_large
= get_shell_icon_size();
443 cx_small
= GetSystemMetrics( SM_CXSMICON
);
444 cy_small
= GetSystemMetrics( SM_CYSMICON
);
448 cx_large
= GetSystemMetrics( SM_CXICON
);
449 cy_large
= GetSystemMetrics( SM_CYICON
);
450 cx_small
= cx_large
/ 2;
451 cy_small
= cy_large
/ 2;
454 TRACE("large %dx%d small %dx%d\n", cx_large
, cy_large
, cx_small
, cx_small
);
456 sic_hdpa
= DPA_Create(16);
463 ShellSmallIconList
= ImageList_Create(cx_small
,cy_small
,ILC_COLOR32
|ILC_MASK
,0,0x20);
464 ShellBigIconList
= ImageList_Create(cx_large
,cy_large
,ILC_COLOR32
|ILC_MASK
,0,0x20);
466 ImageList_SetBkColor(ShellSmallIconList
, CLR_NONE
);
467 ImageList_SetBkColor(ShellBigIconList
, CLR_NONE
);
469 /* Load the document icon, which is used as the default if an icon isn't found. */
470 hSm
= LoadImageA(shell32_hInstance
, MAKEINTRESOURCEA(IDI_SHELL_DOCUMENT
),
471 IMAGE_ICON
, cx_small
, cy_small
, LR_SHARED
);
472 hLg
= LoadImageA(shell32_hInstance
, MAKEINTRESOURCEA(IDI_SHELL_DOCUMENT
),
473 IMAGE_ICON
, cx_large
, cy_large
, LR_SHARED
);
477 FIXME("Failed to load IDI_SHELL_DOCUMENT icon!\n");
481 SIC_IconAppend (swShell32Name
, IDI_SHELL_DOCUMENT
-1, hSm
, hLg
, 0);
482 SIC_IconAppend (swShell32Name
, -IDI_SHELL_DOCUMENT
, hSm
, hLg
, 0);
484 TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList
, ShellBigIconList
);
488 /*************************************************************************
493 static INT CALLBACK
sic_free( LPVOID ptr
, LPVOID lparam
)
495 HeapFree(GetProcessHeap(), 0, ((LPSIC_ENTRY
)ptr
)->sSourceFile
);
500 void SIC_Destroy(void)
504 EnterCriticalSection(&SHELL32_SicCS
);
506 if (sic_hdpa
) DPA_DestroyCallback(sic_hdpa
, sic_free
, NULL
);
508 if (ShellSmallIconList
)
509 ImageList_Destroy(ShellSmallIconList
);
510 if (ShellBigIconList
)
511 ImageList_Destroy(ShellBigIconList
);
513 LeaveCriticalSection(&SHELL32_SicCS
);
514 DeleteCriticalSection(&SHELL32_SicCS
);
517 /*****************************************************************************
518 * SIC_GetIconIndex [internal]
521 * sSourceFile [IN] filename of file containing the icon
522 * index [IN] index/resID (negated) in this file
525 * look in the cache for a proper icon. if not available the icon is taken
526 * from the file and cached
528 INT
SIC_GetIconIndex (LPCWSTR sSourceFile
, INT dwSourceIndex
, DWORD dwFlags
)
531 INT ret
, index
= INVALID_INDEX
;
532 WCHAR path
[MAX_PATH
];
534 TRACE("%s %i\n", debugstr_w(sSourceFile
), dwSourceIndex
);
536 GetFullPathNameW(sSourceFile
, MAX_PATH
, path
, NULL
);
537 sice
.sSourceFile
= path
;
538 sice
.dwSourceIndex
= dwSourceIndex
;
539 sice
.dwFlags
= dwFlags
;
541 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
543 EnterCriticalSection(&SHELL32_SicCS
);
545 if (NULL
!= DPA_GetPtr (sic_hdpa
, 0))
547 /* search linear from position 0*/
548 index
= DPA_Search (sic_hdpa
, &sice
, 0, SIC_CompareEntries
, 0, 0);
551 if ( INVALID_INDEX
== index
)
553 ret
= SIC_LoadIcon (sSourceFile
, dwSourceIndex
, dwFlags
);
558 ret
= ((LPSIC_ENTRY
)DPA_GetPtr(sic_hdpa
, index
))->dwListIndex
;
561 LeaveCriticalSection(&SHELL32_SicCS
);
565 /*****************************************************************************
566 * SIC_LoadOverlayIcon [internal]
568 * Load a shell overlay icon and return its icon cache index.
570 static int SIC_LoadOverlayIcon(int icon_idx
)
572 WCHAR buffer
[1024], wszIdx
[8];
577 static const WCHAR wszShellIcons
[] = {
578 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
579 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
580 'E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','I','c','o','n','s',0
582 static const WCHAR wszNumFmt
[] = {'%','d',0};
584 iconPath
= swShell32Name
; /* default: load icon from shell32.dll */
587 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, wszShellIcons
, 0, KEY_READ
, &hKeyShellIcons
) == ERROR_SUCCESS
)
589 DWORD count
= sizeof(buffer
);
591 sprintfW(wszIdx
, wszNumFmt
, icon_idx
);
593 /* read icon path and index */
594 if (RegQueryValueExW(hKeyShellIcons
, wszIdx
, NULL
, NULL
, (LPBYTE
)buffer
, &count
) == ERROR_SUCCESS
)
596 LPWSTR p
= strchrW(buffer
, ',');
600 ERR("Icon index in %s/%s corrupted, no comma.\n", debugstr_w(wszShellIcons
),debugstr_w(wszIdx
));
601 RegCloseKey(hKeyShellIcons
);
609 RegCloseKey(hKeyShellIcons
);
612 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
614 return SIC_LoadIcon(iconPath
, iconIdx
, 0);
617 /*************************************************************************
618 * Shell_GetImageLists [SHELL32.71]
621 * imglist[1|2] [OUT] pointer which receives imagelist handles
624 BOOL WINAPI
Shell_GetImageLists(HIMAGELIST
* lpBigList
, HIMAGELIST
* lpSmallList
)
626 TRACE("(%p,%p)\n",lpBigList
,lpSmallList
);
627 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
628 if (lpBigList
) *lpBigList
= ShellBigIconList
;
629 if (lpSmallList
) *lpSmallList
= ShellSmallIconList
;
632 /*************************************************************************
633 * PidlToSicIndex [INTERNAL]
636 * sh [IN] IShellFolder
640 * pIndex [OUT] index within the SIC
643 BOOL
PidlToSicIndex (
651 WCHAR szIconFile
[MAX_PATH
]; /* file containing the icon */
652 INT iSourceIndex
; /* index or resID(negated) in this file */
655 int iShortcutDefaultIndex
= INVALID_INDEX
;
657 TRACE("sf=%p pidl=%p %s\n", sh
, pidl
, bBigIcon
?"Big":"Small");
659 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
661 if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh
, 0, 1, &pidl
, &IID_IExtractIconW
, 0, (void **)&ei
)))
663 if (SUCCEEDED(IExtractIconW_GetIconLocation(ei
, uFlags
, szIconFile
, MAX_PATH
, &iSourceIndex
, &dwFlags
)))
665 *pIndex
= SIC_GetIconIndex(szIconFile
, iSourceIndex
, uFlags
);
668 IExtractIconW_Release(ei
);
671 if (INVALID_INDEX
== *pIndex
) /* default icon when failed */
673 if (0 == (uFlags
& GIL_FORSHORTCUT
))
679 if (INVALID_INDEX
== iShortcutDefaultIndex
)
681 iShortcutDefaultIndex
= SIC_LoadIcon(swShell32Name
, 0, GIL_FORSHORTCUT
);
683 *pIndex
= (INVALID_INDEX
!= iShortcutDefaultIndex
? iShortcutDefaultIndex
: 0);
691 /*************************************************************************
692 * SHMapPIDLToSystemImageListIndex [SHELL32.77]
695 * sh [IN] pointer to an instance of IShellFolder
697 * pIndex [OUT][OPTIONAL] SIC index for big icon
700 int WINAPI
SHMapPIDLToSystemImageListIndex(
708 TRACE("(SF=%p,pidl=%p,%p)\n",sh
,pidl
,pIndex
);
711 if (SHELL_IsShortcut(pidl
))
712 uGilFlags
|= GIL_FORSHORTCUT
;
715 if (!PidlToSicIndex ( sh
, pidl
, 1, uGilFlags
, pIndex
))
718 if (!PidlToSicIndex ( sh
, pidl
, 0, uGilFlags
, &Index
))
724 /*************************************************************************
725 * SHMapIDListToImageListIndexAsync [SHELL32.148]
727 HRESULT WINAPI
SHMapIDListToImageListIndexAsync(IUnknown
*pts
, IShellFolder
*psf
,
728 LPCITEMIDLIST pidl
, UINT flags
,
729 void *pfn
, void *pvData
, void *pvHint
,
730 int *piIndex
, int *piIndexSel
)
732 FIXME("(%p, %p, %p, 0x%08x, %p, %p, %p, %p, %p)\n",
733 pts
, psf
, pidl
, flags
, pfn
, pvData
, pvHint
, piIndex
, piIndexSel
);
737 /*************************************************************************
738 * Shell_GetCachedImageIndex [SHELL32.72]
741 static INT
Shell_GetCachedImageIndexA(LPCSTR szPath
, INT nIndex
, BOOL bSimulateDoc
)
746 WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath
), nIndex
, bSimulateDoc
);
748 len
= MultiByteToWideChar( CP_ACP
, 0, szPath
, -1, NULL
, 0 );
749 szTemp
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
750 MultiByteToWideChar( CP_ACP
, 0, szPath
, -1, szTemp
, len
);
752 ret
= SIC_GetIconIndex( szTemp
, nIndex
, 0 );
754 HeapFree( GetProcessHeap(), 0, szTemp
);
759 static INT
Shell_GetCachedImageIndexW(LPCWSTR szPath
, INT nIndex
, BOOL bSimulateDoc
)
761 WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath
), nIndex
, bSimulateDoc
);
763 return SIC_GetIconIndex(szPath
, nIndex
, 0);
766 INT WINAPI
Shell_GetCachedImageIndexAW(LPCVOID szPath
, INT nIndex
, BOOL bSimulateDoc
)
767 { if( SHELL_OsIsUnicode())
768 return Shell_GetCachedImageIndexW(szPath
, nIndex
, bSimulateDoc
);
769 return Shell_GetCachedImageIndexA(szPath
, nIndex
, bSimulateDoc
);
772 /*************************************************************************
773 * ExtractIconExW [SHELL32.@]
776 * -1 file is not valid
777 * or number of icons extracted
779 UINT WINAPI
ExtractIconExW(LPCWSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
781 TRACE("%s %i %p %p %i\n", debugstr_w(lpszFile
), nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
783 return PrivateExtractIconExW(lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
786 /*************************************************************************
787 * ExtractIconExA [SHELL32.@]
789 UINT WINAPI
ExtractIconExA(LPCSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
792 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, NULL
, 0);
793 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
795 TRACE("%s %i %p %p %i\n", lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
799 MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, lpwstrFile
, len
);
800 ret
= ExtractIconExW(lpwstrFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
801 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
806 /*************************************************************************
807 * ExtractAssociatedIconA (SHELL32.@)
809 * Return icon for given file (either from file itself or from associated
810 * executable) and patch parameters if needed.
812 HICON WINAPI
ExtractAssociatedIconA(HINSTANCE hInst
, LPSTR lpIconPath
, LPWORD lpiIcon
)
815 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpIconPath
, -1, NULL
, 0);
816 /* Note that we need to allocate MAX_PATH, since we are supposed to fill
817 * the correct executable if there is no icon in lpIconPath directly.
818 * lpIconPath itself is supposed to be large enough, so make sure lpIconPathW
819 * is large enough too. Yes, I am puking too.
821 LPWSTR lpIconPathW
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
823 TRACE("%p %s %p\n", hInst
, debugstr_a(lpIconPath
), lpiIcon
);
827 MultiByteToWideChar(CP_ACP
, 0, lpIconPath
, -1, lpIconPathW
, len
);
828 hIcon
= ExtractAssociatedIconW(hInst
, lpIconPathW
, lpiIcon
);
829 WideCharToMultiByte(CP_ACP
, 0, lpIconPathW
, -1, lpIconPath
, MAX_PATH
, NULL
, NULL
);
830 HeapFree(GetProcessHeap(), 0, lpIconPathW
);
835 /*************************************************************************
836 * ExtractAssociatedIconW (SHELL32.@)
838 * Return icon for given file (either from file itself or from associated
839 * executable) and patch parameters if needed.
841 HICON WINAPI
ExtractAssociatedIconW(HINSTANCE hInst
, LPWSTR lpIconPath
, LPWORD lpiIcon
)
846 TRACE("%p %s %p\n", hInst
, debugstr_w(lpIconPath
), lpiIcon
);
849 lpiIcon
= &wDummyIcon
;
851 hIcon
= ExtractIconW(hInst
, lpIconPath
, *lpiIcon
);
853 if( hIcon
< (HICON
)2 )
854 { if( hIcon
== (HICON
)1 ) /* no icons found in given file */
855 { WCHAR tempPath
[MAX_PATH
];
856 HINSTANCE uRet
= FindExecutableW(lpIconPath
,NULL
,tempPath
);
858 if( uRet
> (HINSTANCE
)32 && tempPath
[0] )
859 { lstrcpyW(lpIconPath
,tempPath
);
860 hIcon
= ExtractIconW(hInst
, lpIconPath
, *lpiIcon
);
861 if( hIcon
> (HICON
)2 )
866 if( hIcon
== (HICON
)1 )
867 *lpiIcon
= 2; /* MSDOS icon - we found .exe but no icons in it */
869 *lpiIcon
= 6; /* generic icon - found nothing */
871 if (GetModuleFileNameW(hInst
, lpIconPath
, MAX_PATH
))
872 hIcon
= LoadIconW(hInst
, MAKEINTRESOURCEW(*lpiIcon
));
877 /*************************************************************************
878 * ExtractAssociatedIconExW (SHELL32.@)
880 * Return icon for given file (either from file itself or from associated
881 * executable) and patch parameters if needed.
883 HICON WINAPI
ExtractAssociatedIconExW(HINSTANCE hInst
, LPWSTR lpIconPath
, LPWORD lpiIconIdx
, LPWORD lpiIconId
)
885 FIXME("%p %s %p %p): stub\n", hInst
, debugstr_w(lpIconPath
), lpiIconIdx
, lpiIconId
);
889 /*************************************************************************
890 * ExtractAssociatedIconExA (SHELL32.@)
892 * Return icon for given file (either from file itself or from associated
893 * executable) and patch parameters if needed.
895 HICON WINAPI
ExtractAssociatedIconExA(HINSTANCE hInst
, LPSTR lpIconPath
, LPWORD lpiIconIdx
, LPWORD lpiIconId
)
898 INT len
= MultiByteToWideChar( CP_ACP
, 0, lpIconPath
, -1, NULL
, 0 );
899 LPWSTR lpwstrFile
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
901 TRACE("%p %s %p %p)\n", hInst
, lpIconPath
, lpiIconIdx
, lpiIconId
);
903 MultiByteToWideChar( CP_ACP
, 0, lpIconPath
, -1, lpwstrFile
, len
);
904 ret
= ExtractAssociatedIconExW(hInst
, lpwstrFile
, lpiIconIdx
, lpiIconId
);
905 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
910 /****************************************************************************
911 * SHDefExtractIconW [SHELL32.@]
913 HRESULT WINAPI
SHDefExtractIconW(LPCWSTR pszIconFile
, int iIndex
, UINT uFlags
,
914 HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIconSize
)
918 WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile
), iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
920 ret
= PrivateExtractIconsW(pszIconFile
, iIndex
, nIconSize
, nIconSize
, hIcons
, NULL
, 2, LR_DEFAULTCOLOR
);
921 /* FIXME: deal with uFlags parameter which contains GIL_ flags */
922 if (ret
== 0xFFFFFFFF)
926 *phiconLarge
= hIcons
[0];
928 DestroyIcon(hIcons
[0]);
930 *phiconSmall
= hIcons
[1];
932 DestroyIcon(hIcons
[1]);
938 /****************************************************************************
939 * SHDefExtractIconA [SHELL32.@]
941 HRESULT WINAPI
SHDefExtractIconA(LPCSTR pszIconFile
, int iIndex
, UINT uFlags
,
942 HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIconSize
)
945 INT len
= MultiByteToWideChar(CP_ACP
, 0, pszIconFile
, -1, NULL
, 0);
946 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
948 TRACE("%s %d 0x%08x %p %p %d\n", pszIconFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
950 MultiByteToWideChar(CP_ACP
, 0, pszIconFile
, -1, lpwstrFile
, len
);
951 ret
= SHDefExtractIconW(lpwstrFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
952 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
957 /****************************************************************************
958 * SHGetIconOverlayIndexA [SHELL32.@]
960 * Returns the index of the overlay icon in the system image list.
962 INT WINAPI
SHGetIconOverlayIndexA(LPCSTR pszIconPath
, INT iIconIndex
)
964 FIXME("%s, %d\n", debugstr_a(pszIconPath
), iIconIndex
);
969 /****************************************************************************
970 * SHGetIconOverlayIndexW [SHELL32.@]
972 * Returns the index of the overlay icon in the system image list.
974 INT WINAPI
SHGetIconOverlayIndexW(LPCWSTR pszIconPath
, INT iIconIndex
)
976 FIXME("%s, %d\n", debugstr_w(pszIconPath
), iIconIndex
);
981 /****************************************************************************
982 * SHGetStockIconInfo [SHELL32.@]
984 * Receive information for builtin icons
987 * id [I] selected icon-id to get information for
988 * flags [I] selects the information to receive
989 * sii [IO] SHSTOCKICONINFO structure to fill
993 * Failure: A HRESULT failure code
996 HRESULT WINAPI
SHGetStockIconInfo(SHSTOCKICONID id
, UINT flags
, SHSTOCKICONINFO
*sii
)
998 static const WCHAR shell32dll
[] = {'\\','s','h','e','l','l','3','2','.','d','l','l',0};
1000 FIXME("(%d, 0x%x, %p) semi-stub\n", id
, flags
, sii
);
1001 if ((id
< 0) || (id
>= SIID_MAX_ICONS
) || !sii
|| (sii
->cbSize
!= sizeof(SHSTOCKICONINFO
))) {
1002 return E_INVALIDARG
;
1005 GetSystemDirectoryW(sii
->szPath
, MAX_PATH
);
1007 /* no icons defined: use default */
1008 sii
->iIcon
= -IDI_SHELL_DOCUMENT
;
1009 lstrcatW(sii
->szPath
, shell32dll
);
1012 FIXME("flags 0x%x not implemented\n", flags
);
1015 sii
->iSysImageIndex
= -1;
1017 TRACE("%3d: returning %s (%d)\n", id
, debugstr_w(sii
->szPath
), sii
->iIcon
);