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 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
25 /********************** THE ICON CACHE ********************************/
27 #define INVALID_INDEX -1
31 LPWSTR sSourceFile
; /* file (not path!) containing the icon */
32 DWORD dwSourceIndex
; /* index within the file, if it is a resoure ID it will be negated */
33 DWORD dwListIndex
; /* index within the iconlist */
34 DWORD dwFlags
; /* GIL_* flags */
36 } SIC_ENTRY
, * LPSIC_ENTRY
;
38 static HDPA sic_hdpa
= 0;
40 static CRITICAL_SECTION SHELL32_SicCS
;
41 static CRITICAL_SECTION_DEBUG critsect_debug
=
44 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
45 0, 0, { (DWORD_PTR
)(__FILE__
": SHELL32_SicCS") }
47 static CRITICAL_SECTION SHELL32_SicCS
= { &critsect_debug
, -1, 0, 0, 0, 0 };
49 /*****************************************************************************
53 * Callback for DPA_Search
55 static INT CALLBACK
SIC_CompareEntries( LPVOID p1
, LPVOID p2
, LPARAM lparam
)
56 { LPSIC_ENTRY e1
= (LPSIC_ENTRY
)p1
, e2
= (LPSIC_ENTRY
)p2
;
58 TRACE("%p %p %8lx\n", p1
, p2
, lparam
);
60 /* Icons in the cache are keyed by the name of the file they are
61 * loaded from, their resource index and the fact if they have a shortcut
62 * icon overlay or not.
64 if (e1
->dwSourceIndex
!= e2
->dwSourceIndex
|| /* first the faster one */
65 (e1
->dwFlags
& GIL_FORSHORTCUT
) != (e2
->dwFlags
& GIL_FORSHORTCUT
))
68 if (wcsicmp(e1
->sSourceFile
,e2
->sSourceFile
))
74 /* declare SIC_LoadOverlayIcon() */
75 static int SIC_LoadOverlayIcon(int icon_idx
);
77 /*****************************************************************************
78 * SIC_OverlayShortcutImage [internal]
81 * Creates a new icon as a copy of the passed-in icon, overlayed with a
84 static HICON
SIC_OverlayShortcutImage(HICON SourceIcon
, BOOL large
)
85 { ICONINFO SourceIconInfo
, ShortcutIconInfo
, TargetIconInfo
;
86 HICON ShortcutIcon
, TargetIcon
;
87 BITMAP SourceBitmapInfo
, ShortcutBitmapInfo
;
92 HBITMAP OldSourceBitmap
= NULL
,
93 OldShortcutBitmap
= NULL
,
94 OldTargetBitmap
= NULL
;
96 static int s_imgListIdx
= -1;
98 /* Get information about the source icon and shortcut overlay */
99 if (! GetIconInfo(SourceIcon
, &SourceIconInfo
)
100 || 0 == GetObjectW(SourceIconInfo
.hbmColor
, sizeof(BITMAP
), &SourceBitmapInfo
))
105 /* search for the shortcut icon only once */
106 if (s_imgListIdx
== -1)
107 s_imgListIdx
= SIC_LoadOverlayIcon(- IDI_SHELL_SHORTCUT
);
108 /* FIXME should use icon index 29 instead of the
109 resource id, but not all icons are present yet
110 so we can't use icon indices */
112 if (s_imgListIdx
!= -1)
115 ShortcutIcon
= ImageList_GetIcon(ShellBigIconList
, s_imgListIdx
, ILD_TRANSPARENT
);
117 ShortcutIcon
= ImageList_GetIcon(ShellSmallIconList
, s_imgListIdx
, ILD_TRANSPARENT
);
121 if (NULL
== ShortcutIcon
122 || ! GetIconInfo(ShortcutIcon
, &ShortcutIconInfo
)
123 || 0 == GetObjectW(ShortcutIconInfo
.hbmColor
, sizeof(BITMAP
), &ShortcutBitmapInfo
))
128 TargetIconInfo
= SourceIconInfo
;
129 TargetIconInfo
.hbmMask
= NULL
;
130 TargetIconInfo
.hbmColor
= NULL
;
132 /* Setup the source, shortcut and target masks */
133 SourceDC
= CreateCompatibleDC(NULL
);
134 if (NULL
== SourceDC
) goto fail
;
135 OldSourceBitmap
= SelectObject(SourceDC
, SourceIconInfo
.hbmMask
);
136 if (NULL
== OldSourceBitmap
) goto fail
;
138 ShortcutDC
= CreateCompatibleDC(NULL
);
139 if (NULL
== ShortcutDC
) goto fail
;
140 OldShortcutBitmap
= SelectObject(ShortcutDC
, ShortcutIconInfo
.hbmMask
);
141 if (NULL
== OldShortcutBitmap
) goto fail
;
143 TargetDC
= CreateCompatibleDC(NULL
);
144 if (NULL
== TargetDC
) goto fail
;
145 TargetIconInfo
.hbmMask
= CreateCompatibleBitmap(TargetDC
, SourceBitmapInfo
.bmWidth
,
146 SourceBitmapInfo
.bmHeight
);
147 if (NULL
== TargetIconInfo
.hbmMask
) goto fail
;
148 ScreenDC
= GetDC(NULL
);
149 if (NULL
== ScreenDC
) goto fail
;
150 TargetIconInfo
.hbmColor
= CreateCompatibleBitmap(ScreenDC
, SourceBitmapInfo
.bmWidth
,
151 SourceBitmapInfo
.bmHeight
);
152 ReleaseDC(NULL
, ScreenDC
);
153 if (NULL
== TargetIconInfo
.hbmColor
) goto fail
;
154 OldTargetBitmap
= SelectObject(TargetDC
, TargetIconInfo
.hbmMask
);
155 if (NULL
== OldTargetBitmap
) goto fail
;
157 /* Create the target mask by ANDing the source and shortcut masks */
158 if (! BitBlt(TargetDC
, 0, 0, SourceBitmapInfo
.bmWidth
, SourceBitmapInfo
.bmHeight
,
159 SourceDC
, 0, 0, SRCCOPY
) ||
160 ! BitBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
161 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
162 ShortcutDC
, 0, 0, SRCAND
))
167 /* Setup the source and target xor bitmap */
168 if (NULL
== SelectObject(SourceDC
, SourceIconInfo
.hbmColor
) ||
169 NULL
== SelectObject(TargetDC
, TargetIconInfo
.hbmColor
))
174 /* Copy the source color bitmap to the target */
175 if (! BitBlt(TargetDC
, 0, 0, SourceBitmapInfo
.bmWidth
, SourceBitmapInfo
.bmHeight
,
176 SourceDC
, 0, 0, SRCCOPY
)) goto fail
;
178 /* Copy the source xor bitmap to the target and clear out part of it by using
180 if (NULL
== SelectObject(ShortcutDC
, ShortcutIconInfo
.hbmColor
)) goto fail
;
181 if (!MaskBlt(TargetDC
, 0, SourceBitmapInfo
.bmHeight
- ShortcutBitmapInfo
.bmHeight
,
182 ShortcutBitmapInfo
.bmWidth
, ShortcutBitmapInfo
.bmHeight
,
183 ShortcutDC
, 0, 0, ShortcutIconInfo
.hbmMask
, 0, 0,
184 MAKEROP4(SRCCOPY
, 0xAA0000)))
189 /* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set
191 SelectObject(TargetDC
, OldTargetBitmap
);
192 DeleteObject(TargetDC
);
193 SelectObject(ShortcutDC
, OldShortcutBitmap
);
194 DeleteObject(ShortcutDC
);
195 SelectObject(SourceDC
, OldSourceBitmap
);
196 DeleteObject(SourceDC
);
198 /* Create the icon using the bitmaps prepared earlier */
199 TargetIcon
= CreateIconIndirect(&TargetIconInfo
);
201 /* CreateIconIndirect copies the bitmaps, so we can release our bitmaps now */
202 DeleteObject(TargetIconInfo
.hbmColor
);
203 DeleteObject(TargetIconInfo
.hbmMask
);
208 /* Clean up scratch resources we created */
209 if (NULL
!= OldTargetBitmap
) SelectObject(TargetDC
, OldTargetBitmap
);
210 if (NULL
!= TargetIconInfo
.hbmColor
) DeleteObject(TargetIconInfo
.hbmColor
);
211 if (NULL
!= TargetIconInfo
.hbmMask
) DeleteObject(TargetIconInfo
.hbmMask
);
212 if (NULL
!= TargetDC
) DeleteObject(TargetDC
);
213 if (NULL
!= OldShortcutBitmap
) SelectObject(ShortcutDC
, OldShortcutBitmap
);
214 if (NULL
!= ShortcutDC
) DeleteObject(ShortcutDC
);
215 if (NULL
!= OldSourceBitmap
) SelectObject(SourceDC
, OldSourceBitmap
);
216 if (NULL
!= SourceDC
) DeleteObject(SourceDC
);
221 /*****************************************************************************
222 * SIC_IconAppend [internal]
225 * appends an icon pair to the end of the cache
227 static INT
SIC_IconAppend (LPCWSTR sSourceFile
, INT dwSourceIndex
, HICON hSmallIcon
, HICON hBigIcon
, DWORD dwFlags
)
228 { LPSIC_ENTRY lpsice
;
229 INT ret
, index
, index1
;
230 WCHAR path
[MAX_PATH
];
231 TRACE("%s %i %p %p\n", debugstr_w(sSourceFile
), dwSourceIndex
, hSmallIcon
,hBigIcon
);
233 lpsice
= (LPSIC_ENTRY
) SHAlloc (sizeof (SIC_ENTRY
));
235 GetFullPathNameW(sSourceFile
, MAX_PATH
, path
, NULL
);
236 lpsice
->sSourceFile
= HeapAlloc( GetProcessHeap(), 0, (wcslen(path
)+1)*sizeof(WCHAR
) );
237 wcscpy( lpsice
->sSourceFile
, path
);
239 lpsice
->dwSourceIndex
= dwSourceIndex
;
240 lpsice
->dwFlags
= dwFlags
;
242 EnterCriticalSection(&SHELL32_SicCS
);
244 index
= DPA_InsertPtr(sic_hdpa
, 0x7fff, lpsice
);
245 if ( INVALID_INDEX
== index
)
247 HeapFree(GetProcessHeap(), 0, lpsice
->sSourceFile
);
253 index
= ImageList_AddIcon (ShellSmallIconList
, hSmallIcon
);
254 index1
= ImageList_AddIcon (ShellBigIconList
, hBigIcon
);
258 FIXME("iconlists out of sync 0x%x 0x%x\n", index
, index1
);
260 lpsice
->dwListIndex
= index
;
261 ret
= lpsice
->dwListIndex
;
264 LeaveCriticalSection(&SHELL32_SicCS
);
267 /****************************************************************************
268 * SIC_LoadIcon [internal]
271 * gets small/big icon by number from a file
273 static INT
SIC_LoadIcon (LPCWSTR sSourceFile
, INT dwSourceIndex
, DWORD dwFlags
)
274 { HICON hiconLarge
=0;
276 HICON hiconLargeShortcut
;
277 HICON hiconSmallShortcut
;
279 #if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)
280 static UINT (WINAPI
*PrivateExtractIconExW
)(LPCWSTR
,int,HICON
*,HICON
*,UINT
) = NULL
;
282 if (!PrivateExtractIconExW
) {
283 HMODULE hUser32
= GetModuleHandleA("user32");
284 PrivateExtractIconExW
= (UINT(WINAPI
*)(LPCWSTR
,int,HICON
*,HICON
*,UINT
)) GetProcAddress(hUser32
, "PrivateExtractIconExW");
287 if (PrivateExtractIconExW
)
288 PrivateExtractIconExW(sSourceFile
, dwSourceIndex
, &hiconLarge
, &hiconSmall
, 1);
292 PrivateExtractIconsW(sSourceFile
, dwSourceIndex
, 32, 32, &hiconLarge
, NULL
, 1, 0);
293 PrivateExtractIconsW(sSourceFile
, dwSourceIndex
, 16, 16, &hiconSmall
, NULL
, 1, 0);
296 if ( !hiconLarge
|| !hiconSmall
)
298 WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex
, debugstr_w(sSourceFile
), hiconLarge
, hiconSmall
);
302 if (0 != (dwFlags
& GIL_FORSHORTCUT
))
304 hiconLargeShortcut
= SIC_OverlayShortcutImage(hiconLarge
, TRUE
);
305 hiconSmallShortcut
= SIC_OverlayShortcutImage(hiconSmall
, FALSE
);
306 if (NULL
!= hiconLargeShortcut
&& NULL
!= hiconSmallShortcut
)
308 hiconLarge
= hiconLargeShortcut
;
309 hiconSmall
= hiconSmallShortcut
;
313 WARN("Failed to create shortcut overlayed icons\n");
314 if (NULL
!= hiconLargeShortcut
) DestroyIcon(hiconLargeShortcut
);
315 if (NULL
!= hiconSmallShortcut
) DestroyIcon(hiconSmallShortcut
);
316 dwFlags
&= ~ GIL_FORSHORTCUT
;
320 return SIC_IconAppend (sSourceFile
, dwSourceIndex
, hiconSmall
, hiconLarge
, dwFlags
);
322 /*****************************************************************************
323 * SIC_GetIconIndex [internal]
326 * sSourceFile [IN] filename of file containing the icon
327 * index [IN] index/resID (negated) in this file
330 * look in the cache for a proper icon. if not available the icon is taken
331 * from the file and cached
333 INT
SIC_GetIconIndex (LPCWSTR sSourceFile
, INT dwSourceIndex
, DWORD dwFlags
)
336 INT ret
, index
= INVALID_INDEX
;
337 WCHAR path
[MAX_PATH
];
339 TRACE("%s %i\n", debugstr_w(sSourceFile
), dwSourceIndex
);
341 GetFullPathNameW(sSourceFile
, MAX_PATH
, path
, NULL
);
342 sice
.sSourceFile
= path
;
343 sice
.dwSourceIndex
= dwSourceIndex
;
344 sice
.dwFlags
= dwFlags
;
346 EnterCriticalSection(&SHELL32_SicCS
);
348 if (NULL
!= DPA_GetPtr (sic_hdpa
, 0))
350 /* search linear from position 0*/
351 index
= DPA_Search (sic_hdpa
, &sice
, 0, SIC_CompareEntries
, 0, 0);
354 if ( INVALID_INDEX
== index
)
356 ret
= SIC_LoadIcon (sSourceFile
, dwSourceIndex
, dwFlags
);
361 ret
= ((LPSIC_ENTRY
)DPA_GetPtr(sic_hdpa
, index
))->dwListIndex
;
364 LeaveCriticalSection(&SHELL32_SicCS
);
367 /*****************************************************************************
368 * SIC_Initialize [internal]
370 BOOL
SIC_Initialize(void)
372 HICON hSm
= NULL
, hLg
= NULL
;
373 INT cx_small
, cy_small
;
374 INT cx_large
, cy_large
;
379 TRACE("Entered SIC_Initialize\n");
383 TRACE("Icon cache already initialized\n");
387 sic_hdpa
= DPA_Create(16);
393 hDC
= CreateICW(L
"DISPLAY", NULL
, NULL
, NULL
);
396 ERR("Failed to create information context (error %d)\n", GetLastError());
400 bpp
= GetDeviceCaps(hDC
, BITSPIXEL
);
401 ReleaseDC(NULL
, hDC
);
408 ilMask
= ILC_COLOR16
;
410 ilMask
= ILC_COLOR24
;
412 ilMask
= ILC_COLOR32
;
418 cx_small
= GetSystemMetrics(SM_CXSMICON
);
419 cy_small
= GetSystemMetrics(SM_CYSMICON
);
420 cx_large
= GetSystemMetrics(SM_CXICON
);
421 cy_large
= GetSystemMetrics(SM_CYICON
);
423 ShellSmallIconList
= ImageList_Create(cx_small
,
429 ShellBigIconList
= ImageList_Create(cx_large
,
434 if (ShellSmallIconList
)
436 /* Load the document icon, which is used as the default if an icon isn't found. */
437 hSm
= (HICON
)LoadImageW(shell32_hInstance
,
438 MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT
),
442 LR_SHARED
| LR_DEFAULTCOLOR
);
445 ERR("Failed to load IDI_SHELL_DOCUMENT icon1!\n");
451 ERR("Failed to load ShellSmallIconList\n");
455 if (ShellBigIconList
)
457 hLg
= (HICON
)LoadImageW(shell32_hInstance
,
458 MAKEINTRESOURCEW(IDI_SHELL_DOCUMENT
),
462 LR_SHARED
| LR_DEFAULTCOLOR
);
465 ERR("Failed to load IDI_SHELL_DOCUMENT icon2!\n");
472 ERR("Failed to load ShellBigIconList\n");
476 SIC_IconAppend(swShell32Name
, IDI_SHELL_DOCUMENT
-1, hSm
, hLg
, 0);
477 SIC_IconAppend(swShell32Name
, -IDI_SHELL_DOCUMENT
, hSm
, hLg
, 0);
479 TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList
, ShellBigIconList
);
483 /*************************************************************************
488 static INT CALLBACK
sic_free( LPVOID ptr
, LPVOID lparam
)
490 HeapFree(GetProcessHeap(), 0, ((LPSIC_ENTRY
)ptr
)->sSourceFile
);
495 void SIC_Destroy(void)
499 EnterCriticalSection(&SHELL32_SicCS
);
501 if (sic_hdpa
) DPA_DestroyCallback(sic_hdpa
, sic_free
, NULL
);
504 ImageList_Destroy(ShellSmallIconList
);
505 ShellSmallIconList
= 0;
506 ImageList_Destroy(ShellBigIconList
);
507 ShellBigIconList
= 0;
509 LeaveCriticalSection(&SHELL32_SicCS
);
510 //DeleteCriticalSection(&SHELL32_SicCS); //static
513 /*****************************************************************************
514 * SIC_LoadOverlayIcon [internal]
516 * Load a shell overlay icon and return its icon cache index.
518 static int SIC_LoadOverlayIcon(int icon_idx
)
520 WCHAR buffer
[1024], wszIdx
[8];
525 static const WCHAR wszShellIcons
[] = {
526 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
527 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
528 'E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','I','c','o','n','s',0
530 static const WCHAR wszNumFmt
[] = {'%','d',0};
532 iconPath
= swShell32Name
; /* default: load icon from shell32.dll */
535 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, wszShellIcons
, 0, KEY_READ
, &hKeyShellIcons
) == ERROR_SUCCESS
)
537 DWORD count
= sizeof(buffer
);
539 swprintf(wszIdx
, wszNumFmt
, icon_idx
);
541 /* read icon path and index */
542 if (RegQueryValueExW(hKeyShellIcons
, wszIdx
, NULL
, NULL
, (LPBYTE
)buffer
, &count
) == ERROR_SUCCESS
)
544 LPWSTR p
= wcschr(buffer
, ',');
553 RegCloseKey(hKeyShellIcons
);
556 return SIC_LoadIcon(iconPath
, iconIdx
, 0);
559 /*************************************************************************
560 * Shell_GetImageLists [SHELL32.71]
563 * imglist[1|2] [OUT] pointer which receives imagelist handles
566 BOOL WINAPI
Shell_GetImageLists(HIMAGELIST
* lpBigList
, HIMAGELIST
* lpSmallList
)
567 { TRACE("(%p,%p)\n",lpBigList
,lpSmallList
);
569 { *lpBigList
= ShellBigIconList
;
572 { *lpSmallList
= ShellSmallIconList
;
577 /*************************************************************************
578 * PidlToSicIndex [INTERNAL]
581 * sh [IN] IShellFolder
585 * pIndex [OUT] index within the SIC
588 BOOL
PidlToSicIndex (
596 WCHAR szIconFile
[MAX_PATH
]; /* file containing the icon */
597 INT iSourceIndex
; /* index or resID(negated) in this file */
600 int iShortcutDefaultIndex
= INVALID_INDEX
;
602 TRACE("sf=%p pidl=%p %s\n", sh
, pidl
, bBigIcon
?"Big":"Small");
604 if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh
, 0, 1, &pidl
, &IID_IExtractIconW
, 0, (void **)&ei
)))
606 if (SUCCEEDED(ei
->lpVtbl
->GetIconLocation(ei
, uFlags
, szIconFile
, MAX_PATH
, &iSourceIndex
, &dwFlags
)))
608 *pIndex
= SIC_GetIconIndex(szIconFile
, iSourceIndex
, uFlags
);
611 ei
->lpVtbl
->Release(ei
);
614 if (INVALID_INDEX
== *pIndex
) /* default icon when failed */
616 if (0 == (uFlags
& GIL_FORSHORTCUT
))
622 if (INVALID_INDEX
== iShortcutDefaultIndex
)
624 iShortcutDefaultIndex
= SIC_LoadIcon(swShell32Name
, 0, GIL_FORSHORTCUT
);
626 *pIndex
= (INVALID_INDEX
!= iShortcutDefaultIndex
? iShortcutDefaultIndex
: 0);
634 /*************************************************************************
635 * SHMapPIDLToSystemImageListIndex [SHELL32.77]
638 * sh [IN] pointer to an instance of IShellFolder
640 * pIndex [OUT][OPTIONAL] SIC index for big icon
643 int WINAPI
SHMapPIDLToSystemImageListIndex(
651 TRACE("(SF=%p,pidl=%p,%p)\n",sh
,pidl
,pIndex
);
654 if (SHELL_IsShortcut(pidl
))
655 uGilFlags
|= GIL_FORSHORTCUT
;
658 if (!PidlToSicIndex ( sh
, pidl
, 1, uGilFlags
, pIndex
))
661 if (!PidlToSicIndex ( sh
, pidl
, 0, uGilFlags
, &Index
))
667 /*************************************************************************
668 * SHMapIDListToImageListIndexAsync [SHELL32.148]
670 HRESULT WINAPI
SHMapIDListToImageListIndexAsync(IUnknown
*pts
, IShellFolder
*psf
,
671 LPCITEMIDLIST pidl
, UINT flags
,
672 void *pfn
, void *pvData
, void *pvHint
,
673 int *piIndex
, int *piIndexSel
)
675 FIXME("(%p, %p, %p, 0x%08x, %p, %p, %p, %p, %p)\n",
676 pts
, psf
, pidl
, flags
, pfn
, pvData
, pvHint
, piIndex
, piIndexSel
);
680 /*************************************************************************
681 * Shell_GetCachedImageIndex [SHELL32.72]
684 INT WINAPI
Shell_GetCachedImageIndexA(LPCSTR szPath
, INT nIndex
, UINT bSimulateDoc
)
689 WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath
), nIndex
, bSimulateDoc
);
691 len
= MultiByteToWideChar( CP_ACP
, 0, szPath
, -1, NULL
, 0 );
692 szTemp
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
693 MultiByteToWideChar( CP_ACP
, 0, szPath
, -1, szTemp
, len
);
695 ret
= SIC_GetIconIndex( szTemp
, nIndex
, 0 );
697 HeapFree( GetProcessHeap(), 0, szTemp
);
702 INT WINAPI
Shell_GetCachedImageIndexW(LPCWSTR szPath
, INT nIndex
, UINT bSimulateDoc
)
704 WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath
), nIndex
, bSimulateDoc
);
706 return SIC_GetIconIndex(szPath
, nIndex
, 0);
709 INT WINAPI
Shell_GetCachedImageIndexAW(LPCVOID szPath
, INT nIndex
, BOOL bSimulateDoc
)
710 { if( SHELL_OsIsUnicode())
711 return Shell_GetCachedImageIndexW(szPath
, nIndex
, bSimulateDoc
);
712 return Shell_GetCachedImageIndexA(szPath
, nIndex
, bSimulateDoc
);
715 /*************************************************************************
716 * ExtractIconExW [SHELL32.@]
719 * -1 file is not valid
720 * or number of icons extracted
722 UINT WINAPI
ExtractIconExW(LPCWSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
724 /* get entry point of undocumented function PrivateExtractIconExW() in user32 */
725 #if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)
726 static UINT (WINAPI
*PrivateExtractIconExW
)(LPCWSTR
,int,HICON
*,HICON
*,UINT
) = NULL
;
728 if (!PrivateExtractIconExW
) {
729 HMODULE hUser32
= GetModuleHandleA("user32");
730 PrivateExtractIconExW
= (UINT(WINAPI
*)(LPCWSTR
,int,HICON
*,HICON
*,UINT
)) GetProcAddress(hUser32
, "PrivateExtractIconExW");
732 if (!PrivateExtractIconExW
)
737 TRACE("%s %i %p %p %i\n", debugstr_w(lpszFile
), nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
739 return PrivateExtractIconExW(lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
742 /*************************************************************************
743 * ExtractIconExA [SHELL32.@]
745 UINT WINAPI
ExtractIconExA(LPCSTR lpszFile
, INT nIconIndex
, HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIcons
)
748 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, NULL
, 0);
749 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
751 TRACE("%s %i %p %p %i\n", lpszFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
755 MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, lpwstrFile
, len
);
756 ret
= ExtractIconExW(lpwstrFile
, nIconIndex
, phiconLarge
, phiconSmall
, nIcons
);
757 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
762 /*************************************************************************
763 * ExtractAssociatedIconA (SHELL32.@)
765 * Return icon for given file (either from file itself or from associated
766 * executable) and patch parameters if needed.
768 HICON WINAPI
ExtractAssociatedIconA(HINSTANCE hInst
, LPSTR lpIconPath
, LPWORD lpiIcon
)
771 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpIconPath
, -1, NULL
, 0);
772 /* Note that we need to allocate MAX_PATH, since we are supposed to fill
773 * the correct executable if there is no icon in lpIconPath directly.
774 * lpIconPath itself is supposed to be large enough, so make sure lpIconPathW
775 * is large enough too. Yes, I am puking too.
777 LPWSTR lpIconPathW
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
779 TRACE("%p %s %p\n", hInst
, debugstr_a(lpIconPath
), lpiIcon
);
783 MultiByteToWideChar(CP_ACP
, 0, lpIconPath
, -1, lpIconPathW
, len
);
784 hIcon
= ExtractAssociatedIconW(hInst
, lpIconPathW
, lpiIcon
);
785 WideCharToMultiByte(CP_ACP
, 0, lpIconPathW
, -1, lpIconPath
, MAX_PATH
, NULL
, NULL
);
786 HeapFree(GetProcessHeap(), 0, lpIconPathW
);
791 /*************************************************************************
792 * ExtractAssociatedIconW (SHELL32.@)
794 * Return icon for given file (either from file itself or from associated
795 * executable) and patch parameters if needed.
797 HICON WINAPI
ExtractAssociatedIconW(HINSTANCE hInst
, LPWSTR lpIconPath
, LPWORD lpiIcon
)
802 TRACE("%p %s %p\n", hInst
, debugstr_w(lpIconPath
), lpiIcon
);
805 lpiIcon
= &wDummyIcon
;
807 hIcon
= ExtractIconW(hInst
, lpIconPath
, *lpiIcon
);
809 if( hIcon
< (HICON
)2 )
810 { if( hIcon
== (HICON
)1 ) /* no icons found in given file */
811 { WCHAR tempPath
[MAX_PATH
];
812 HINSTANCE uRet
= FindExecutableW(lpIconPath
,NULL
,tempPath
);
814 if( uRet
> (HINSTANCE
)32 && tempPath
[0] )
815 { wcscpy(lpIconPath
,tempPath
);
816 hIcon
= ExtractIconW(hInst
, lpIconPath
, *lpiIcon
);
817 if( hIcon
> (HICON
)2 )
822 if( hIcon
== (HICON
)1 )
823 *lpiIcon
= 2; /* MSDOS icon - we found .exe but no icons in it */
825 *lpiIcon
= 6; /* generic icon - found nothing */
827 if (GetModuleFileNameW(hInst
, lpIconPath
, MAX_PATH
))
828 hIcon
= LoadIconW(hInst
, MAKEINTRESOURCEW(*lpiIcon
));
833 /*************************************************************************
834 * ExtractAssociatedIconExW (SHELL32.@)
836 * Return icon for given file (either from file itself or from associated
837 * executable) and patch parameters if needed.
839 HICON WINAPI
ExtractAssociatedIconExW(HINSTANCE hInst
, LPWSTR lpIconPath
, LPWORD lpiIconIdx
, LPWORD lpiIconId
)
841 FIXME("%p %s %p %p): stub\n", hInst
, debugstr_w(lpIconPath
), lpiIconIdx
, lpiIconId
);
845 /*************************************************************************
846 * ExtractAssociatedIconExA (SHELL32.@)
848 * Return icon for given file (either from file itself or from associated
849 * executable) and patch parameters if needed.
851 HICON WINAPI
ExtractAssociatedIconExA(HINSTANCE hInst
, LPSTR lpIconPath
, LPWORD lpiIconIdx
, LPWORD lpiIconId
)
854 INT len
= MultiByteToWideChar( CP_ACP
, 0, lpIconPath
, -1, NULL
, 0 );
855 LPWSTR lpwstrFile
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
857 TRACE("%p %s %p %p)\n", hInst
, lpIconPath
, lpiIconIdx
, lpiIconId
);
859 MultiByteToWideChar( CP_ACP
, 0, lpIconPath
, -1, lpwstrFile
, len
);
860 ret
= ExtractAssociatedIconExW(hInst
, lpwstrFile
, lpiIconIdx
, lpiIconId
);
861 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
866 /****************************************************************************
867 * SHDefExtractIconW [SHELL32.@]
869 HRESULT WINAPI
SHDefExtractIconW(LPCWSTR pszIconFile
, int iIndex
, UINT uFlags
,
870 HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIconSize
)
874 WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile
), iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
876 ret
= PrivateExtractIconsW(pszIconFile
, iIndex
, nIconSize
, nIconSize
, hIcons
, NULL
, 2, LR_DEFAULTCOLOR
);
877 /* FIXME: deal with uFlags parameter which contains GIL_ flags */
878 if (ret
== 0xFFFFFFFF)
882 *phiconLarge
= hIcons
[0];
884 DestroyIcon(hIcons
[0]);
886 *phiconSmall
= hIcons
[1];
888 DestroyIcon(hIcons
[1]);
894 /****************************************************************************
895 * SHDefExtractIconA [SHELL32.@]
897 HRESULT WINAPI
SHDefExtractIconA(LPCSTR pszIconFile
, int iIndex
, UINT uFlags
,
898 HICON
* phiconLarge
, HICON
* phiconSmall
, UINT nIconSize
)
901 INT len
= MultiByteToWideChar(CP_ACP
, 0, pszIconFile
, -1, NULL
, 0);
902 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
904 TRACE("%s %d 0x%08x %p %p %d\n", pszIconFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
906 MultiByteToWideChar(CP_ACP
, 0, pszIconFile
, -1, lpwstrFile
, len
);
907 ret
= SHDefExtractIconW(lpwstrFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
908 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
912 /****************************************************************************
913 * SHGetIconOverlayIndexA [SHELL32.@]
915 * Returns the index of the overlay icon in the system image list.
917 INT WINAPI
SHGetIconOverlayIndexA(LPCSTR pszIconPath
, INT iIconIndex
)
919 FIXME("%s, %d\n", debugstr_a(pszIconPath
), iIconIndex
);
924 /****************************************************************************
925 * SHGetIconOverlayIndexW [SHELL32.@]
927 * Returns the index of the overlay icon in the system image list.
929 INT WINAPI
SHGetIconOverlayIndexW(LPCWSTR pszIconPath
, INT iIconIndex
)
931 FIXME("%s, %d\n", debugstr_w(pszIconPath
), iIconIndex
);