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
23 #include <sys/types.h>
32 #include "wine/debug.h"
37 #include "shell32_main.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
42 /********************** THE ICON CACHE ********************************/
44 #define INVALID_INDEX -1
48 LPWSTR sSourceFile
; /* file (not path!) containing the icon */
49 DWORD dwSourceIndex
; /* index within the file, if it is a resource ID it will be negated */
50 DWORD dwListIndex
; /* index within the iconlist */
51 DWORD dwFlags
; /* GIL_* flags */
53 } SIC_ENTRY
, * LPSIC_ENTRY
;
56 static INIT_ONCE sic_init_once
= INIT_ONCE_STATIC_INIT
;
57 static HIMAGELIST shell_imagelists
[SHIL_LAST
+1];
59 static CRITICAL_SECTION SHELL32_SicCS
;
60 static CRITICAL_SECTION_DEBUG critsect_debug
=
63 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
64 0, 0, { (DWORD_PTR
)(__FILE__
": SHELL32_SicCS") }
66 static CRITICAL_SECTION SHELL32_SicCS
= { &critsect_debug
, -1, 0, 0, 0, 0 };
69 #define SIC_COMPARE_LISTINDEX 1
71 /*****************************************************************************
75 * Callback for DPA_Search
77 static INT CALLBACK
SIC_CompareEntries( LPVOID p1
, LPVOID p2
, LPARAM lparam
)
79 LPSIC_ENTRY e1
= p1
, e2
= p2
;
81 TRACE("%p %p %8Ix\n", p1
, p2
, lparam
);
83 /* Icons in the cache are keyed by the name of the file they are
84 * loaded from, their resource index and the fact if they have a shortcut
85 * icon overlay or not.
88 if (lparam
& SIC_COMPARE_LISTINDEX
)
89 return e1
->dwListIndex
!= e2
->dwListIndex
;
91 if (e1
->dwSourceIndex
!= e2
->dwSourceIndex
|| /* first the faster one */
92 (e1
->dwFlags
& GIL_FORSHORTCUT
) != (e2
->dwFlags
& GIL_FORSHORTCUT
))
95 if (wcsicmp(e1
->sSourceFile
,e2
->sSourceFile
))
101 /**************************************************************************************
104 * Returns the source file and resource index of an icon with the given imagelist index
106 HRESULT
SIC_get_location( int list_idx
, WCHAR
*file
, DWORD
*size
, int *res_idx
)
108 SIC_ENTRY seek
, *found
;
110 HRESULT hr
= E_INVALIDARG
;
113 seek
.dwListIndex
= list_idx
;
115 EnterCriticalSection( &SHELL32_SicCS
);
117 dpa_idx
= DPA_Search( sic_hdpa
, &seek
, 0, SIC_CompareEntries
, SIC_COMPARE_LISTINDEX
, 0 );
120 found
= DPA_GetPtr( sic_hdpa
, dpa_idx
);
121 needed
= (lstrlenW( found
->sSourceFile
) + 1) * sizeof(WCHAR
);
124 memcpy( file
, found
->sSourceFile
, needed
);
125 *res_idx
= found
->dwSourceIndex
;
131 hr
= E_NOT_SUFFICIENT_BUFFER
;
134 LeaveCriticalSection( &SHELL32_SicCS
);
139 /* declare SIC_LoadOverlayIcon() */
140 static int SIC_LoadOverlayIcon(int icon_idx
);
142 /*****************************************************************************
143 * SIC_OverlayShortcutImage [internal]
146 * Creates a new icon as a copy of the passed-in icon, overlaid with a
149 static HICON
SIC_OverlayShortcutImage(HICON SourceIcon
, int type
)
151 ICONINFO SourceIconInfo
, ShortcutIconInfo
, TargetIconInfo
;
152 HICON ShortcutIcon
, TargetIcon
;
153 BITMAP SourceBitmapInfo
, ShortcutBitmapInfo
;
158 HBITMAP OldSourceBitmap
= NULL
,
159 OldShortcutBitmap
= NULL
,
160 OldTargetBitmap
= NULL
;
162 static int s_imgListIdx
= -1;
164 /* Get information about the source icon and shortcut overlay */
165 if (! GetIconInfo(SourceIcon
, &SourceIconInfo
)
166 || 0 == GetObjectW(SourceIconInfo
.hbmColor
, sizeof(BITMAP
), &SourceBitmapInfo
))
171 /* search for the shortcut icon only once */
172 if (s_imgListIdx
== -1)
173 s_imgListIdx
= SIC_LoadOverlayIcon(- IDI_SHELL_SHORTCUT
);
174 /* FIXME should use icon index 29 instead of the
175 resource id, but not all icons are present yet
176 so we can't use icon indices */
178 if (s_imgListIdx
!= -1)
179 ShortcutIcon
= ImageList_GetIcon(shell_imagelists
[type
], s_imgListIdx
, ILD_TRANSPARENT
);
183 if (NULL
== ShortcutIcon
|| ! GetIconInfo(ShortcutIcon
, &ShortcutIconInfo
)
184 || 0 == GetObjectW(ShortcutIconInfo
.hbmColor
, sizeof(BITMAP
), &ShortcutBitmapInfo
))
189 TargetIconInfo
= SourceIconInfo
;
190 TargetIconInfo
.hbmMask
= NULL
;
191 TargetIconInfo
.hbmColor
= NULL
;
193 /* Setup the source, shortcut and target masks */
194 SourceDC
= CreateCompatibleDC(NULL
);
195 if (NULL
== SourceDC
) goto fail
;
196 OldSourceBitmap
= SelectObject(SourceDC
, SourceIconInfo
.hbmMask
);
197 if (NULL
== OldSourceBitmap
) goto fail
;
199 ShortcutDC
= CreateCompatibleDC(NULL
);
200 if (NULL
== ShortcutDC
) goto fail
;
201 OldShortcutBitmap
= SelectObject(ShortcutDC
, ShortcutIconInfo
.hbmMask
);
202 if (NULL
== OldShortcutBitmap
) goto fail
;
204 TargetDC
= CreateCompatibleDC(NULL
);
205 if (NULL
== TargetDC
) goto fail
;
206 TargetIconInfo
.hbmMask
= CreateCompatibleBitmap(TargetDC
, SourceBitmapInfo
.bmWidth
,
207 SourceBitmapInfo
.bmHeight
);
208 if (NULL
== TargetIconInfo
.hbmMask
) goto fail
;
209 ScreenDC
= GetDC(NULL
);
210 if (NULL
== ScreenDC
) goto fail
;
211 TargetIconInfo
.hbmColor
= CreateCompatibleBitmap(ScreenDC
, SourceBitmapInfo
.bmWidth
,
212 SourceBitmapInfo
.bmHeight
);
213 ReleaseDC(NULL
, ScreenDC
);
214 if (NULL
== TargetIconInfo
.hbmColor
) goto fail
;
215 OldTargetBitmap
= SelectObject(TargetDC
, TargetIconInfo
.hbmMask
);
216 if (NULL
== OldTargetBitmap
) goto fail
;
218 /* Create the target mask by ANDing the source and shortcut masks */
219 if (! BitBlt(TargetDC
, 0, 0, SourceBitmapInfo
.bmWidth
, SourceBitmapInfo
.bmHeight
,
220 SourceDC
, 0, 0, SRCCOPY
) ||
221 ! BitBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
222 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
223 ShortcutDC
, 0, 0, SRCAND
))
228 /* Setup the source and target xor bitmap */
229 if (NULL
== SelectObject(SourceDC
, SourceIconInfo
.hbmColor
) ||
230 NULL
== SelectObject(TargetDC
, TargetIconInfo
.hbmColor
))
235 /* Copy the source xor bitmap to the target and clear out part of it by using
237 if (! BitBlt(TargetDC
, 0, 0, SourceBitmapInfo
.bmWidth
, SourceBitmapInfo
.bmHeight
,
238 SourceDC
, 0, 0, SRCCOPY
) ||
239 ! BitBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
240 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
241 ShortcutDC
, 0, 0, SRCAND
))
246 if (NULL
== SelectObject(ShortcutDC
, ShortcutIconInfo
.hbmColor
)) goto fail
;
248 /* Now put in the shortcut xor mask */
249 if (! BitBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
250 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
251 ShortcutDC
, 0, 0, SRCINVERT
))
256 /* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set
258 SelectObject(TargetDC
, OldTargetBitmap
);
259 DeleteObject(TargetDC
);
260 SelectObject(ShortcutDC
, OldShortcutBitmap
);
261 DeleteObject(ShortcutDC
);
262 SelectObject(SourceDC
, OldSourceBitmap
);
263 DeleteObject(SourceDC
);
265 /* Create the icon using the bitmaps prepared earlier */
266 TargetIcon
= CreateIconIndirect(&TargetIconInfo
);
268 /* CreateIconIndirect copies the bitmaps, so we can release our bitmaps now */
269 DeleteObject(TargetIconInfo
.hbmColor
);
270 DeleteObject(TargetIconInfo
.hbmMask
);
275 /* Clean up scratch resources we created */
276 if (NULL
!= OldTargetBitmap
) SelectObject(TargetDC
, OldTargetBitmap
);
277 if (NULL
!= TargetIconInfo
.hbmColor
) DeleteObject(TargetIconInfo
.hbmColor
);
278 if (NULL
!= TargetIconInfo
.hbmMask
) DeleteObject(TargetIconInfo
.hbmMask
);
279 if (NULL
!= TargetDC
) DeleteObject(TargetDC
);
280 if (NULL
!= OldShortcutBitmap
) SelectObject(ShortcutDC
, OldShortcutBitmap
);
281 if (NULL
!= ShortcutDC
) DeleteObject(ShortcutDC
);
282 if (NULL
!= OldSourceBitmap
) SelectObject(SourceDC
, OldSourceBitmap
);
283 if (NULL
!= SourceDC
) DeleteObject(SourceDC
);
288 /*****************************************************************************
289 * SIC_IconAppend [internal]
291 static INT
SIC_IconAppend (const WCHAR
*sourcefile
, INT src_index
, HICON
*hicons
, DWORD flags
)
293 INT ret
, index
, index1
;
294 WCHAR path
[MAX_PATH
];
298 TRACE("%s %i %p %#lx\n", debugstr_w(sourcefile
), src_index
, hicons
, flags
);
300 entry
= SHAlloc(sizeof(*entry
));
302 GetFullPathNameW(sourcefile
, MAX_PATH
, path
, NULL
);
303 entry
->sSourceFile
= heap_alloc( (lstrlenW(path
)+1)*sizeof(WCHAR
) );
304 lstrcpyW( entry
->sSourceFile
, path
);
306 entry
->dwSourceIndex
= src_index
;
307 entry
->dwFlags
= flags
;
309 EnterCriticalSection(&SHELL32_SicCS
);
311 index
= DPA_InsertPtr(sic_hdpa
, 0x7fff, entry
);
312 if ( INVALID_INDEX
== index
)
314 heap_free(entry
->sSourceFile
);
321 for (i
= 0; i
< ARRAY_SIZE(shell_imagelists
); i
++)
323 index1
= ImageList_AddIcon(shell_imagelists
[i
], hicons
[i
]);
324 if (index
!= -1 && index1
!= index
)
325 WARN("Imagelists out of sync, list %d.\n", i
);
329 entry
->dwListIndex
= index
;
330 ret
= entry
->dwListIndex
;
333 LeaveCriticalSection(&SHELL32_SicCS
);
337 static BOOL
get_imagelist_icon_size(int list
, SIZE
*size
)
340 if (list
< 0 || list
>= ARRAY_SIZE(shell_imagelists
)) return FALSE
;
342 if (!ImageList_GetIconSize( shell_imagelists
[list
], &cx
, &cy
)) return FALSE
;
348 /****************************************************************************
349 * SIC_LoadIcon [internal]
352 * gets icons by index from the file
354 static INT
SIC_LoadIcon (const WCHAR
*sourcefile
, INT index
, DWORD flags
)
356 HICON hicons
[ARRAY_SIZE(shell_imagelists
)] = { 0 };
357 HICON hshortcuts
[ARRAY_SIZE(hicons
)] = { 0 };
362 for (i
= 0; i
< ARRAY_SIZE(hicons
); i
++)
364 if (!get_imagelist_icon_size( i
, &size
) ||
365 !PrivateExtractIconsW( sourcefile
, index
, size
.cx
, size
.cy
, &hicons
[i
], 0, 1, 0 ))
366 WARN("Failed to load icon %d from %s.\n", index
, debugstr_w(sourcefile
));
367 if (!hicons
[i
]) goto fail
;
370 if (flags
& GIL_FORSHORTCUT
)
374 for (i
= 0; i
< ARRAY_SIZE(hshortcuts
); i
++)
376 if (!(hshortcuts
[i
] = SIC_OverlayShortcutImage(hicons
[i
], i
)))
378 WARN("Failed to create shortcut overlaid icons.\n");
385 for (i
= 0; i
< ARRAY_SIZE(hshortcuts
); i
++)
386 DestroyIcon(hshortcuts
[i
]);
387 flags
&= ~GIL_FORSHORTCUT
;
391 for (i
= 0; i
< ARRAY_SIZE(hicons
); i
++)
393 DestroyIcon(hicons
[i
]);
394 hicons
[i
] = hshortcuts
[i
];
399 ret
= SIC_IconAppend( sourcefile
, index
, hicons
, flags
);
402 for (i
= 0; i
< ARRAY_SIZE(hicons
); i
++)
403 DestroyIcon(hicons
[i
]);
407 static int get_shell_icon_size(void)
410 DWORD value
= 32, size
= sizeof(buf
), type
;
413 if (!RegOpenKeyW( HKEY_CURRENT_USER
, L
"Control Panel\\Desktop\\WindowMetrics", &key
))
415 if (!RegQueryValueExW( key
, L
"Shell Icon Size", NULL
, &type
, (BYTE
*)buf
, &size
) && type
== REG_SZ
)
417 if (size
== sizeof(buf
)) buf
[size
/ sizeof(WCHAR
) - 1] = 0;
418 value
= wcstol( buf
, NULL
, 10 );
425 /*****************************************************************************
426 * SIC_Initialize [internal]
428 static BOOL WINAPI
SIC_Initialize( INIT_ONCE
*once
, void *param
, void **context
)
430 HICON hicons
[ARRAY_SIZE(shell_imagelists
)];
431 SIZE sizes
[ARRAY_SIZE(shell_imagelists
)];
435 if (!IsProcessDPIAware())
437 sizes
[SHIL_LARGE
].cx
= sizes
[SHIL_LARGE
].cy
= get_shell_icon_size();
438 sizes
[SHIL_SMALL
].cx
= GetSystemMetrics( SM_CXSMICON
);
439 sizes
[SHIL_SMALL
].cy
= GetSystemMetrics( SM_CYSMICON
);
443 sizes
[SHIL_LARGE
].cx
= GetSystemMetrics( SM_CXICON
);
444 sizes
[SHIL_LARGE
].cy
= GetSystemMetrics( SM_CYICON
);
445 sizes
[SHIL_SMALL
].cx
= sizes
[SHIL_LARGE
].cx
/ 2;
446 sizes
[SHIL_SMALL
].cy
= sizes
[SHIL_LARGE
].cy
/ 2;
449 sizes
[SHIL_EXTRALARGE
].cx
= (GetSystemMetrics( SM_CXICON
) * 3) / 2;
450 sizes
[SHIL_EXTRALARGE
].cy
= (GetSystemMetrics( SM_CYICON
) * 3) / 2;
451 sizes
[SHIL_SYSSMALL
].cx
= GetSystemMetrics( SM_CXSMICON
);
452 sizes
[SHIL_SYSSMALL
].cy
= GetSystemMetrics( SM_CYSMICON
);
453 sizes
[SHIL_JUMBO
].cx
= sizes
[SHIL_JUMBO
].cy
= 256;
455 TRACE("large %ldx%ld small %ldx%ld\n", sizes
[SHIL_LARGE
].cx
, sizes
[SHIL_LARGE
].cy
, sizes
[SHIL_SMALL
].cx
, sizes
[SHIL_SMALL
].cy
);
457 sic_hdpa
= DPA_Create(16);
461 for (i
= 0; i
< ARRAY_SIZE(shell_imagelists
); i
++)
463 shell_imagelists
[i
] = ImageList_Create(sizes
[i
].cx
, sizes
[i
].cy
, ILC_COLOR32
| ILC_MASK
, 0, 0x20);
464 ImageList_SetBkColor(shell_imagelists
[i
], CLR_NONE
);
466 /* Load the generic file icon, which is used as the default if an icon isn't found. */
467 if (!(hicons
[i
] = LoadImageA(shell32_hInstance
, MAKEINTRESOURCEA(IDI_SHELL_FILE
),
468 IMAGE_ICON
, sizes
[i
].cx
, sizes
[i
].cy
, LR_SHARED
)))
476 FIXME("Failed to load IDI_SHELL_FILE icon!\n");
480 SIC_IconAppend(swShell32Name
, IDI_SHELL_FILE
- 1, hicons
, 0);
481 SIC_IconAppend(swShell32Name
, -IDI_SHELL_FILE
, hicons
, 0);
483 TRACE("small list=%p, large list=%p\n", shell_imagelists
[SHIL_SMALL
], shell_imagelists
[SHIL_LARGE
]);
488 /*************************************************************************
493 static INT CALLBACK
sic_free( LPVOID ptr
, LPVOID lparam
)
495 heap_free(((LPSIC_ENTRY
)ptr
)->sSourceFile
);
500 void SIC_Destroy(void)
506 EnterCriticalSection(&SHELL32_SicCS
);
508 if (sic_hdpa
) DPA_DestroyCallback(sic_hdpa
, sic_free
, NULL
);
510 for (i
= 0; i
< ARRAY_SIZE(shell_imagelists
); i
++)
512 if (shell_imagelists
[i
])
513 ImageList_Destroy(shell_imagelists
[i
]);
516 LeaveCriticalSection(&SHELL32_SicCS
);
517 DeleteCriticalSection(&SHELL32_SicCS
);
520 /*****************************************************************************
521 * SIC_GetIconIndex [internal]
524 * sSourceFile [IN] filename of file containing the icon
525 * index [IN] index/resID (negated) in this file
528 * look in the cache for a proper icon. if not available the icon is taken
529 * from the file and cached
531 INT
SIC_GetIconIndex (LPCWSTR sSourceFile
, INT dwSourceIndex
, DWORD dwFlags
)
534 INT ret
, index
= INVALID_INDEX
;
535 WCHAR path
[MAX_PATH
];
537 TRACE("%s %i\n", debugstr_w(sSourceFile
), dwSourceIndex
);
539 GetFullPathNameW(sSourceFile
, MAX_PATH
, path
, NULL
);
540 sice
.sSourceFile
= path
;
541 sice
.dwSourceIndex
= dwSourceIndex
;
542 sice
.dwFlags
= dwFlags
;
544 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
546 EnterCriticalSection(&SHELL32_SicCS
);
548 if (NULL
!= DPA_GetPtr (sic_hdpa
, 0))
550 /* search linear from position 0*/
551 index
= DPA_Search (sic_hdpa
, &sice
, 0, SIC_CompareEntries
, 0, 0);
554 if ( INVALID_INDEX
== index
)
556 ret
= SIC_LoadIcon (sSourceFile
, dwSourceIndex
, dwFlags
);
561 ret
= ((LPSIC_ENTRY
)DPA_GetPtr(sic_hdpa
, index
))->dwListIndex
;
564 LeaveCriticalSection(&SHELL32_SicCS
);
568 /*****************************************************************************
569 * SIC_LoadOverlayIcon [internal]
571 * Load a shell overlay icon and return its icon cache index.
573 static int SIC_LoadOverlayIcon(int icon_idx
)
575 WCHAR buffer
[1024], wszIdx
[12];
580 iconPath
= swShell32Name
; /* default: load icon from shell32.dll */
583 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons",
584 0, KEY_READ
, &hKeyShellIcons
) == ERROR_SUCCESS
)
586 DWORD count
= sizeof(buffer
);
588 swprintf(wszIdx
, ARRAY_SIZE(wszIdx
), L
"%d", icon_idx
);
590 /* read icon path and index */
591 if (RegQueryValueExW(hKeyShellIcons
, wszIdx
, NULL
, NULL
, (LPBYTE
)buffer
, &count
) == ERROR_SUCCESS
)
593 LPWSTR p
= wcschr(buffer
, ',');
597 ERR("Icon index in Shell Icons/%s corrupted, no comma.\n", debugstr_w(wszIdx
));
598 RegCloseKey(hKeyShellIcons
);
603 iconIdx
= wcstol(p
, NULL
, 10);
606 RegCloseKey(hKeyShellIcons
);
609 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
611 return SIC_LoadIcon(iconPath
, iconIdx
, 0);
614 /*************************************************************************
615 * Shell_GetImageLists [SHELL32.71]
618 * imglist[1|2] [OUT] pointer which receives imagelist handles
621 BOOL WINAPI
Shell_GetImageLists(HIMAGELIST
*large_list
, HIMAGELIST
*small_list
)
623 TRACE("(%p, %p)\n", large_list
, small_list
);
625 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
626 if (large_list
) *large_list
= shell_imagelists
[SHIL_LARGE
];
627 if (small_list
) *small_list
= shell_imagelists
[SHIL_SMALL
];
631 /*************************************************************************
632 * PidlToSicIndex [INTERNAL]
635 * sh [IN] IShellFolder
639 * pIndex [OUT] index within the SIC
642 BOOL
PidlToSicIndex (
650 WCHAR szIconFile
[MAX_PATH
]; /* file containing the icon */
651 INT iSourceIndex
; /* index or resID(negated) in this file */
654 int iShortcutDefaultIndex
= INVALID_INDEX
;
656 TRACE("sf=%p pidl=%p %s\n", sh
, pidl
, bBigIcon
?"Big":"Small");
658 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
660 if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh
, 0, 1, &pidl
, &IID_IExtractIconW
, 0, (void **)&ei
)))
662 if (SUCCEEDED(IExtractIconW_GetIconLocation(ei
, uFlags
, szIconFile
, MAX_PATH
, &iSourceIndex
, &dwFlags
)))
664 *pIndex
= SIC_GetIconIndex(szIconFile
, iSourceIndex
, uFlags
);
667 IExtractIconW_Release(ei
);
670 if (INVALID_INDEX
== *pIndex
) /* default icon when failed */
672 if (0 == (uFlags
& GIL_FORSHORTCUT
))
678 if (INVALID_INDEX
== iShortcutDefaultIndex
)
680 iShortcutDefaultIndex
= SIC_LoadIcon(swShell32Name
, 0, GIL_FORSHORTCUT
);
682 *pIndex
= (INVALID_INDEX
!= iShortcutDefaultIndex
? iShortcutDefaultIndex
: 0);
690 /*************************************************************************
691 * SHMapPIDLToSystemImageListIndex [SHELL32.77]
694 * sh [IN] pointer to an instance of IShellFolder
696 * pIndex [OUT][OPTIONAL] SIC index for big icon
699 int WINAPI
SHMapPIDLToSystemImageListIndex(
707 TRACE("(SF=%p,pidl=%p,%p)\n",sh
,pidl
,pIndex
);
710 if (SHELL_IsShortcut(pidl
))
711 uGilFlags
|= GIL_FORSHORTCUT
;
714 if (!PidlToSicIndex ( sh
, pidl
, 1, uGilFlags
, pIndex
))
717 if (!PidlToSicIndex ( sh
, pidl
, 0, uGilFlags
, &Index
))
723 /*************************************************************************
724 * SHMapIDListToImageListIndexAsync [SHELL32.148]
726 HRESULT WINAPI
SHMapIDListToImageListIndexAsync(IUnknown
*pts
, IShellFolder
*psf
,
727 LPCITEMIDLIST pidl
, UINT flags
,
728 void *pfn
, void *pvData
, void *pvHint
,
729 int *piIndex
, int *piIndexSel
)
731 FIXME("(%p, %p, %p, 0x%08x, %p, %p, %p, %p, %p)\n",
732 pts
, psf
, pidl
, flags
, pfn
, pvData
, pvHint
, piIndex
, piIndexSel
);
736 /*************************************************************************
737 * Shell_GetCachedImageIndex [SHELL32.72]
740 INT WINAPI
Shell_GetCachedImageIndexA(LPCSTR szPath
, INT nIndex
, BOOL bSimulateDoc
)
745 WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath
), nIndex
, bSimulateDoc
);
747 len
= MultiByteToWideChar( CP_ACP
, 0, szPath
, -1, NULL
, 0 );
748 szTemp
= heap_alloc( len
* sizeof(WCHAR
) );
749 MultiByteToWideChar( CP_ACP
, 0, szPath
, -1, szTemp
, len
);
751 ret
= SIC_GetIconIndex( szTemp
, nIndex
, 0 );
758 INT WINAPI
Shell_GetCachedImageIndexW(LPCWSTR szPath
, INT nIndex
, BOOL bSimulateDoc
)
760 WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath
), nIndex
, bSimulateDoc
);
762 return SIC_GetIconIndex(szPath
, nIndex
, 0);
765 INT WINAPI
Shell_GetCachedImageIndexAW(LPCVOID szPath
, INT nIndex
, BOOL bSimulateDoc
)
766 { if( SHELL_OsIsUnicode())
767 return Shell_GetCachedImageIndexW(szPath
, nIndex
, bSimulateDoc
);
768 return Shell_GetCachedImageIndexA(szPath
, nIndex
, bSimulateDoc
);
771 /*************************************************************************
772 * ExtractIconExW [SHELL32.@]
775 * -1 file is not valid
776 * or number of icons extracted
778 UINT WINAPI
ExtractIconExW(LPCWSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
780 TRACE("%s %i %p %p %i\n", debugstr_w(lpszFile
), nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
782 return PrivateExtractIconExW(lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
785 /*************************************************************************
786 * ExtractIconExA [SHELL32.@]
788 UINT WINAPI
ExtractIconExA(LPCSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
791 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, NULL
, 0);
792 LPWSTR lpwstrFile
= heap_alloc( len
* sizeof(WCHAR
));
794 TRACE("%s %i %p %p %i\n", lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
798 MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, lpwstrFile
, len
);
799 ret
= ExtractIconExW(lpwstrFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
800 heap_free(lpwstrFile
);
805 /*************************************************************************
806 * ExtractAssociatedIconA (SHELL32.@)
808 * Return icon for given file (either from file itself or from associated
809 * executable) and patch parameters if needed.
811 HICON WINAPI
ExtractAssociatedIconA(HINSTANCE hInst
, LPSTR lpIconPath
, LPWORD lpiIcon
)
814 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpIconPath
, -1, NULL
, 0);
815 /* Note that we need to allocate MAX_PATH, since we are supposed to fill
816 * the correct executable if there is no icon in lpIconPath directly.
817 * lpIconPath itself is supposed to be large enough, so make sure lpIconPathW
818 * is large enough too. Yes, I am puking too.
820 LPWSTR lpIconPathW
= heap_alloc(MAX_PATH
* sizeof(WCHAR
));
822 TRACE("%p %s %p\n", hInst
, debugstr_a(lpIconPath
), lpiIcon
);
826 MultiByteToWideChar(CP_ACP
, 0, lpIconPath
, -1, lpIconPathW
, len
);
827 hIcon
= ExtractAssociatedIconW(hInst
, lpIconPathW
, lpiIcon
);
828 WideCharToMultiByte(CP_ACP
, 0, lpIconPathW
, -1, lpIconPath
, MAX_PATH
, NULL
, NULL
);
829 heap_free(lpIconPathW
);
834 /*************************************************************************
835 * ExtractAssociatedIconW (SHELL32.@)
837 * Return icon for given file (either from file itself or from associated
838 * executable) and patch parameters if needed.
840 HICON WINAPI
ExtractAssociatedIconW(HINSTANCE hInst
, LPWSTR lpIconPath
, LPWORD lpiIcon
)
845 TRACE("%p %s %p\n", hInst
, debugstr_w(lpIconPath
), lpiIcon
);
848 lpiIcon
= &wDummyIcon
;
850 hIcon
= ExtractIconW(hInst
, lpIconPath
, *lpiIcon
);
852 if( hIcon
< (HICON
)2 )
853 { if( hIcon
== (HICON
)1 ) /* no icons found in given file */
854 { WCHAR tempPath
[MAX_PATH
];
855 HINSTANCE uRet
= FindExecutableW(lpIconPath
,NULL
,tempPath
);
857 if( uRet
> (HINSTANCE
)32 && tempPath
[0] )
858 { lstrcpyW(lpIconPath
,tempPath
);
859 hIcon
= ExtractIconW(hInst
, lpIconPath
, *lpiIcon
);
860 if( hIcon
> (HICON
)2 )
865 if( hIcon
== (HICON
)1 )
866 *lpiIcon
= 2; /* MS-DOS icon - we found .exe but no icons in it */
868 *lpiIcon
= 6; /* generic icon - found nothing */
870 if (GetModuleFileNameW(hInst
, lpIconPath
, MAX_PATH
))
871 hIcon
= LoadIconW(hInst
, MAKEINTRESOURCEW(*lpiIcon
));
876 /*************************************************************************
877 * ExtractAssociatedIconExW (SHELL32.@)
879 * Return icon for given file (either from file itself or from associated
880 * executable) and patch parameters if needed.
882 HICON WINAPI
ExtractAssociatedIconExW(HINSTANCE hInst
, LPWSTR lpIconPath
, LPWORD lpiIconIdx
, LPWORD lpiIconId
)
884 FIXME("%p %s %p %p): stub\n", hInst
, debugstr_w(lpIconPath
), lpiIconIdx
, lpiIconId
);
888 /*************************************************************************
889 * ExtractAssociatedIconExA (SHELL32.@)
891 * Return icon for given file (either from file itself or from associated
892 * executable) and patch parameters if needed.
894 HICON WINAPI
ExtractAssociatedIconExA(HINSTANCE hInst
, LPSTR lpIconPath
, LPWORD lpiIconIdx
, LPWORD lpiIconId
)
897 INT len
= MultiByteToWideChar( CP_ACP
, 0, lpIconPath
, -1, NULL
, 0 );
898 LPWSTR lpwstrFile
= heap_alloc( len
* sizeof(WCHAR
) );
900 TRACE("%p %s %p %p)\n", hInst
, lpIconPath
, lpiIconIdx
, lpiIconId
);
902 MultiByteToWideChar( CP_ACP
, 0, lpIconPath
, -1, lpwstrFile
, len
);
903 ret
= ExtractAssociatedIconExW(hInst
, lpwstrFile
, lpiIconIdx
, lpiIconId
);
904 heap_free(lpwstrFile
);
909 /****************************************************************************
910 * SHDefExtractIconW [SHELL32.@]
912 HRESULT WINAPI
SHDefExtractIconW(LPCWSTR pszIconFile
, int iIndex
, UINT uFlags
,
913 HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIconSize
)
917 WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile
), iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
919 ret
= PrivateExtractIconsW(pszIconFile
, iIndex
, nIconSize
, nIconSize
, hIcons
, NULL
, 2, LR_DEFAULTCOLOR
);
920 /* FIXME: deal with uFlags parameter which contains GIL_ flags */
921 if (ret
== 0xFFFFFFFF)
925 *phiconLarge
= hIcons
[0];
927 DestroyIcon(hIcons
[0]);
929 *phiconSmall
= hIcons
[1];
931 DestroyIcon(hIcons
[1]);
937 /****************************************************************************
938 * SHDefExtractIconA [SHELL32.@]
940 HRESULT WINAPI
SHDefExtractIconA(LPCSTR pszIconFile
, int iIndex
, UINT uFlags
,
941 HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIconSize
)
944 INT len
= MultiByteToWideChar(CP_ACP
, 0, pszIconFile
, -1, NULL
, 0);
945 LPWSTR lpwstrFile
= heap_alloc(len
* sizeof(WCHAR
));
947 TRACE("%s %d 0x%08x %p %p %d\n", pszIconFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
949 MultiByteToWideChar(CP_ACP
, 0, pszIconFile
, -1, lpwstrFile
, len
);
950 ret
= SHDefExtractIconW(lpwstrFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
951 heap_free(lpwstrFile
);
956 /****************************************************************************
957 * SHGetIconOverlayIndexA [SHELL32.@]
959 * Returns the index of the overlay icon in the system image list.
961 INT WINAPI
SHGetIconOverlayIndexA(LPCSTR pszIconPath
, INT iIconIndex
)
963 FIXME("%s, %d\n", debugstr_a(pszIconPath
), iIconIndex
);
968 /****************************************************************************
969 * SHGetIconOverlayIndexW [SHELL32.@]
971 * Returns the index of the overlay icon in the system image list.
973 INT WINAPI
SHGetIconOverlayIndexW(LPCWSTR pszIconPath
, INT iIconIndex
)
975 FIXME("%s, %d\n", debugstr_w(pszIconPath
), iIconIndex
);
980 /****************************************************************************
981 * SHGetStockIconInfo [SHELL32.@]
983 * Receive information for builtin icons
986 * id [I] selected icon-id to get information for
987 * flags [I] selects the information to receive
988 * sii [IO] SHSTOCKICONINFO structure to fill
992 * Failure: A HRESULT failure code
995 HRESULT WINAPI
SHGetStockIconInfo(SHSTOCKICONID id
, UINT flags
, SHSTOCKICONINFO
*sii
)
997 FIXME("(%d, 0x%x, %p) semi-stub\n", id
, flags
, sii
);
998 if ((id
< 0) || (id
>= SIID_MAX_ICONS
) || !sii
|| (sii
->cbSize
!= sizeof(SHSTOCKICONINFO
))) {
1002 GetSystemDirectoryW(sii
->szPath
, MAX_PATH
);
1004 /* no icons defined: use default */
1005 sii
->iIcon
= -IDI_SHELL_FILE
;
1006 lstrcatW(sii
->szPath
, L
"\\shell32.dll");
1009 FIXME("flags 0x%x not implemented\n", flags
);
1012 sii
->iSysImageIndex
= -1;
1014 TRACE("%3d: returning %s (%d)\n", id
, debugstr_w(sii
->szPath
), sii
->iIcon
);
1019 /*************************************************************************
1020 * SHGetImageList (SHELL32.727)
1022 * Returns a copy of a shell image list.
1025 * Windows XP features 4 sizes of image list, and Vista 5. Wine currently
1026 * only supports the traditional small and large image lists, so requests
1027 * for the others will currently fail.
1029 HRESULT WINAPI
SHGetImageList(int iImageList
, REFIID riid
, void **ppv
)
1031 TRACE("(%d, %s, %p)\n", iImageList
, debugstr_guid(riid
), ppv
);
1033 if (iImageList
< 0 || iImageList
> SHIL_LAST
)
1036 InitOnceExecuteOnce( &sic_init_once
, SIC_Initialize
, NULL
, NULL
);
1037 return HIMAGELIST_QueryInterface(shell_imagelists
[iImageList
], riid
, ppv
);