-/*\r
- * shell icon cache (SIC)\r
- *\r
- * Copyright 1998, 1999 Juergen Schmied\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-\r
-#include "config.h"\r
-#include "wine/port.h"\r
-\r
-#include <stdarg.h>\r
-#include <string.h>\r
-#include <sys/types.h>\r
-#ifdef HAVE_UNISTD_H\r
-# include <unistd.h>\r
-#endif\r
-\r
-#define COBJMACROS\r
-\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "wingdi.h"\r
-#include "winuser.h"\r
-#include "winreg.h"\r
-#include "wine/debug.h"\r
-\r
-#include "shellapi.h"\r
-#include "objbase.h"\r
-#include "shlguid.h"\r
-#include "pidl.h"\r
-#include "shell32_main.h"\r
-#include "undocshell.h"\r
-#include "shlwapi.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(shell);\r
-\r
-/********************** THE ICON CACHE ********************************/\r
-\r
-#define INVALID_INDEX -1\r
-\r
-typedef struct\r
-{\r
- LPWSTR sSourceFile; /* file (not path!) containing the icon */\r
- DWORD dwSourceIndex; /* index within the file, if it is a resoure ID it will be negated */\r
- DWORD dwListIndex; /* index within the iconlist */\r
- DWORD dwFlags; /* GIL_* flags */\r
- DWORD dwAccessTime;\r
-} SIC_ENTRY, * LPSIC_ENTRY;\r
-\r
-static HDPA sic_hdpa = 0;\r
-\r
-static CRITICAL_SECTION SHELL32_SicCS;\r
-static CRITICAL_SECTION_DEBUG critsect_debug =\r
-{\r
- 0, 0, &SHELL32_SicCS,\r
- { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },\r
- 0, 0, { 0, (DWORD)(__FILE__ ": SHELL32_SicCS") }\r
-};\r
-static CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 };\r
-\r
-/*****************************************************************************\r
- * SIC_CompareEntries\r
- *\r
- * NOTES\r
- * Callback for DPA_Search\r
- */\r
-static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam)\r
-{ TRACE("%p %p %8lx\n", p1, p2, lparam);\r
-\r
- if (((LPSIC_ENTRY)p1)->dwSourceIndex != ((LPSIC_ENTRY)p2)->dwSourceIndex) /* first the faster one*/\r
- return 1;\r
-\r
- if (strcmpiW(((LPSIC_ENTRY)p1)->sSourceFile,((LPSIC_ENTRY)p2)->sSourceFile))\r
- return 1;\r
-\r
- return 0;\r
-}\r
-/*****************************************************************************\r
- * SIC_IconAppend [internal]\r
- *\r
- * NOTES\r
- * appends an icon pair to the end of the cache\r
- */\r
-static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallIcon, HICON hBigIcon)\r
-{ LPSIC_ENTRY lpsice;\r
- INT ret, index, index1;\r
- WCHAR path[MAX_PATH];\r
- TRACE("%s %i %p %p\n", debugstr_w(sSourceFile), dwSourceIndex, hSmallIcon ,hBigIcon);\r
-\r
- lpsice = (LPSIC_ENTRY) SHAlloc (sizeof (SIC_ENTRY));\r
-\r
- GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL);\r
- lpsice->sSourceFile = HeapAlloc( GetProcessHeap(), 0, (strlenW(path)+1)*sizeof(WCHAR) );\r
- strcpyW( lpsice->sSourceFile, path );\r
-\r
- lpsice->dwSourceIndex = dwSourceIndex;\r
-\r
- EnterCriticalSection(&SHELL32_SicCS);\r
-\r
- index = DPA_InsertPtr(sic_hdpa, 0x7fff, lpsice);\r
- if ( INVALID_INDEX == index )\r
- {\r
- HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile);\r
- SHFree(lpsice);\r
- ret = INVALID_INDEX;\r
- }\r
- else\r
- {\r
- index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon);\r
- index1= ImageList_AddIcon (ShellBigIconList, hBigIcon);\r
-\r
- if (index!=index1)\r
- {\r
- FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1);\r
- }\r
- lpsice->dwListIndex = index;\r
- ret = lpsice->dwListIndex;\r
- }\r
-\r
- LeaveCriticalSection(&SHELL32_SicCS);\r
- return ret;\r
-}\r
-/****************************************************************************\r
- * SIC_LoadIcon [internal]\r
- *\r
- * NOTES\r
- * gets small/big icon by number from a file\r
- */\r
-static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex)\r
-{ HICON hiconLarge=0;\r
- HICON hiconSmall=0;\r
-\r
-#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)\r
- static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL;\r
-\r
- if (!PrivateExtractIconExW) {\r
- HMODULE hUser32 = GetModuleHandleA("user32");\r
- PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW");\r
- }\r
-\r
- if (PrivateExtractIconExW)\r
- PrivateExtractIconExW(sSourceFile, dwSourceIndex, &hiconLarge, &hiconSmall, 1);\r
- else\r
-#endif\r
- {\r
- PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, 0);\r
- PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, 0);\r
- }\r
-\r
- if ( !hiconLarge || !hiconSmall)\r
- {\r
- WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall);\r
- return -1;\r
- }\r
- return SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge);\r
-}\r
-/*****************************************************************************\r
- * SIC_GetIconIndex [internal]\r
- *\r
- * Parameters\r
- * sSourceFile [IN] filename of file containing the icon\r
- * index [IN] index/resID (negated) in this file\r
- *\r
- * NOTES\r
- * look in the cache for a proper icon. if not available the icon is taken\r
- * from the file and cached\r
- */\r
-INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex )\r
-{\r
- SIC_ENTRY sice;\r
- INT ret, index = INVALID_INDEX;\r
- WCHAR path[MAX_PATH];\r
-\r
- TRACE("%s %i\n", debugstr_w(sSourceFile), dwSourceIndex);\r
-\r
- GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL);\r
- sice.sSourceFile = path;\r
- sice.dwSourceIndex = dwSourceIndex;\r
-\r
- EnterCriticalSection(&SHELL32_SicCS);\r
-\r
- if (NULL != DPA_GetPtr (sic_hdpa, 0))\r
- {\r
- /* search linear from position 0*/\r
- index = DPA_Search (sic_hdpa, &sice, 0, SIC_CompareEntries, 0, 0);\r
- }\r
-\r
- if ( INVALID_INDEX == index )\r
- {\r
- ret = SIC_LoadIcon (sSourceFile, dwSourceIndex);\r
- }\r
- else\r
- {\r
- TRACE("-- found\n");\r
- ret = ((LPSIC_ENTRY)DPA_GetPtr(sic_hdpa, index))->dwListIndex;\r
- }\r
-\r
- LeaveCriticalSection(&SHELL32_SicCS);\r
- return ret;\r
-}\r
-/*****************************************************************************\r
- * SIC_Initialize [internal]\r
- *\r
- * NOTES\r
- * hack to load the resources from the shell32.dll under a different dll name\r
- * will be removed when the resource-compiler is ready\r
- */\r
-BOOL SIC_Initialize(void)\r
-{\r
- HICON hSm, hLg;\r
- UINT index;\r
- int cx_small, cy_small;\r
- int cx_large, cy_large;\r
-\r
- cx_small = GetSystemMetrics(SM_CXSMICON);\r
- cy_small = GetSystemMetrics(SM_CYSMICON);\r
- cx_large = GetSystemMetrics(SM_CXICON);\r
- cy_large = GetSystemMetrics(SM_CYICON);\r
-\r
- TRACE("\n");\r
-\r
- if (sic_hdpa) /* already initialized?*/\r
- return TRUE;\r
-\r
- sic_hdpa = DPA_Create(16);\r
-\r
- if (!sic_hdpa)\r
- {\r
- return(FALSE);\r
- }\r
-\r
- ShellSmallIconList = ImageList_Create(16,16,ILC_COLOR32|ILC_MASK,0,0x20);\r
- ShellBigIconList = ImageList_Create(32,32,ILC_COLOR32|ILC_MASK,0,0x20);\r
-\r
- ImageList_SetBkColor(ShellSmallIconList, CLR_NONE);\r
- ImageList_SetBkColor(ShellBigIconList, CLR_NONE);\r
-\r
- for (index=1; index<39; index++)\r
- {\r
- hSm = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_small, cy_small, LR_SHARED);\r
- hLg = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_large, cy_large, LR_SHARED);\r
-\r
- if(!hSm)\r
- {\r
- hSm = LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(1), IMAGE_ICON, cx_small, cy_small, LR_SHARED);\r
- hLg = LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(1), IMAGE_ICON, cx_large, cy_large, LR_SHARED);\r
- }\r
- SIC_IconAppend (swShell32Name, index, hSm, hLg);\r
- }\r
-\r
- TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);\r
-\r
- return TRUE;\r
-}\r
-/*************************************************************************\r
- * SIC_Destroy\r
- *\r
- * frees the cache\r
- */\r
-static INT CALLBACK sic_free( LPVOID ptr, LPVOID lparam )\r
-{\r
- HeapFree(GetProcessHeap(), 0, ((LPSIC_ENTRY)ptr)->sSourceFile);\r
- SHFree(ptr);\r
- return TRUE;\r
-}\r
-\r
-void SIC_Destroy(void)\r
-{\r
- TRACE("\n");\r
-\r
- EnterCriticalSection(&SHELL32_SicCS);\r
-\r
- if (sic_hdpa) DPA_DestroyCallback(sic_hdpa, sic_free, NULL );\r
-\r
- sic_hdpa = NULL;\r
- ImageList_Destroy(ShellSmallIconList);\r
- ShellSmallIconList = 0;\r
- ImageList_Destroy(ShellBigIconList);\r
- ShellBigIconList = 0;\r
-\r
- LeaveCriticalSection(&SHELL32_SicCS);\r
- DeleteCriticalSection(&SHELL32_SicCS);\r
-}\r
-\r
-/*************************************************************************\r
- * Shell_GetImageList [SHELL32.71]\r
- *\r
- * PARAMETERS\r
- * imglist[1|2] [OUT] pointer which receives imagelist handles\r
- *\r
- */\r
-BOOL WINAPI Shell_GetImageList(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList)\r
-{ TRACE("(%p,%p)\n",lpBigList,lpSmallList);\r
- if (lpBigList)\r
- { *lpBigList = ShellBigIconList;\r
- }\r
- if (lpSmallList)\r
- { *lpSmallList = ShellSmallIconList;\r
- }\r
-\r
- return TRUE;\r
-}\r
-/*************************************************************************\r
- * PidlToSicIndex [INTERNAL]\r
- *\r
- * PARAMETERS\r
- * sh [IN] IShellFolder\r
- * pidl [IN]\r
- * bBigIcon [IN]\r
- * uFlags [IN] GIL_*\r
- * pIndex [OUT] index within the SIC\r
- *\r
- */\r
-BOOL PidlToSicIndex (\r
- IShellFolder * sh,\r
- LPCITEMIDLIST pidl,\r
- BOOL bBigIcon,\r
- UINT uFlags,\r
- int * pIndex)\r
-{\r
- IExtractIconW *ei;\r
- WCHAR szIconFile[MAX_PATH]; /* file containing the icon */\r
- INT iSourceIndex; /* index or resID(negated) in this file */\r
- BOOL ret = FALSE;\r
- UINT dwFlags = 0;\r
-\r
- TRACE("sf=%p pidl=%p %s\n", sh, pidl, bBigIcon?"Big":"Small");\r
-\r
- if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh, 0, 1, &pidl, &IID_IExtractIconW, 0, (void **)&ei)))\r
- {\r
- if (SUCCEEDED(IExtractIconW_GetIconLocation(ei, uFlags, szIconFile, MAX_PATH, &iSourceIndex, &dwFlags)))\r
- {\r
- *pIndex = SIC_GetIconIndex(szIconFile, iSourceIndex);\r
- ret = TRUE;\r
- }\r
- IExtractIconW_Release(ei);\r
- }\r
-\r
- if (INVALID_INDEX == *pIndex) /* default icon when failed */\r
- *pIndex = 0;\r
-\r
- return ret;\r
-\r
-}\r
-\r
-/*************************************************************************\r
- * SHMapPIDLToSystemImageListIndex [SHELL32.77]\r
- *\r
- * PARAMETERS\r
- * sh [IN] pointer to an instance of IShellFolder\r
- * pidl [IN]\r
- * pIndex [OUT][OPTIONAL] SIC index for big icon\r
- *\r
- */\r
-int WINAPI SHMapPIDLToSystemImageListIndex(\r
- IShellFolder *sh,\r
- LPCITEMIDLIST pidl,\r
- int *pIndex)\r
-{\r
- int Index;\r
-\r
- TRACE("(SF=%p,pidl=%p,%p)\n",sh,pidl,pIndex);\r
- pdump(pidl);\r
-\r
- if (pIndex)\r
- if (!PidlToSicIndex ( sh, pidl, 1, 0, pIndex))\r
- *pIndex = -1; \r
-\r
- if (!PidlToSicIndex ( sh, pidl, 0, 0, &Index))\r
- return -1;\r
-\r
- return Index;\r
-}\r
-\r
-/*************************************************************************\r
- * Shell_GetCachedImageIndex [SHELL32.72]\r
- *\r
- */\r
-INT WINAPI Shell_GetCachedImageIndexA(LPCSTR szPath, INT nIndex, BOOL bSimulateDoc)\r
-{\r
- INT ret, len;\r
- LPWSTR szTemp;\r
-\r
- WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath), nIndex, bSimulateDoc);\r
-\r
- len = MultiByteToWideChar( CP_ACP, 0, szPath, -1, NULL, 0 );\r
- szTemp = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );\r
- MultiByteToWideChar( CP_ACP, 0, szPath, -1, szTemp, len );\r
-\r
- ret = SIC_GetIconIndex( szTemp, nIndex );\r
-\r
- HeapFree( GetProcessHeap(), 0, szTemp );\r
-\r
- return ret;\r
-}\r
-\r
-INT WINAPI Shell_GetCachedImageIndexW(LPCWSTR szPath, INT nIndex, BOOL bSimulateDoc)\r
-{\r
- WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath), nIndex, bSimulateDoc);\r
-\r
- return SIC_GetIconIndex(szPath, nIndex);\r
-}\r
-\r
-INT WINAPI Shell_GetCachedImageIndexAW(LPCVOID szPath, INT nIndex, BOOL bSimulateDoc)\r
-{ if( SHELL_OsIsUnicode())\r
- return Shell_GetCachedImageIndexW(szPath, nIndex, bSimulateDoc);\r
- return Shell_GetCachedImageIndexA(szPath, nIndex, bSimulateDoc);\r
-}\r
-\r
-/*************************************************************************\r
- * ExtractIconEx [SHELL32.@]\r
- */\r
-UINT WINAPI ExtractIconExAW(LPCVOID lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons)\r
-{ if (SHELL_OsIsUnicode())\r
- return ExtractIconExW ( lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);\r
- return ExtractIconExA ( lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);\r
-}\r
-\r
-/*************************************************************************\r
- * ExtractIconExW [SHELL32.@]\r
- * RETURNS\r
- * 0 no icon found\r
- * -1 file is not valid\r
- * or number of icons extracted\r
- */\r
-UINT WINAPI ExtractIconExW(LPCWSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons)\r
-{\r
- /* get entry point of undocumented function PrivateExtractIconExW() in user32 */\r
-#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)\r
- static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL;\r
-\r
- if (!PrivateExtractIconExW) {\r
- HMODULE hUser32 = GetModuleHandleA("user32");\r
- PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW");\r
-\r
- if (!PrivateExtractIconExW)\r
- return 0;\r
- }\r
-#endif\r
-\r
- TRACE("%s %i %p %p %i\n", debugstr_w(lpszFile), nIconIndex, phiconLarge, phiconSmall, nIcons);\r
-\r
- return PrivateExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);\r
-}\r
-\r
-/*************************************************************************\r
- * ExtractIconExA [SHELL32.@]\r
- */\r
-UINT WINAPI ExtractIconExA(LPCSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons)\r
-{\r
- UINT ret;\r
- INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0);\r
- LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));\r
-\r
- TRACE("%s %i %p %p %i\n", lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);\r
-\r
- MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len);\r
- ret = ExtractIconExW (lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIcons);\r
- HeapFree(GetProcessHeap(), 0, lpwstrFile);\r
- return ret;\r
-}\r
-\r
-/*************************************************************************\r
- * ExtractAssociatedIconA (SHELL32.@)\r
- *\r
- * Return icon for given file (either from file itself or from associated\r
- * executable) and patch parameters if needed.\r
- */\r
-HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon)\r
-{ \r
- HICON hIcon;\r
- WORD wDummyIcon = 0;\r
- \r
- TRACE("\n");\r
-\r
- if(lpiIcon == NULL)\r
- lpiIcon = &wDummyIcon;\r
-\r
- hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon);\r
-\r
- if( hIcon < (HICON)2 )\r
- { if( hIcon == (HICON)1 ) /* no icons found in given file */\r
- { char tempPath[0x80];\r
- HINSTANCE uRet = FindExecutableA(lpIconPath,NULL,tempPath);\r
-\r
- if( uRet > (HINSTANCE)32 && tempPath[0] )\r
- { strcpy(lpIconPath,tempPath);\r
- hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon);\r
- if( hIcon > (HICON)2 )\r
- return hIcon;\r
- }\r
- else hIcon = 0;\r
- }\r
-\r
- if( hIcon == (HICON)1 )\r
- *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */\r
- else\r
- *lpiIcon = 6; /* generic icon - found nothing */\r
-\r
- if (GetModuleFileNameA(hInst, lpIconPath, 0x80))\r
- {\r
- /* terminate string (GetModuleFileName doesn't do if buffer is too small) */\r
- lpIconPath[0x80 - 1] = '\0';\r
- hIcon = LoadIconA( hInst, MAKEINTRESOURCEA(*lpiIcon));\r
- }\r
- }\r
- return hIcon;\r
-}\r
-\r
-/*************************************************************************\r
- * ExtractAssociatedIconExW (SHELL32.@)\r
- *\r
- * Return icon for given file (either from file itself or from associated\r
- * executable) and patch parameters if needed.\r
- */\r
-HICON WINAPI ExtractAssociatedIconExW(HINSTANCE hInst, LPWSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId)\r
-{\r
- FIXME("%p %s %p %p): stub\n", hInst, debugstr_w(lpIconPath), lpiIconIdx, lpiIconId);\r
- return 0;\r
-}\r
-\r
-/*************************************************************************\r
- * ExtractAssociatedIconExA (SHELL32.@)\r
- *\r
- * Return icon for given file (either from file itself or from associated\r
- * executable) and patch parameters if needed.\r
- */\r
-HICON WINAPI ExtractAssociatedIconExA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId)\r
-{\r
- HICON ret;\r
- INT len = MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, NULL, 0 );\r
- LPWSTR lpwstrFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );\r
-\r
- TRACE("%p %s %p %p)\n", hInst, lpIconPath, lpiIconIdx, lpiIconId);\r
-\r
- MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, lpwstrFile, len );\r
- ret = ExtractAssociatedIconExW(hInst, lpwstrFile, lpiIconIdx, lpiIconId);\r
- HeapFree(GetProcessHeap(), 0, lpwstrFile);\r
- return ret;\r
-}\r
-\r
-\r
-/****************************************************************************\r
- * SHDefExtractIconW [SHELL32.@]\r
- */\r
-HRESULT WINAPI SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags,\r
- HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize)\r
-{\r
- UINT ret;\r
- HICON hIcons[2];\r
- WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile), iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);\r
-\r
- ret = PrivateExtractIconsW(pszIconFile, iIndex, nIconSize, nIconSize, hIcons, NULL, 2, LR_DEFAULTCOLOR);\r
- /* FIXME: deal with uFlags parameter which contains GIL_ flags */\r
- if (ret == 0xFFFFFFFF)\r
- return E_FAIL;\r
- if (ret > 0) {\r
- *phiconLarge = hIcons[0];\r
- *phiconSmall = hIcons[1];\r
- return S_OK;\r
- }\r
- return S_FALSE;\r
-}\r
-\r
-/****************************************************************************\r
- * SHDefExtractIconA [SHELL32.@]\r
- */\r
-HRESULT WINAPI SHDefExtractIconA(LPCSTR pszIconFile, int iIndex, UINT uFlags,\r
- HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize)\r
-{\r
- HRESULT ret;\r
- INT len = MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, NULL, 0);\r
- LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));\r
-\r
- TRACE("%s %d 0x%08x %p %p %d\n", pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);\r
-\r
- MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, lpwstrFile, len);\r
- ret = SHDefExtractIconW(lpwstrFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);\r
- HeapFree(GetProcessHeap(), 0, lpwstrFile);\r
- return ret;\r
-}\r
+/*
+ * shell icon cache (SIC)
+ *
+ * Copyright 1998, 1999 Juergen Schmied
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "wine/debug.h"
+
+#include "shellapi.h"
+#include "objbase.h"
+#include "shlguid.h"
+#include "pidl.h"
+#include "shell32_main.h"
+#include "undocshell.h"
+#include "shresdef.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+/********************** THE ICON CACHE ********************************/
+
+#define INVALID_INDEX -1
+
+typedef struct
+{
+ LPWSTR sSourceFile; /* file (not path!) containing the icon */
+ DWORD dwSourceIndex; /* index within the file, if it is a resoure ID it will be negated */
+ DWORD dwListIndex; /* index within the iconlist */
+ DWORD dwFlags; /* GIL_* flags */
+ DWORD dwAccessTime;
+} SIC_ENTRY, * LPSIC_ENTRY;
+
+static HDPA sic_hdpa = 0;
+
+static CRITICAL_SECTION SHELL32_SicCS;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+ 0, 0, &SHELL32_SicCS,
+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": SHELL32_SicCS") }
+};
+static CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+/*****************************************************************************
+ * SIC_CompareEntries
+ *
+ * NOTES
+ * Callback for DPA_Search
+ */
+static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam)
+{ LPSIC_ENTRY e1 = (LPSIC_ENTRY)p1, e2 = (LPSIC_ENTRY)p2;
+
+ TRACE("%p %p %8lx\n", p1, p2, lparam);
+
+ /* Icons in the cache are keyed by the name of the file they are
+ * loaded from, their resource index and the fact if they have a shortcut
+ * icon overlay or not.
+ */
+ if (e1->dwSourceIndex != e2->dwSourceIndex || /* first the faster one */
+ (e1->dwFlags & GIL_FORSHORTCUT) != (e2->dwFlags & GIL_FORSHORTCUT))
+ return 1;
+
+ if (strcmpiW(e1->sSourceFile,e2->sSourceFile))
+ return 1;
+
+ return 0;
+}
+
+/* declare SIC_LoadOverlayIcon() */
+static int SIC_LoadOverlayIcon(int idx);
+
+/*****************************************************************************
+ * SIC_OverlayShortcutImage [internal]
+ *
+ * NOTES
+ * Creates a new icon as a copy of the passed-in icon, overlayed with a
+ * shortcut image.
+ */
+static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large)
+{ ICONINFO SourceIconInfo, ShortcutIconInfo, TargetIconInfo;
+ HICON ShortcutIcon, TargetIcon;
+ BITMAP SourceBitmapInfo, ShortcutBitmapInfo;
+ HDC SourceDC = NULL,
+ ShortcutDC = NULL,
+ TargetDC = NULL,
+ ScreenDC = NULL;
+ HBITMAP OldSourceBitmap = NULL,
+ OldShortcutBitmap = NULL,
+ OldTargetBitmap = NULL;
+
+ static int s_imgListIdx = -1;
+
+ /* Get information about the source icon and shortcut overlay */
+ if (! GetIconInfo(SourceIcon, &SourceIconInfo)
+ || 0 == GetObjectW(SourceIconInfo.hbmColor, sizeof(BITMAP), &SourceBitmapInfo))
+ {
+ return NULL;
+ }
+
+ /* search for the shortcut icon only once */
+ if (s_imgListIdx == -1)
+ s_imgListIdx = SIC_LoadOverlayIcon(- IDI_SHELL_SHORTCUT);
+ /* FIXME should use icon index 29 instead of the
+ resource id, but not all icons are present yet
+ so we can't use icon indices */
+
+ if (s_imgListIdx != -1)
+ {
+ if (large)
+ ShortcutIcon = ImageList_GetIcon(ShellBigIconList, s_imgListIdx, ILD_TRANSPARENT);
+ else
+ ShortcutIcon = ImageList_GetIcon(ShellSmallIconList, s_imgListIdx, ILD_TRANSPARENT);
+ } else
+ ShortcutIcon = NULL;
+
+ if (NULL == ShortcutIcon
+ || ! GetIconInfo(ShortcutIcon, &ShortcutIconInfo)
+ || 0 == GetObjectW(ShortcutIconInfo.hbmColor, sizeof(BITMAP), &ShortcutBitmapInfo))
+ {
+ return NULL;
+ }
+
+ TargetIconInfo = SourceIconInfo;
+ TargetIconInfo.hbmMask = NULL;
+ TargetIconInfo.hbmColor = NULL;
+
+ /* Setup the source, shortcut and target masks */
+ SourceDC = CreateCompatibleDC(NULL);
+ if (NULL == SourceDC) goto fail;
+ OldSourceBitmap = SelectObject(SourceDC, SourceIconInfo.hbmMask);
+ if (NULL == OldSourceBitmap) goto fail;
+
+ ShortcutDC = CreateCompatibleDC(NULL);
+ if (NULL == ShortcutDC) goto fail;
+ OldShortcutBitmap = SelectObject(ShortcutDC, ShortcutIconInfo.hbmMask);
+ if (NULL == OldShortcutBitmap) goto fail;
+
+ TargetDC = CreateCompatibleDC(NULL);
+ if (NULL == TargetDC) goto fail;
+ TargetIconInfo.hbmMask = CreateCompatibleBitmap(TargetDC, SourceBitmapInfo.bmWidth,
+ SourceBitmapInfo.bmHeight);
+ if (NULL == TargetIconInfo.hbmMask) goto fail;
+ ScreenDC = GetDC(NULL);
+ if (NULL == ScreenDC) goto fail;
+ TargetIconInfo.hbmColor = CreateCompatibleBitmap(ScreenDC, SourceBitmapInfo.bmWidth,
+ SourceBitmapInfo.bmHeight);
+ ReleaseDC(NULL, ScreenDC);
+ if (NULL == TargetIconInfo.hbmColor) goto fail;
+ OldTargetBitmap = SelectObject(TargetDC, TargetIconInfo.hbmMask);
+ if (NULL == OldTargetBitmap) goto fail;
+
+ /* Create the target mask by ANDing the source and shortcut masks */
+ if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight,
+ SourceDC, 0, 0, SRCCOPY) ||
+ ! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
+ ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+ ShortcutDC, 0, 0, SRCAND))
+ {
+ goto fail;
+ }
+
+ /* Setup the source and target xor bitmap */
+ if (NULL == SelectObject(SourceDC, SourceIconInfo.hbmColor) ||
+ NULL == SelectObject(TargetDC, TargetIconInfo.hbmColor))
+ {
+ goto fail;
+ }
+
+ /* Copy the source xor bitmap to the target and clear out part of it by using
+ the shortcut mask */
+ if (! BitBlt(TargetDC, 0, 0, SourceBitmapInfo.bmWidth, SourceBitmapInfo.bmHeight,
+ SourceDC, 0, 0, SRCCOPY) ||
+ ! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
+ ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+ ShortcutDC, 0, 0, SRCAND))
+ {
+ goto fail;
+ }
+
+ if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor)) goto fail;
+
+ /* Now put in the shortcut xor mask */
+ if (! BitBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight,
+ ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight,
+ ShortcutDC, 0, 0, SRCINVERT))
+ {
+ goto fail;
+ }
+
+ /* Clean up, we're not goto'ing to 'fail' after this so we can be lazy and not set
+ handles to NULL */
+ SelectObject(TargetDC, OldTargetBitmap);
+ DeleteObject(TargetDC);
+ SelectObject(ShortcutDC, OldShortcutBitmap);
+ DeleteObject(ShortcutDC);
+ SelectObject(SourceDC, OldSourceBitmap);
+ DeleteObject(SourceDC);
+
+ /* Create the icon using the bitmaps prepared earlier */
+ TargetIcon = CreateIconIndirect(&TargetIconInfo);
+
+ /* CreateIconIndirect copies the bitmaps, so we can release our bitmaps now */
+ DeleteObject(TargetIconInfo.hbmColor);
+ DeleteObject(TargetIconInfo.hbmMask);
+
+ return TargetIcon;
+
+fail:
+ /* Clean up scratch resources we created */
+ if (NULL != OldTargetBitmap) SelectObject(TargetDC, OldTargetBitmap);
+ if (NULL != TargetIconInfo.hbmColor) DeleteObject(TargetIconInfo.hbmColor);
+ if (NULL != TargetIconInfo.hbmMask) DeleteObject(TargetIconInfo.hbmMask);
+ if (NULL != TargetDC) DeleteObject(TargetDC);
+ if (NULL != OldShortcutBitmap) SelectObject(ShortcutDC, OldShortcutBitmap);
+ if (NULL != ShortcutDC) DeleteObject(ShortcutDC);
+ if (NULL != OldSourceBitmap) SelectObject(SourceDC, OldSourceBitmap);
+ if (NULL != SourceDC) DeleteObject(SourceDC);
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * SIC_IconAppend [internal]
+ *
+ * NOTES
+ * appends an icon pair to the end of the cache
+ */
+static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallIcon, HICON hBigIcon, DWORD dwFlags)
+{ LPSIC_ENTRY lpsice;
+ INT ret, index, index1;
+ WCHAR path[MAX_PATH];
+ TRACE("%s %i %p %p\n", debugstr_w(sSourceFile), dwSourceIndex, hSmallIcon ,hBigIcon);
+
+ lpsice = (LPSIC_ENTRY) SHAlloc (sizeof (SIC_ENTRY));
+
+ GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL);
+ lpsice->sSourceFile = HeapAlloc( GetProcessHeap(), 0, (strlenW(path)+1)*sizeof(WCHAR) );
+ strcpyW( lpsice->sSourceFile, path );
+
+ lpsice->dwSourceIndex = dwSourceIndex;
+ lpsice->dwFlags = dwFlags;
+
+ EnterCriticalSection(&SHELL32_SicCS);
+
+ index = DPA_InsertPtr(sic_hdpa, 0x7fff, lpsice);
+ if ( INVALID_INDEX == index )
+ {
+ HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile);
+ SHFree(lpsice);
+ ret = INVALID_INDEX;
+ }
+ else
+ {
+ index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon);
+ index1= ImageList_AddIcon (ShellBigIconList, hBigIcon);
+
+ if (index!=index1)
+ {
+ FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1);
+ }
+ lpsice->dwListIndex = index;
+ ret = lpsice->dwListIndex;
+ }
+
+ LeaveCriticalSection(&SHELL32_SicCS);
+ return ret;
+}
+/****************************************************************************
+ * SIC_LoadIcon [internal]
+ *
+ * NOTES
+ * gets small/big icon by number from a file
+ */
+static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags)
+{ HICON hiconLarge=0;
+ HICON hiconSmall=0;
+ HICON hiconLargeShortcut;
+ HICON hiconSmallShortcut;
+
+#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)
+ static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL;
+
+ if (!PrivateExtractIconExW) {
+ HMODULE hUser32 = GetModuleHandleA("user32");
+ PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW");
+ }
+
+ if (PrivateExtractIconExW)
+ PrivateExtractIconExW(sSourceFile, dwSourceIndex, &hiconLarge, &hiconSmall, 1);
+ else
+#endif
+ {
+ PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, 0);
+ PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, 0);
+ }
+
+ if ( !hiconLarge || !hiconSmall)
+ {
+ WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall);
+ return -1;
+ }
+
+ if (0 != (dwFlags & GIL_FORSHORTCUT))
+ {
+ hiconLargeShortcut = SIC_OverlayShortcutImage(hiconLarge, TRUE);
+ hiconSmallShortcut = SIC_OverlayShortcutImage(hiconSmall, FALSE);
+ if (NULL != hiconLargeShortcut && NULL != hiconSmallShortcut)
+ {
+ hiconLarge = hiconLargeShortcut;
+ hiconSmall = hiconSmallShortcut;
+ }
+ else
+ {
+ WARN("Failed to create shortcut overlayed icons\n");
+ if (NULL != hiconLargeShortcut) DestroyIcon(hiconLargeShortcut);
+ if (NULL != hiconSmallShortcut) DestroyIcon(hiconSmallShortcut);
+ dwFlags &= ~ GIL_FORSHORTCUT;
+ }
+ }
+
+ return SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge, dwFlags);
+}
+/*****************************************************************************
+ * SIC_GetIconIndex [internal]
+ *
+ * Parameters
+ * sSourceFile [IN] filename of file containing the icon
+ * index [IN] index/resID (negated) in this file
+ *
+ * NOTES
+ * look in the cache for a proper icon. if not available the icon is taken
+ * from the file and cached
+ */
+INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags )
+{
+ SIC_ENTRY sice;
+ INT ret, index = INVALID_INDEX;
+ WCHAR path[MAX_PATH];
+
+ TRACE("%s %i\n", debugstr_w(sSourceFile), dwSourceIndex);
+
+ GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL);
+ sice.sSourceFile = path;
+ sice.dwSourceIndex = dwSourceIndex;
+ sice.dwFlags = dwFlags;
+
+ EnterCriticalSection(&SHELL32_SicCS);
+
+ if (NULL != DPA_GetPtr (sic_hdpa, 0))
+ {
+ /* search linear from position 0*/
+ index = DPA_Search (sic_hdpa, &sice, 0, SIC_CompareEntries, 0, 0);
+ }
+
+ if ( INVALID_INDEX == index )
+ {
+ ret = SIC_LoadIcon (sSourceFile, dwSourceIndex, dwFlags);
+ }
+ else
+ {
+ TRACE("-- found\n");
+ ret = ((LPSIC_ENTRY)DPA_GetPtr(sic_hdpa, index))->dwListIndex;
+ }
+
+ LeaveCriticalSection(&SHELL32_SicCS);
+ return ret;
+}
+/*****************************************************************************
+ * SIC_Initialize [internal]
+ */
+BOOL SIC_Initialize(void)
+{
+ HICON hSm, hLg;
+ int cx_small, cy_small;
+ int cx_large, cy_large;
+
+ cx_small = GetSystemMetrics(SM_CXSMICON);
+ cy_small = GetSystemMetrics(SM_CYSMICON);
+ cx_large = GetSystemMetrics(SM_CXICON);
+ cy_large = GetSystemMetrics(SM_CYICON);
+
+ TRACE("\n");
+
+ if (sic_hdpa) /* already initialized?*/
+ return TRUE;
+
+ sic_hdpa = DPA_Create(16);
+
+ if (!sic_hdpa)
+ {
+ return(FALSE);
+ }
+
+ ShellSmallIconList = ImageList_Create(cx_small,cy_small,ILC_COLOR32|ILC_MASK,0,0x20);
+ ShellBigIconList = ImageList_Create(cx_large,cy_large,ILC_COLOR32|ILC_MASK,0,0x20);
+
+ ImageList_SetBkColor(ShellSmallIconList, CLR_NONE);
+ ImageList_SetBkColor(ShellBigIconList, CLR_NONE);
+
+ /* Load the document icon, which is used as the default if an icon isn't found. */
+ hSm = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(IDI_SHELL_DOCUMENT),
+ IMAGE_ICON, cx_small, cy_small, LR_SHARED);
+ hLg = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(IDI_SHELL_DOCUMENT),
+ IMAGE_ICON, cx_large, cy_large, LR_SHARED);
+
+ if (!hSm || !hLg)
+ {
+ FIXME("Failed to load IDI_SHELL_DOCUMENT icon!\n");
+ return FALSE;
+ }
+
+ SIC_IconAppend (swShell32Name, IDI_SHELL_DOCUMENT-1, hSm, hLg, 0);
+ SIC_IconAppend (swShell32Name, -IDI_SHELL_DOCUMENT, hSm, hLg, 0);
+
+ TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);
+
+ return TRUE;
+}
+/*************************************************************************
+ * SIC_Destroy
+ *
+ * frees the cache
+ */
+static INT CALLBACK sic_free( LPVOID ptr, LPVOID lparam )
+{
+ HeapFree(GetProcessHeap(), 0, ((LPSIC_ENTRY)ptr)->sSourceFile);
+ SHFree(ptr);
+ return TRUE;
+}
+
+void SIC_Destroy(void)
+{
+ TRACE("\n");
+
+ EnterCriticalSection(&SHELL32_SicCS);
+
+ if (sic_hdpa) DPA_DestroyCallback(sic_hdpa, sic_free, NULL );
+
+ sic_hdpa = NULL;
+ ImageList_Destroy(ShellSmallIconList);
+ ShellSmallIconList = 0;
+ ImageList_Destroy(ShellBigIconList);
+ ShellBigIconList = 0;
+
+ LeaveCriticalSection(&SHELL32_SicCS);
+}
+
+/*****************************************************************************
+ * SIC_LoadOverlayIcon [internal]
+ *
+ * Load a shell overlay icon and return its icon cache index.
+ */
+static int SIC_LoadOverlayIcon(int idx)
+{
+ WCHAR buffer[1024], wszIdx[8];
+ HKEY hKeyShellIcons;
+ LPCWSTR iconPath;
+ int iconIdx;
+
+ static const WCHAR wszShellIcons[] = {
+ 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
+ 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+ 'E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','I','c','o','n','s',0
+ };
+ static const WCHAR wszNumFmt[] = {'%','d',0};
+
+ iconPath = swShell32Name; /* default: load icon from shell32.dll */
+ iconIdx = idx;
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszShellIcons, 0, KEY_READ, &hKeyShellIcons) == ERROR_SUCCESS)
+ {
+ DWORD count = sizeof(buffer);
+
+ sprintfW(wszIdx, wszNumFmt, idx);
+
+ /* read icon path and index */
+ if (RegQueryValueExW(hKeyShellIcons, wszIdx, NULL, NULL, (LPBYTE)buffer, &count) == ERROR_SUCCESS)
+ {
+ LPWSTR p = strchrW(buffer, ',');
+
+ if (p)
+ *p++ = 0;
+
+ iconPath = buffer;
+ iconIdx = atoiW(p);
+ }
+
+ RegCloseKey(hKeyShellIcons);
+ }
+
+ return SIC_LoadIcon(iconPath, iconIdx, 0);
+}
+
+/*************************************************************************
+ * Shell_GetImageList [SHELL32.71]
+ *
+ * PARAMETERS
+ * imglist[1|2] [OUT] pointer which receives imagelist handles
+ *
+ */
+BOOL WINAPI Shell_GetImageList(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList)
+{ TRACE("(%p,%p)\n",lpBigList,lpSmallList);
+ if (lpBigList)
+ { *lpBigList = ShellBigIconList;
+ }
+ if (lpSmallList)
+ { *lpSmallList = ShellSmallIconList;
+ }
+
+ return TRUE;
+}
+/*************************************************************************
+ * PidlToSicIndex [INTERNAL]
+ *
+ * PARAMETERS
+ * sh [IN] IShellFolder
+ * pidl [IN]
+ * bBigIcon [IN]
+ * uFlags [IN] GIL_*
+ * pIndex [OUT] index within the SIC
+ *
+ */
+BOOL PidlToSicIndex (
+ IShellFolder * sh,
+ LPCITEMIDLIST pidl,
+ BOOL bBigIcon,
+ UINT uFlags,
+ int * pIndex)
+{
+ IExtractIconW *ei;
+ WCHAR szIconFile[MAX_PATH]; /* file containing the icon */
+ INT iSourceIndex; /* index or resID(negated) in this file */
+ BOOL ret = FALSE;
+ UINT dwFlags = 0;
+ int iShortcutDefaultIndex = INVALID_INDEX;
+
+ TRACE("sf=%p pidl=%p %s\n", sh, pidl, bBigIcon?"Big":"Small");
+
+ if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh, 0, 1, &pidl, &IID_IExtractIconW, 0, (void **)&ei)))
+ {
+ if (SUCCEEDED(IExtractIconW_GetIconLocation(ei, uFlags, szIconFile, MAX_PATH, &iSourceIndex, &dwFlags)))
+ {
+ *pIndex = SIC_GetIconIndex(szIconFile, iSourceIndex, uFlags);
+ ret = TRUE;
+ }
+ IExtractIconW_Release(ei);
+ }
+
+ if (INVALID_INDEX == *pIndex) /* default icon when failed */
+ {
+ if (0 == (uFlags & GIL_FORSHORTCUT))
+ {
+ *pIndex = 0;
+ }
+ else
+ {
+ if (INVALID_INDEX == iShortcutDefaultIndex)
+ {
+ iShortcutDefaultIndex = SIC_LoadIcon(swShell32Name, 0, GIL_FORSHORTCUT);
+ }
+ *pIndex = (INVALID_INDEX != iShortcutDefaultIndex ? iShortcutDefaultIndex : 0);
+ }
+ }
+
+ return ret;
+
+}
+
+/*************************************************************************
+ * SHMapPIDLToSystemImageListIndex [SHELL32.77]
+ *
+ * PARAMETERS
+ * sh [IN] pointer to an instance of IShellFolder
+ * pidl [IN]
+ * pIndex [OUT][OPTIONAL] SIC index for big icon
+ *
+ */
+int WINAPI SHMapPIDLToSystemImageListIndex(
+ IShellFolder *sh,
+ LPCITEMIDLIST pidl,
+ int *pIndex)
+{
+ int Index;
+ UINT uGilFlags = 0;
+
+ TRACE("(SF=%p,pidl=%p,%p)\n",sh,pidl,pIndex);
+ pdump(pidl);
+
+ if (SHELL_IsShortcut(pidl))
+ uGilFlags |= GIL_FORSHORTCUT;
+
+ if (pIndex)
+ if (!PidlToSicIndex ( sh, pidl, 1, uGilFlags, pIndex))
+ *pIndex = -1;
+
+ if (!PidlToSicIndex ( sh, pidl, 0, uGilFlags, &Index))
+ return -1;
+
+ return Index;
+}
+
+/*************************************************************************
+ * Shell_GetCachedImageIndex [SHELL32.72]
+ *
+ */
+INT WINAPI Shell_GetCachedImageIndexA(LPCSTR szPath, INT nIndex, BOOL bSimulateDoc)
+{
+ INT ret, len;
+ LPWSTR szTemp;
+
+ WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath), nIndex, bSimulateDoc);
+
+ len = MultiByteToWideChar( CP_ACP, 0, szPath, -1, NULL, 0 );
+ szTemp = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, szPath, -1, szTemp, len );
+
+ ret = SIC_GetIconIndex( szTemp, nIndex, 0 );
+
+ HeapFree( GetProcessHeap(), 0, szTemp );
+
+ return ret;
+}
+
+INT WINAPI Shell_GetCachedImageIndexW(LPCWSTR szPath, INT nIndex, BOOL bSimulateDoc)
+{
+ WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath), nIndex, bSimulateDoc);
+
+ return SIC_GetIconIndex(szPath, nIndex, 0);
+}
+
+INT WINAPI Shell_GetCachedImageIndexAW(LPCVOID szPath, INT nIndex, BOOL bSimulateDoc)
+{ if( SHELL_OsIsUnicode())
+ return Shell_GetCachedImageIndexW(szPath, nIndex, bSimulateDoc);
+ return Shell_GetCachedImageIndexA(szPath, nIndex, bSimulateDoc);
+}
+
+/*************************************************************************
+ * ExtractIconExW [SHELL32.@]
+ * RETURNS
+ * 0 no icon found
+ * -1 file is not valid
+ * or number of icons extracted
+ */
+UINT WINAPI ExtractIconExW(LPCWSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons)
+{
+ /* get entry point of undocumented function PrivateExtractIconExW() in user32 */
+#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER)
+ static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL;
+
+ if (!PrivateExtractIconExW) {
+ HMODULE hUser32 = GetModuleHandleA("user32");
+ PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW");
+
+ if (!PrivateExtractIconExW)
+ return 0;
+ }
+#endif
+
+ TRACE("%s %i %p %p %i\n", debugstr_w(lpszFile), nIconIndex, phiconLarge, phiconSmall, nIcons);
+
+ return PrivateExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
+}
+
+/*************************************************************************
+ * ExtractIconExA [SHELL32.@]
+ */
+UINT WINAPI ExtractIconExA(LPCSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons)
+{
+ UINT ret = 0;
+ INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0);
+ LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+
+ TRACE("%s %i %p %p %i\n", lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
+
+ if (lpwstrFile)
+ {
+ MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len);
+ ret = ExtractIconExW(lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
+ HeapFree(GetProcessHeap(), 0, lpwstrFile);
+ }
+ return ret;
+}
+
+/*************************************************************************
+ * ExtractAssociatedIconA (SHELL32.@)
+ *
+ * Return icon for given file (either from file itself or from associated
+ * executable) and patch parameters if needed.
+ */
+HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon)
+{
+ HICON hIcon = NULL;
+ INT len = MultiByteToWideChar(CP_ACP, 0, lpIconPath, -1, NULL, 0);
+ /* Note that we need to allocate MAX_PATH, since we are supposed to fill
+ * the correct executable if there is no icon in lpIconPath directly.
+ * lpIconPath itself is supposed to be large enough, so make sure lpIconPathW
+ * is large enough too. Yes, I am puking too.
+ */
+ LPWSTR lpIconPathW = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
+
+ TRACE("%p %s %p\n", hInst, debugstr_a(lpIconPath), lpiIcon);
+
+ if (lpIconPathW)
+ {
+ MultiByteToWideChar(CP_ACP, 0, lpIconPath, -1, lpIconPathW, len);
+ hIcon = ExtractAssociatedIconW(hInst, lpIconPathW, lpiIcon);
+ WideCharToMultiByte(CP_ACP, 0, lpIconPathW, -1, lpIconPath, MAX_PATH , NULL, NULL);
+ HeapFree(GetProcessHeap(), 0, lpIconPathW);
+ }
+ return hIcon;
+}
+
+/*************************************************************************
+ * ExtractAssociatedIconW (SHELL32.@)
+ *
+ * Return icon for given file (either from file itself or from associated
+ * executable) and patch parameters if needed.
+ */
+HICON WINAPI ExtractAssociatedIconW(HINSTANCE hInst, LPWSTR lpIconPath, LPWORD lpiIcon)
+{
+ HICON hIcon = NULL;
+ WORD wDummyIcon = 0;
+
+ TRACE("%p %s %p\n", hInst, debugstr_w(lpIconPath), lpiIcon);
+
+ if(lpiIcon == NULL)
+ lpiIcon = &wDummyIcon;
+
+ hIcon = ExtractIconW(hInst, lpIconPath, *lpiIcon);
+
+ if( hIcon < (HICON)2 )
+ { if( hIcon == (HICON)1 ) /* no icons found in given file */
+ { WCHAR tempPath[MAX_PATH];
+ HINSTANCE uRet = FindExecutableW(lpIconPath,NULL,tempPath);
+
+ if( uRet > (HINSTANCE)32 && tempPath[0] )
+ { lstrcpyW(lpIconPath,tempPath);
+ hIcon = ExtractIconW(hInst, lpIconPath, *lpiIcon);
+ if( hIcon > (HICON)2 )
+ return hIcon;
+ }
+ }
+
+ if( hIcon == (HICON)1 )
+ *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
+ else
+ *lpiIcon = 6; /* generic icon - found nothing */
+
+ if (GetModuleFileNameW(hInst, lpIconPath, MAX_PATH))
+ hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(*lpiIcon));
+ }
+ return hIcon;
+}
+
+/*************************************************************************
+ * ExtractAssociatedIconExW (SHELL32.@)
+ *
+ * Return icon for given file (either from file itself or from associated
+ * executable) and patch parameters if needed.
+ */
+HICON WINAPI ExtractAssociatedIconExW(HINSTANCE hInst, LPWSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId)
+{
+ FIXME("%p %s %p %p): stub\n", hInst, debugstr_w(lpIconPath), lpiIconIdx, lpiIconId);
+ return 0;
+}
+
+/*************************************************************************
+ * ExtractAssociatedIconExA (SHELL32.@)
+ *
+ * Return icon for given file (either from file itself or from associated
+ * executable) and patch parameters if needed.
+ */
+HICON WINAPI ExtractAssociatedIconExA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId)
+{
+ HICON ret;
+ INT len = MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, NULL, 0 );
+ LPWSTR lpwstrFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+
+ TRACE("%p %s %p %p)\n", hInst, lpIconPath, lpiIconIdx, lpiIconId);
+
+ MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, lpwstrFile, len );
+ ret = ExtractAssociatedIconExW(hInst, lpwstrFile, lpiIconIdx, lpiIconId);
+ HeapFree(GetProcessHeap(), 0, lpwstrFile);
+ return ret;
+}
+
+
+/****************************************************************************
+ * SHDefExtractIconW [SHELL32.@]
+ */
+HRESULT WINAPI SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags,
+ HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize)
+{
+ UINT ret;
+ HICON hIcons[2];
+ WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile), iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
+
+ ret = PrivateExtractIconsW(pszIconFile, iIndex, nIconSize, nIconSize, hIcons, NULL, 2, LR_DEFAULTCOLOR);
+ /* FIXME: deal with uFlags parameter which contains GIL_ flags */
+ if (ret == 0xFFFFFFFF)
+ return E_FAIL;
+ if (ret > 0) {
+ *phiconLarge = hIcons[0];
+ *phiconSmall = hIcons[1];
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+/****************************************************************************
+ * SHDefExtractIconA [SHELL32.@]
+ */
+HRESULT WINAPI SHDefExtractIconA(LPCSTR pszIconFile, int iIndex, UINT uFlags,
+ HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize)
+{
+ HRESULT ret;
+ INT len = MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, NULL, 0);
+ LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+
+ TRACE("%s %d 0x%08x %p %p %d\n", pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
+
+ MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, lpwstrFile, len);
+ ret = SHDefExtractIconW(lpwstrFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
+ HeapFree(GetProcessHeap(), 0, lpwstrFile);
+ return ret;
+}