exe.go (2279B)
1 // Package exe reads the icons a Windows executable or DLL carries. 2 // 3 // A portable executable keeps its icons in the resource section as two 4 // resource types that refer to each other: RT_GROUP_ICON holds a directory of 5 // the sizes one icon is drawn at, and RT_ICON holds the image for each of 6 // them. A directory and the images it names are an ico file in all but the 7 // offsets, so this package puts them back together and hands out ico files 8 // the ico package reads. 9 // 10 // A binary may carry several groups. Explorer draws the first by ordinal, 11 // which is the one Icons returns first. 12 package exe 13 14 import ( 15 "errors" 16 "fmt" 17 ) 18 19 // Errors returned by the reader. They are wrapped with detail, so compare 20 // with errors.Is. 21 var ( 22 // ErrNoIcons means the binary carries no icon resources. 23 ErrNoIcons = errors.New("no icons found") 24 // ErrMalformed means a resource offset or length disagrees with the 25 // section holding it. 26 ErrMalformed = errors.New("malformed resource section") 27 ) 28 29 // Resource types, as the resource directory numbers them. 30 const ( 31 typeIcon = 3 32 typeIconGroup = 14 33 ) 34 35 const ( 36 // directoryHeaderSize is the fixed part of a resource directory, before 37 // its entries. 38 directoryHeaderSize = 16 39 // directoryEntrySize is one entry in a resource directory. 40 directoryEntrySize = 8 41 // dataEntrySize is the leaf that points at the bytes of a resource. 42 dataEntrySize = 16 43 // groupHeaderSize is the fixed part of a group icon directory. 44 groupHeaderSize = 6 45 // groupEntrySize is one icon's row in a group icon directory. It differs 46 // from the ico row only in naming a resource rather than an offset. 47 groupEntrySize = 14 48 // icoEntrySize is one icon's row in an ico directory. 49 icoEntrySize = 16 50 ) 51 52 // Group is one icon a binary carries, at every size it holds. 53 type Group struct { 54 // ID is the ordinal the resource directory gives the group. Explorer 55 // draws the lowest. 56 ID uint16 57 // Sizes are the dimensions the directory lists, largest first. 58 Sizes []int 59 60 ico []byte 61 } 62 63 func (g Group) String() string { 64 return fmt.Sprintf("icon %d (%d sizes)", g.ID, len(g.Sizes)) 65 } 66 67 // ICO returns the group as an ico file, which ico.Decode reads. 68 // 69 // The bytes are not copied, and must not be modified. 70 func (g Group) ICO() []byte { 71 return g.ico 72 }