📄 exticon.c
字号:
{
/* .ICO files have only one icon directory */
if (lpiID == NULL) /* not *.ico */
pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize);
pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags);
}
if (lpiID && pCIDir) /* *.ico file, deallocate heap pointer*/
HeapFree(GetProcessHeap(), 0, pCIDir);
for (icon = 0; icon < nIcons; icon++)
{
pCIDir = NULL;
if (lpiID)
pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize);
else
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] = (HICON)CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
(icon & 1) ? cx2 : cx1, (icon & 1) ? cy2 : cy1, flags);
else
RetPtr[icon] = 0;
}
ret = icon; /* return number of retrieved icons */
}
}
}
/* end ico file */
/* exe/dll */
else if( sig == IMAGE_NT_SIGNATURE )
#endif
if( sig == IMAGE_NT_SIGNATURE )
{
LPBYTE idata,igdata;
PIMAGE_DOS_HEADER dheader;
PIMAGE_NT_HEADERS pe_header;
PIMAGE_SECTION_HEADER pe_sections;
const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir;
const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent;
const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
UINT i, j;
dheader = (PIMAGE_DOS_HEADER)peimage;
pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew); /* it is a pe header, USER32_GetResourceTable checked that */
pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER)
+ pe_header->FileHeader.SizeOfOptionalHeader);
rootresdir = NULL;
/* search for the root resource directory */
for (i=0;i<pe_header->FileHeader.NumberOfSections;i++)
{
if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
continue;
if (fsizel < pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData) {
FIXME("File %s too short (section is at %ld bytes, real size is %ld)\n",
debugstr_w(lpszExeFileName),
pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData,
fsizel
);
goto end;
}
/* FIXME: doesn't work when the resources are not in a separate section */
if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)
{
rootresdir = (PIMAGE_RESOURCE_DIRECTORY)(peimage+pe_sections[i].PointerToRawData);
break;
}
}
if (!rootresdir)
{
WARN("haven't found section for resource directory.\n");
goto end; /* failure */
}
/* search for the group icon directory */
if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir)))
{
WARN("No Icongroupresourcedirectory!\n");
goto end; /* failure */
}
iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries;
/* only number of icons requested */
if( nIcons == 0 )
{
ret = iconDirCount;
goto end; /* success */
}
if( nIconIndex < 0 )
{
/* search resource id */
int n = 0;
int iId = abs(nIconIndex);
PIMAGE_RESOURCE_DIRECTORY_ENTRY xprdeTmp = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
while(n<iconDirCount && xprdeTmp)
{
if(xprdeTmp->Id == iId)
{
nIconIndex = n;
break;
}
n++;
xprdeTmp++;
}
if (nIconIndex < 0)
{
WARN("resource id %d not found\n", iId);
goto end; /* failure */
}
}
else
{
/* check nIconIndex to be in range */
if (nIconIndex >= iconDirCount)
{
WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
goto end; /* failure */
}
}
/* assure we don't get too much */
if( nIcons / 2 > iconDirCount - nIconIndex )
nIcons = 2 * (iconDirCount - nIconIndex);
/* starting from specified index */
xresent = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1) + nIconIndex;
for (i=0; i < nIcons; i++)
{
const IMAGE_RESOURCE_DIRECTORY *resdir;
/* go down this resource entry, name */
resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->OffsetToDirectory));
/* default language (0) */
resdir = find_entry_default(resdir,rootresdir);
igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir;
/* lookup address in mapped image for virtual address */
igdata = NULL;
for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
{
if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
continue;
if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
continue;
if (igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData+igdataent->Size > fsizel) {
FIXME("overflow in PE lookup (%s has len %ld, have offset %ld), short file?\n", debugstr_w(lpszExeFileName), fsizel,
igdataent->OffsetToData - pe_sections[j].VirtualAddress + pe_sections[j].PointerToRawData + igdataent->Size);
goto end; /* failure */
}
igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
}
if (!igdata)
{
FIXME("no matching real address for icongroup!\n");
goto end; /* failure */
}
pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags);
if (i & 1) xresent++;
}
if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir)))
{
WARN("No Iconresourcedirectory!\n");
goto end; /* failure */
}
for (i=0; i<nIcons; i++)
{
const IMAGE_RESOURCE_DIRECTORY *xresdir;
xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
xresdir = find_entry_default(xresdir, rootresdir);
idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir;
idata = NULL;
/* map virtual to address in image */
for (j=0;j<pe_header->FileHeader.NumberOfSections;j++)
{
if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
continue;
if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
continue;
idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
}
if (!idata)
{
WARN("no matching real address found for icondata!\n");
RetPtr[i]=0;
continue;
}
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) */
end:
UnmapViewOfFile(peimage); /* success */
return ret;
}
/***********************************************************************
* PrivateExtractIconsW [USER32.@]
* @implemented
*
* NOTES
* 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:
* should also support 16 bit EXE + DLLs, cursor and animated cursor as
* well as bitmap files.
*/
UINT WINAPI PrivateExtractIconsW (
LPCWSTR lpwstrFile,
int nIndex,
int sizeX,
int sizeY,
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 */
{
TRACE("%s %d %dx%d %p %p %d 0x%08x\n",
debugstr_w(lpwstrFile), nIndex, sizeX, sizeY, phicon, pIconId, nIcons, flags);
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);
}
/***********************************************************************
* PrivateExtractIconsA [USER32.@]
* @implemented
*/
UINT WINAPI PrivateExtractIconsA (
LPCSTR lpstrFile,
int nIndex,
int sizeX,
int sizeY,
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 ret;
INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len);
ret = PrivateExtractIconsW(lpwstrFile, nIndex, sizeX, sizeY, phicon, piconid, nIcons, flags);
HeapFree(GetProcessHeap(), 0, lpwstrFile);
return ret;
}
/***********************************************************************
* PrivateExtractIconExW [USER32.@]
* @implemented
* NOTES
* if nIndex == -1 it returns the number of icons in any case !!!
*/
UINT WINAPI PrivateExtractIconExW (
LPCWSTR lpwstrFile,
int nIndex,
HICON * phIconLarge,
HICON * phIconSmall,
UINT nIcons )
{
DWORD cyicon, cysmicon, cxicon, cxsmicon;
INT ret = 0;
TRACE("%s %d %p %p %d\n",
debugstr_w(lpwstrFile),nIndex,phIconLarge, phIconSmall, nIcons);
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);
cyicon = GetSystemMetrics(SM_CYICON);
cxsmicon = GetSystemMetrics(SM_CXSMICON);
cysmicon = GetSystemMetrics(SM_CYSMICON);
ret = ICO_ExtractIconExW(lpwstrFile, (HICON*) &hIcon, nIndex, 2, cxicon | (cxsmicon<<16),
cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR);
*phIconLarge = (1 <= ret ? hIcon[0] : NULL);
*phIconSmall = (2 <= ret ? hIcon[1] : NULL);
return ret;
}
if (phIconSmall)
{
/* extract n small icons */
cxsmicon = GetSystemMetrics(SM_CXSMICON);
cysmicon = GetSystemMetrics(SM_CYSMICON);
ret = ICO_ExtractIconExW(lpwstrFile, phIconSmall, nIndex, nIcons, cxsmicon,
cysmicon, NULL, LR_DEFAULTCOLOR);
}
if (phIconLarge)
{
/* extract n large icons */
cxicon = GetSystemMetrics(SM_CXICON);
cyicon = GetSystemMetrics(SM_CYICON);
ret = ICO_ExtractIconExW(lpwstrFile, phIconLarge, nIndex, nIcons, cxicon,
cyicon, NULL, LR_DEFAULTCOLOR);
}
return ret;
}
/***********************************************************************
* PrivateExtractIconExA [USER32.@]
* @implemented
*/
UINT WINAPI PrivateExtractIconExA (
LPCSTR lpstrFile,
int nIndex,
HICON * phIconLarge,
HICON * phIconSmall,
UINT nIcons )
{
UINT ret;
INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0);
LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
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);
HeapFree(GetProcessHeap(), 0, lpwstrFile);
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -