Icon now supports the res:// protocol

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7328 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2021-09-18 20:24:41 +00:00
parent cc431158fd
commit 167e53df8a
6 changed files with 266 additions and 127 deletions

View file

@ -43,13 +43,9 @@ static bool is_valid_header(const void*headerdata)
return FIX_ENDIAN_INT16(pGH->wCount) != 0;
}
static FILE * open_icon(const TCHAR* filename, IconGroupHeader& igh)
template<class S> static WORD read_icon_header(S*f, IconGroupHeader& igh)
{
FILE* f = FOPEN(filename, ("rb"));
if (!f)
throw runtime_error("can't open file");
if (!fread(&igh, sizeof(IconGroupHeader), 1, f))
if (!freadall(&igh, sizeof(IconGroupHeader), f))
{
fclose(f);
throw runtime_error("unable to read header from file");
@ -57,6 +53,7 @@ static FILE * open_icon(const TCHAR* filename, IconGroupHeader& igh)
if (!is_valid_header(&igh))
{
igh.wType = igh.wCount = 0;
fclose(f);
throw runtime_error("invalid icon file");
}
@ -64,30 +61,31 @@ static FILE * open_icon(const TCHAR* filename, IconGroupHeader& igh)
FIX_ENDIAN_INT16_INPLACE(igh.wReserved);
FIX_ENDIAN_INT16_INPLACE(igh.wType);
FIX_ENDIAN_INT16_INPLACE(igh.wCount);
return f;
return igh.wCount;
}
void free_loaded_icon(IconGroup icon)
void free_loaded_icon(IconGroup&icon)
{
for (IconGroup::size_type i = 0; i < icon.size(); i++)
{
delete [] icon[i].data;
}
icon.clear();
}
IconGroup load_icon_res(CResourceEditor* re, WORD id)
IconGroup load_icon_res(CResourceEditor* re, const TCHAR*RT, WORD RN, LANGID RL)
{
IconGroupHeader* header;
IconGroup result;
LPBYTE group = re->GetResource(
RT_GROUP_ICON, id, NSIS_DEFAULT_LANG);
LPBYTE group = re->GetResource(RT, RN, RL);
if (!group)
throw runtime_error("can't find icon group");
header = (IconGroupHeader*) group;
// Note: To handle cursors, use CResourceEditor::ExtractIcoCur
if (MAKEINTRESOURCE((size_t) RT) != RT_GROUP_ICON)
throw runtime_error("unsupported type");
for (WORD i = 0; i < FIX_ENDIAN_INT16(header->wCount); i++)
{
Icon icon;
@ -99,9 +97,7 @@ IconGroup load_icon_res(CResourceEditor* re, WORD id)
memcpy(&icon.meta, &entry->header, sizeof(IconGroupEntry));
WORD rsrc_id = FIX_ENDIAN_INT16(entry->wRsrcId);
icon.data = re->GetResource(RT_ICON, rsrc_id, NSIS_DEFAULT_LANG);
icon.data = re->GetResource(RT_ICON, rsrc_id, RL);
if (!icon.data)
{
free_loaded_icon(result);
@ -115,13 +111,14 @@ IconGroup load_icon_res(CResourceEditor* re, WORD id)
return result;
}
IconGroup load_icon_file(const TCHAR* filename)
IconGroup load_icon_res(CResourceEditor* re, WORD id)
{
IconGroupHeader iconHeader;
IconGroup result;
return load_icon_res(re, RT_GROUP_ICON, id, NSIS_DEFAULT_LANG);
}
FILE *file = open_icon(filename, iconHeader);
MANAGE_WITH(file, fclose);
template<class S> static IconGroup load_iconimages_from_stream(const IconGroupHeader&iconHeader, S&file)
{
IconGroup result;
for (WORD i = 0; i < iconHeader.wCount; i++)
{
@ -129,7 +126,7 @@ IconGroup load_icon_file(const TCHAR* filename)
icon.index = i;
icon.data = NULL;
if (!fread(&icon.meta, sizeof(IconGroupEntry), 1, file))
if (!freadall(&icon.meta, sizeof(IconGroupEntry), file))
{
free_loaded_icon(result);
throw runtime_error("unable to read entry from file");
@ -143,8 +140,7 @@ IconGroup load_icon_file(const TCHAR* filename)
}
DWORD iconOffset;
if (!fread(&iconOffset, sizeof(DWORD), 1, file))
if (!freadall(&iconOffset, sizeof(DWORD), file))
{
free_loaded_icon(result);
throw runtime_error("unable to read offset from file");
@ -154,7 +150,6 @@ IconGroup load_icon_file(const TCHAR* filename)
fpos_t pos;
fgetpos(file, &pos);
if (fseek(file, iconOffset, SEEK_SET))
{
free_loaded_icon(result);
@ -162,14 +157,14 @@ IconGroup load_icon_file(const TCHAR* filename)
}
icon.data = new BYTE[size];
if (!fread(icon.data, size, 1, file))
if (!freadall(icon.data, size, file)) die:
{
free_loaded_icon(result);
throw runtime_error("unable to read icon from file");
}
fsetpos(file, &pos);
if (fsetpos(file, &pos))
goto die;
result.push_back(icon);
}
@ -177,6 +172,39 @@ IconGroup load_icon_file(const TCHAR* filename)
return result;
}
template<class S> static IconGroup load_icon_from_stream(S*file)
{
IconGroupHeader iconHeader;
read_icon_header(file, iconHeader);
return load_iconimages_from_stream(iconHeader, file);
}
IconGroup load_icon_file(const TCHAR* filename)
{
FILE* f = FOPEN(filename, ("rb"));
if (!f)
throw runtime_error("can't open file");
MANAGE_WITH(f, fclose);
return load_icon_from_stream(f);
}
IconGroup load_icon(const TCHAR* filename)
{
if (CResourceEditor::IsResProtocol(filename)) // Try opening embedded resource
{
CResourceEditor::EXTERNAL x;
if (CResourceEditor::MapExternal(filename, CResourceEditor::TM_ICON, x))
{
CStdFileStreamOnMemory stream(x.Data, x.cbData);
IconGroup icon = load_icon_from_stream(&stream);
CResourceEditor::FreeExternal(x);
return icon;
}
}
return load_icon_file(filename);
}
typedef struct
{
unsigned index1;