00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029
00030 #include "persrc.h"
00031 #include <stdexcept>
00032 #include <list>
00033 #include "utils/f77auto_ptr"
00034
00035 struct iconinfo
00036 {
00037
00038 unsigned id;
00039 long pos;
00040 uint32_t size;
00041 };
00042
00043 typedef std::list<iconinfo> TIconInfos;
00044
00045 static void CollectIconInfos(ICFile& file,const PeResourceDirectoryData* data,const PeResourceDirectoryInfo* info,unsigned level,void* param)
00046 {
00047 _DEBUG_(fprintf(stderr,"data %p level %d name %p id %d\n", data, level, info->name, info->id ));
00048 if (data != NULL && level == 3 && info->name == NULL && info->highLevel->id == 3)
00049 {
00050 _DEBUG_(fprintf(stderr,"---data %p level %d name %p id %d\n", data, level, info->name, info->highLevel->id));
00051 iconinfo iinfo;
00052 iinfo.id = info->id;
00053 iinfo.pos = file.Tell();
00054 iinfo.size = data->data.Size;
00055 _DEBUG_(fprintf(stderr,"---id %d pos %ld size %d\n", iinfo.id, iinfo.pos, iinfo.size));
00056
00057 (*reinterpret_cast<TIconInfos*>(param)).push_back(iinfo);
00058 }
00059 }
00060
00061 struct WriteIconParam
00062 {
00063 TIconInfos iconInfos;
00064 int n;
00065 WriteIconParam():n(1) {};
00066
00067 };
00068
00069 static const iconinfo* findIconInfo(const TIconInfos& infos,unsigned id)
00070 {
00071 TIconInfos::const_iterator end = infos.end();
00072 for(TIconInfos::const_iterator i = infos.begin(); i != end; ++i)
00073 if ( (*i).id == id )
00074 return &(*i);
00075 return NULL;
00076 }
00077
00078 static void CopyFileToFile(const ICFile& from,ICFile& to,size_t bytes)
00079 {
00080 char buffer[128];
00081 while(bytes > 0)
00082 {
00083 size_t len = f77_min(bytes,(size_t)128);
00084 from.RawRead(buffer,len);
00085 to.RawWrite(buffer,len);
00086 bytes -= len;
00087 }
00088 }
00089
00090 static void WriteIcons(ICFile& file,const PeResourceDirectoryData* data,const PeResourceDirectoryInfo* info,unsigned level,void* param)
00091 {
00092 static const char zeroes[2] = { 0, 0 };
00093 if (data != NULL && level == 3 && info->highLevel->id == 14)
00094 {
00095 WriteIconParam *p = reinterpret_cast<WriteIconParam*>(param);
00096
00097
00098 NEWHEADER hdr;
00099 RawRead(file,hdr);
00100
00101 char buffer[128];
00102 sprintf(buffer,"resico%d.ico",p->n);
00103 ++p->n;
00104 CFile ico(buffer,"wb");
00105
00106
00107 RawWrite(ico,hdr);
00108
00109
00110 freddy77::auto_delete_ptr<const iconinfo*> icons(new const iconinfo*[hdr.ResCount]);
00111 int i;
00112 for( i = 0; i < hdr.ResCount; ++i )
00113 {
00114 RESDIR resico;
00115
00116 file.RawRead(&resico,14);
00117
00118
00119
00120 ico.RawWrite(&resico,14);
00121 ico.RawWrite(zeroes,2);
00122
00123
00124 const iconinfo* info = findIconInfo(p->iconInfos,resico.IconCursorId);
00125 *(icons.get()+i) = info;
00126 if (!info)
00127 throw std::runtime_error("icon not found for icon group");
00128 if (resico.BytesInRes != info->size)
00129 throw std::runtime_error("icon with wrong size");
00130
00131 }
00132 for( i = 0; i < hdr.ResCount; ++i )
00133 {
00134 const iconinfo* info = *(icons.get()+i);
00135 file.Seek(info->pos);
00136 CopyFileToFile(file,ico,info->size);
00137 }
00138 }
00139 }
00140
00141 void ResourceExtract::ExtractIcons(PeFile& peFile)
00142 {
00143
00144
00145
00146 WriteIconParam param;
00147 peFile.ParseResource(CollectIconInfos,¶m.iconInfos);
00148
00149
00150 peFile.ParseResource(WriteIcons,¶m);
00151 }