From 2dcb751aa7242d03218e1824f528a0f73d52870b Mon Sep 17 00:00:00 2001 From: Rolf Kalbermatter Date: Tue, 10 Dec 2002 19:09:45 +0000 Subject: [PATCH] - Modify ICO_ExtractIconExW to: return more compliant values for usage in PrivateExtractIcons and PrivateExtractIconEx accept and fill in the icon identifier array correctly if provided allow to retrieve both small and large icons together. - Simplify PrivateExtraxtIcons - Modify PrivateExtractIconExW to: use compatible signature to ExtractIconEx in shell32 which it really is directly as tested on W2K by calling both functions with the same parameters directly call internal extraction function fix error when requesting 1 icon for both sizes --- dlls/user/exticon.c | 190 +++++++++++++++++++++--------------------- dlls/user/user32.spec | 4 +- include/winuser.h | 2 + 3 files changed, 98 insertions(+), 98 deletions(-) diff --git a/dlls/user/exticon.c b/dlls/user/exticon.c index 256cfe23489..7e884d0b60d 100644 --- a/dlls/user/exticon.c +++ b/dlls/user/exticon.c @@ -240,7 +240,9 @@ static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG * nIcons = 0: returns number of Icons in file * * returns - * failure:0; success: number of icons in file (nIcons = 0) or nr of icons retrieved + * invalid file: -1 + * failure:0; + * success: number of icons in file (nIcons = 0) or nr of icons retrieved */ static UINT ICO_ExtractIconExW( LPCWSTR lpszExeFileName, @@ -252,7 +254,8 @@ static UINT ICO_ExtractIconExW( UINT *pIconId, UINT flags) { - UINT ret = 0; + UINT ret = 0xFFFFFFFF; + UINT cx1, cx2, cy1, cy2; LPBYTE pData; DWORD sig; HANDLE hFile; @@ -280,11 +283,25 @@ static UINT ICO_ExtractIconExW( if ( !(peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0))) { WARN("MapViewOfFile error %ld\n", GetLastError() ); - CloseHandle( fmapping ); + CloseHandle( fmapping ); return ret; } CloseHandle( fmapping ); + /* Initialize return value to 0 to indicate extraction error */ + ret = 0; + + cx1 = LOWORD(cxDesired); + cx2 = HIWORD(cxDesired) ? HIWORD(cxDesired) : cx1; + cy1 = LOWORD(cyDesired); + cy2 = HIWORD(cyDesired) ? HIWORD(cyDesired) : cy1; + + if (pIconId) /* Invalidate first icon identifier */ + *pIconId = 0xFFFFFFFF; + + if (!pIconId) /* if no icon identifier array present use the icon handle array as intermediate storage */ + pIconId = (UINT*)RetPtr; + sig = USER32_GetResourceTable(peimage,fsizel,&pData); /* ico file */ @@ -337,30 +354,31 @@ static UINT ICO_ExtractIconExW( if( nIcons > iconDirCount - nIconIndex ) nIcons = iconDirCount - nIconIndex; - for( i = nIconIndex; i < nIconIndex + nIcons; i++ ) + for (i = 0; i < nIcons; i++) { /* .ICO files have only one icon directory */ if( lpiID == NULL ) /* *.ico */ - pCIDir = USER32_LoadResource( peimage, pIconDir + i, *(WORD*)pData, &uSize ); - RetPtr[i-nIconIndex] = (HICON)LookupIconIdFromDirectoryEx( pCIDir, TRUE, cxDesired, cyDesired, flags ); + pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex , *(WORD*)pData, &uSize); + pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags); } - for( icon = nIconIndex; icon < nIconIndex + nIcons; icon++ ) + for (icon = 0; icon < nIcons; icon++) { pCIDir = NULL; if( lpiID ) - pCIDir = ICO_LoadIcon( peimage, lpiID->idEntries + (int)RetPtr[icon-nIconIndex], &uSize); + pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize); else - for ( i = 0; i < iconCount; i++ ) - if ( pIconStorage[i].id == ((int)RetPtr[icon-nIconIndex] | 0x8000) ) - pCIDir = USER32_LoadResource( peimage, pIconStorage + i,*(WORD*)pData, &uSize ); + for (i = 0; i < iconCount; i++) + if (pIconStorage[i].id == ((int)pIconId[icon] | 0x8000) ) + pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize); if( pCIDir ) - RetPtr[icon - nIconIndex] = (HICON)CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000, cxDesired, cyDesired, flags); + RetPtr[icon] = (HICON)CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000, + (icon & 1) ? cx2 : cx1, (icon & 1) ? cy2 : cy1, flags); else - RetPtr[icon - nIconIndex] = 0; + RetPtr[icon] = 0; } - ret = icon - nIconIndex; /* return number of retrieved icons */ + ret = icon; /* return number of retrieved icons */ } } } @@ -467,7 +485,7 @@ static UINT ICO_ExtractIconExW( for (i=0; i < nIcons; i++,xresent++) { - const IMAGE_RESOURCE_DIRECTORY *resdir; + const IMAGE_RESOURCE_DIRECTORY *resdir; /* go down this resource entry, name */ resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s3.OffsetToDirectory)); @@ -499,12 +517,9 @@ static UINT ICO_ExtractIconExW( FIXME("no matching real address for icongroup!\n"); goto end; /* failure */ } - RetPtr[i] = (HICON)LookupIconIdFromDirectoryEx(igdata, TRUE, cxDesired, cyDesired, flags); + pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags); } - if (pIconId) - *pIconId = LOWORD(*RetPtr); - if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICONW),rootresdir))) { WARN("No Iconresourcedirectory!\n"); @@ -513,9 +528,9 @@ static UINT ICO_ExtractIconExW( for (i=0; iSize,TRUE,0x00030000, cxDesired, cyDesired, flags); + RetPtr[i] = (HICON) CreateIconFromResourceEx(idata,idataent->Size,TRUE,0x00030000, + (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags); } ret = i; /* return number of retrieved icons */ } /* if(sig == IMAGE_NT_SIGNATURE) */ @@ -548,24 +564,16 @@ end: * PrivateExtractIconsW [USER32.@] * * NOTES - * nIndex = 1: a small and a large icon are extracted. - * the higher word of sizeXY contains the size of the small icon, the lower - * word the size of the big icon. phicon points to HICON[2]. + * If HIWORD(sizeX) && HIWORD(sizeY) 2 * ((nIcons + 1) MOD 2) icons are + * returned, with the LOWORD size icon first and the HIWORD size icon + * second. + * Also the Windows equivalent does extract icons in a strange way if + * nIndex is negative. Our implementation treats a negative nIndex as + * looking for that resource identifier for the first icon to retrieve. * * FIXME: - * 1) should also support 16 bit EXE + DLLs, cursor and animated cursor as well - * as bitmap files. - * 2) should return according to MSDN - * phicons == NULL : the number of icons in file or 0 on error - * phicons != NULL : the number of icons extracted or 0xFFFFFFFF on error - * does return in Win2000 - * when file valid the number of icons or 0 on any error - * when file invalid and phicon == NULL returns 0 - * when file invalid and phicon != NULL returns 0xFFFFFFFF - * - * *pIconID is always set to 0 when file invalid - * *pIconID is always set to 0xFFFFFFFF for valid icon and cursor files - * *pIconID is set to actual identifier for valid dll/exes or -1 on error + * should also support 16 bit EXE + DLLs, cursor and animated cursor as + * well as bitmap files. */ UINT WINAPI PrivateExtractIconsW ( @@ -573,29 +581,19 @@ UINT WINAPI PrivateExtractIconsW ( int nIndex, int sizeX, int sizeY, - HICON * phicon, /* [out] pointer to array of HICON handles */ - UINT* pIconId, /* [out] pointer to returned icon identifier which fits best */ + HICON * phicon, /* [out] pointer to array of nIcons HICON handles */ + UINT* pIconId, /* [out] pointer to array of nIcons icon identifiers or NULL */ UINT nIcons, /* [in] number of icons to retrieve */ - UINT flags ) /* [in] LR_* flags used by LoadImage */ + UINT flags ) /* [in] LR_* flags used by LoadImage */ { - UINT ret; - TRACE("%s %d %dx%d %p %p %d 0x%08x\n", - debugstr_w(lpwstrFile), nIndex, sizeX, sizeY, phicon, pIconId, nIcons, flags); + TRACE("%s %d %dx%d %p %p %d 0x%08x\n", + debugstr_w(lpwstrFile), nIndex, sizeX, sizeY, phicon, pIconId, nIcons, flags); - if (pIconId) /* Invalidate icon identifier on entry */ - *pIconId = 0xFFFFFFFF; - - if (!phicon) - return ICO_ExtractIconExW(lpwstrFile, NULL, nIndex, 0, sizeX & 0xffff, sizeY & 0xffff, pIconId, flags); - - if ((nIcons == 2) && HIWORD(sizeX) && HIWORD(sizeY)) - { - ret = ICO_ExtractIconExW(lpwstrFile, phicon, nIndex, 1, sizeX & 0xffff, sizeY & 0xffff, pIconId, flags); - if (!SUCCEEDED(ret)) return ret; - ret = ICO_ExtractIconExW(lpwstrFile, phicon+1, nIndex, 1, (sizeX>>16) & 0xffff, (sizeY>>16) & 0xffff, pIconId, flags); - } else - ret = ICO_ExtractIconExW(lpwstrFile, phicon, nIndex, nIcons, sizeX & 0xffff, sizeY & 0xffff, pIconId, flags); - return ret; + if ((nIcons & 1) && HIWORD(sizeX) && HIWORD(sizeY)) + { + WARN("Uneven number %d of icons requested for small and large icons!", nIcons); + } + return ICO_ExtractIconExW(lpwstrFile, phicon, nIndex, nIcons, sizeX, sizeY, pIconId, flags); } /*********************************************************************** @@ -607,8 +605,8 @@ UINT WINAPI PrivateExtractIconsA ( int nIndex, int sizeX, int sizeY, - HICON * phicon, - UINT* piconid, /* [out] pointer to returned icon identifier which fits best */ + HICON * phicon, /* [out] pointer to array of nIcons HICON handles */ + UINT* piconid, /* [out] pointer to array of nIcons icon identifiers or NULL */ UINT nIcons, /* [in] number of icons to retrieve */ UINT flags ) /* [in] LR_* flags used by LoadImage */ { @@ -626,22 +624,26 @@ UINT WINAPI PrivateExtractIconsA ( /*********************************************************************** * PrivateExtractIconExW [USER32.@] * NOTES - * if nIcons = -1 it returns the number of icons in any case !!! + * if nIndex == -1 it returns the number of icons in any case !!! */ -HRESULT WINAPI PrivateExtractIconExW ( +UINT WINAPI PrivateExtractIconExW ( LPCWSTR lpwstrFile, - DWORD nIndex, + int nIndex, HICON * phIconLarge, HICON * phIconSmall, UINT nIcons ) { DWORD cyicon, cysmicon, cxicon, cxsmicon; - HRESULT ret = 0; + UINT ret = 0; - TRACE("%s 0x%08lx %p %p 0x%08x\n", + TRACE("%s %d %p %p %d\n", debugstr_w(lpwstrFile),nIndex,phIconLarge, phIconSmall, nIcons); - if (nIndex == 1 && phIconSmall && phIconLarge) + if (nIndex == -1) + /* get the number of icons */ + return ICO_ExtractIconExW(lpwstrFile, NULL, 0, 0, 0, 0, NULL, LR_DEFAULTCOLOR); + + if (nIcons == 1 && phIconSmall && phIconLarge) { HICON hIcon[2]; cxicon = GetSystemMetrics(SM_CXICON); @@ -649,54 +651,50 @@ HRESULT WINAPI PrivateExtractIconExW ( cxsmicon = GetSystemMetrics(SM_CXSMICON); cysmicon = GetSystemMetrics(SM_CYSMICON); - ret = PrivateExtractIconsW ( lpwstrFile, nIndex, cxicon | (cxsmicon<<16), cyicon | (cysmicon<<16), - (HICON*) &hIcon, 0, 2, 0 ); + ret = ICO_ExtractIconExW(lpwstrFile, (HICON*) &hIcon, nIndex, 2, cxicon | (cxsmicon<<16), + cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR); *phIconLarge = hIcon[0]; *phIconSmall = hIcon[1]; return ret; } - if (nIndex != -1) + if (phIconSmall) { - if (phIconSmall) - { - /* extract n small icons */ - cxsmicon = GetSystemMetrics(SM_CXSMICON); - cysmicon = GetSystemMetrics(SM_CYSMICON); - ret = PrivateExtractIconsW ( lpwstrFile, nIndex, cxsmicon, cysmicon, phIconSmall, 0, nIcons, 0 ); - } - if (phIconLarge ) - { - /* extract n large icons */ - cxicon = GetSystemMetrics(SM_CXICON); - cyicon = GetSystemMetrics(SM_CYICON); - ret = PrivateExtractIconsW ( lpwstrFile, nIndex, cxicon, cyicon, phIconLarge, 0, nIcons, 0 ); - } - return ret; + /* extract n small icons */ + cxsmicon = GetSystemMetrics(SM_CXSMICON); + cysmicon = GetSystemMetrics(SM_CYSMICON); + ret = ICO_ExtractIconExW(lpwstrFile, phIconSmall, nIndex, nIcons, cxsmicon, + cysmicon, NULL, LR_DEFAULTCOLOR); } - - /* get the number of icons */ - return PrivateExtractIconsW ( lpwstrFile, 0, 0, 0, 0, 0, 0, 0 ); + if (phIconLarge ) + { + /* extract n large icons */ + cxicon = GetSystemMetrics(SM_CXICON); + cyicon = GetSystemMetrics(SM_CYICON); + ret = ICO_ExtractIconExW(lpwstrFile, phIconSmall, nIndex, nIcons, cxicon, + cyicon, NULL, LR_DEFAULTCOLOR); + } + return ret; } /*********************************************************************** * PrivateExtractIconExA [USER32.@] */ -HRESULT WINAPI PrivateExtractIconExA ( +UINT WINAPI PrivateExtractIconExA ( LPCSTR lpstrFile, - DWORD nIndex, + int nIndex, HICON * phIconLarge, HICON * phIconSmall, UINT nIcons ) { - DWORD ret; - INT len = MultiByteToWideChar( CP_ACP, 0, lpstrFile, -1, NULL, 0 ); - LPWSTR lpwstrFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + UINT ret; + INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0); + LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - TRACE("%s 0x%08lx %p %p 0x%08x\n", lpstrFile, nIndex, phIconLarge, phIconSmall, nIcons); + TRACE("%s %d %p %p %d\n", lpstrFile, nIndex, phIconLarge, phIconSmall, nIcons); - MultiByteToWideChar( CP_ACP, 0, lpstrFile, -1, lpwstrFile, len ); - ret = PrivateExtractIconExW(lpwstrFile,nIndex,phIconLarge, phIconSmall, nIcons); + MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len); + ret = PrivateExtractIconExW(lpwstrFile, nIndex, phIconLarge, phIconSmall, nIcons); HeapFree(GetProcessHeap(), 0, lpwstrFile); return ret; } diff --git a/dlls/user/user32.spec b/dlls/user/user32.spec index fe437b38589..fb560c73601 100644 --- a/dlls/user/user32.spec +++ b/dlls/user/user32.spec @@ -619,8 +619,8 @@ @ stdcall MonitorFromRect(ptr long) MonitorFromRect @ stdcall MonitorFromPoint(long long long) MonitorFromPoint @ stdcall EnumDisplayMonitors(long ptr ptr long) EnumDisplayMonitors -@ stdcall PrivateExtractIconExA (long long long long long) PrivateExtractIconExA -@ stdcall PrivateExtractIconExW (long long long long long) PrivateExtractIconExW +@ stdcall PrivateExtractIconExA(str long ptr ptr long) PrivateExtractIconExA +@ stdcall PrivateExtractIconExW(wstr long ptr ptr long) PrivateExtractIconExW @ stdcall PrivateExtractIconsA (str long long long ptr ptr long long) PrivateExtractIconsA @ stdcall PrivateExtractIconsW (wstr long long long ptr ptr long long) PrivateExtractIconsW @ stdcall RegisterShellHookWindow (long) RegisterShellHookWindow diff --git a/include/winuser.h b/include/winuser.h index 1d8698aa614..a46355b6922 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -4314,6 +4314,8 @@ BOOL WINAPI PostMessageA(HWND,UINT,WPARAM,LPARAM); BOOL WINAPI PostMessageW(HWND,UINT,WPARAM,LPARAM); #define PostMessage WINELIB_NAME_AW(PostMessage) void WINAPI PostQuitMessage(INT); +UINT WINAPI PrivateExtractIconExA(LPCSTR,int,HICON*,HICON*,UINT); +UINT WINAPI PrivateExtractIconExW(LPCWSTR,int,HICON*,HICON*,UINT); UINT WINAPI PrivateExtractIconsA(LPCSTR,int,int,int,HICON*,UINT*,UINT,UINT); UINT WINAPI PrivateExtractIconsW(LPCWSTR,int,int,int,HICON*,UINT*,UINT,UINT); BOOL WINAPI PtInRect(const RECT*,POINT);