diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index 2bdbdbf8f61..4a5639b9704 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -103,7 +103,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(menubuilder); (csidl)==CSIDL_COMMON_DESKTOPDIRECTORY) #define in_startmenu(csidl) ((csidl)==CSIDL_STARTMENU || \ (csidl)==CSIDL_COMMON_STARTMENU) - + /* link file formats */ #include "pshpack1.h" @@ -964,20 +964,32 @@ end: return hr; } -static HRESULT write_native_icon(IStream *iconStream, const char *icon_name, LPCWSTR szFileName) +static HRESULT validate_ico(IStream **ppStream, ICONDIRENTRY **ppIconDirEntries, int *numEntries) +{ + HRESULT hr; + + hr = read_ico_direntries(*ppStream, ppIconDirEntries, numEntries); + if (SUCCEEDED(hr)) + { + if (*numEntries) + return hr; + HeapFree(GetProcessHeap(), 0, *ppIconDirEntries); + *ppIconDirEntries = NULL; + } + IStream_Release(*ppStream); + *ppStream = NULL; + return E_FAIL; +} + +static HRESULT write_native_icon(IStream *iconStream, ICONDIRENTRY *pIconDirEntry, + int numEntries, const char *icon_name, LPCWSTR szFileName) { - ICONDIRENTRY *pIconDirEntry = NULL; - int numEntries; int nMax = 0, nMaxBits = 0; int nIndex = 0; int i; LARGE_INTEGER position; HRESULT hr; - hr = read_ico_direntries(iconStream, &pIconDirEntry, &numEntries); - if (FAILED(hr)) - goto end; - for (i = 0; i < numEntries; i++) { WINE_TRACE("[%d]: %d x %d @ %d\n", i, pIconDirEntry[i].bWidth, pIconDirEntry[i].bHeight, pIconDirEntry[i].wBitCount); @@ -1069,7 +1081,7 @@ static HRESULT open_default_icon(IStream **ppStream) return open_module_icon(user32W, -(INT_PTR)IDI_WINLOGO, ppStream); } -static HRESULT open_icon(LPCWSTR filename, int index, BOOL bWait, IStream **ppStream) +static HRESULT open_icon(LPCWSTR filename, int index, BOOL bWait, IStream **ppStream, ICONDIRENTRY **ppIconDirEntries, int *numEntries) { HRESULT hr; @@ -1084,16 +1096,25 @@ static HRESULT open_icon(LPCWSTR filename, int index, BOOL bWait, IStream **ppSt } else { - static const WCHAR dot_icoW[] = {'.','i','c','o',0}; - int len = strlenW(filename); - if (len >= 4 && strcmpiW(&filename[len - 4], dot_icoW) == 0) - hr = SHCreateStreamOnFileW(filename, STGM_READ, ppStream); + /* This might be a raw .ico file */ + hr = SHCreateStreamOnFileW(filename, STGM_READ, ppStream); } } + if (SUCCEEDED(hr)) + hr = validate_ico(ppStream, ppIconDirEntries, numEntries); + if (FAILED(hr)) + { hr = open_file_type_icon(filename, ppStream); + if (SUCCEEDED(hr)) + hr = validate_ico(ppStream, ppIconDirEntries, numEntries); + } if (FAILED(hr) && !bWait) + { hr = open_default_icon(ppStream); + if (SUCCEEDED(hr)) + hr = validate_ico(ppStream, ppIconDirEntries, numEntries); + } return hr; } @@ -1147,11 +1168,10 @@ static inline int size_to_slot(int size) #define CLASSIC_SLOT 3 -static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW, +static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *pIconDirEntry, + int numEntries, int exeIndex, LPCWSTR icoPathW, const char *destFilename, char **nativeIdentifier) { - ICONDIRENTRY *iconDirEntries = NULL; - int numEntries; struct { int index; int maxBits; @@ -1164,9 +1184,6 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR ico LARGE_INTEGER zero; HRESULT hr; - hr = read_ico_direntries(icoStream, &iconDirEntries, &numEntries); - if (FAILED(hr)) - goto end; for (i = 0; i < ICNS_SLOTS; i++) { best[i].index = -1; @@ -1254,7 +1271,6 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR ico } end: - HeapFree(GetProcessHeap(), 0, iconDirEntries); HeapFree(GetProcessHeap(), 0, icnsPath); return hr; } @@ -1279,20 +1295,15 @@ static void refresh_icon_cache(const char *iconsDir) } } -static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW, +static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *iconDirEntries, + int numEntries, int exeIndex, LPCWSTR icoPathW, const char *destFilename, char **nativeIdentifier) { - ICONDIRENTRY *iconDirEntries = NULL; - int numEntries; int i; char *iconsDir = NULL; HRESULT hr = S_OK; LARGE_INTEGER zero; - hr = read_ico_direntries(icoStream, &iconDirEntries, &numEntries); - if (FAILED(hr)) - goto end; - if (destFilename) *nativeIdentifier = heap_printf("%s", destFilename); else @@ -1372,7 +1383,6 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR ico refresh_icon_cache(iconsDir); end: - HeapFree(GetProcessHeap(), 0, iconDirEntries); HeapFree(GetProcessHeap(), 0, iconsDir); return hr; } @@ -1382,24 +1392,27 @@ end: static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename, BOOL bWait) { IStream *stream = NULL; + ICONDIRENTRY *pIconDirEntries = NULL; + int numEntries; HRESULT hr; char *nativeIdentifier = NULL; WINE_TRACE("path=[%s] index=%d destFilename=[%s]\n", wine_dbgstr_w(icoPathW), index, wine_dbgstr_a(destFilename)); - hr = open_icon(icoPathW, index, bWait, &stream); + hr = open_icon(icoPathW, index, bWait, &stream, &pIconDirEntries, &numEntries); if (FAILED(hr)) { WINE_WARN("opening icon %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(icoPathW), index, hr); goto end; } - hr = platform_write_icon(stream, index, icoPathW, destFilename, &nativeIdentifier); + hr = platform_write_icon(stream, pIconDirEntries, numEntries, index, icoPathW, destFilename, &nativeIdentifier); if (FAILED(hr)) WINE_WARN("writing icon failed, error 0x%08X\n", hr); end: if (stream) IStream_Release(stream); + HeapFree(GetProcessHeap(), 0, pIconDirEntries); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, nativeIdentifier); @@ -3472,6 +3485,8 @@ static void thumbnail_lnk(LPCWSTR lnkPath, LPCWSTR outputPath) WCHAR szIconPath[MAX_PATH]; int iconId; IStream *stream = NULL; + ICONDIRENTRY *pIconDirEntries = NULL; + int numEntries; HRESULT hr; utf8lnkPath = wchars_to_utf8_chars(lnkPath); @@ -3533,15 +3548,15 @@ static void thumbnail_lnk(LPCWSTR lnkPath, LPCWSTR outputPath) if (szIconPath[0]) { - hr = open_icon(szIconPath, iconId, FALSE, &stream); + hr = open_icon(szIconPath, iconId, FALSE, &stream, &pIconDirEntries, &numEntries); if (SUCCEEDED(hr)) - hr = write_native_icon(stream, utf8OutputPath, NULL); + hr = write_native_icon(stream, pIconDirEntries, numEntries, utf8OutputPath, NULL); } else { - hr = open_icon(szPath, iconId, FALSE, &stream); + hr = open_icon(szPath, iconId, FALSE, &stream, &pIconDirEntries, &numEntries); if (SUCCEEDED(hr)) - hr = write_native_icon(stream, utf8OutputPath, NULL); + hr = write_native_icon(stream, pIconDirEntries, numEntries, utf8OutputPath, NULL); } end: @@ -3554,6 +3569,7 @@ end: IPersistFile_Release(persistFile); if (stream != NULL) IStream_Release(stream); + HeapFree(GetProcessHeap(), 0, pIconDirEntries); } static WCHAR *next_token( LPWSTR *p )