-
Notifications
You must be signed in to change notification settings - Fork 122
/
rsrc.go
103 lines (88 loc) · 2.27 KB
/
rsrc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package rsrc
import (
"encoding/binary"
"fmt"
"io"
"os"
"strings"
"github.com/akavel/rsrc/binutil"
"github.com/akavel/rsrc/coff"
"github.com/akavel/rsrc/ico"
"github.com/akavel/rsrc/internal"
)
// on storing icons, see: http://blogs.msdn.com/b/oldnewthing/archive/2012/07/20/10331787.aspx
type _GRPICONDIR struct {
ico.ICONDIR
Entries []_GRPICONDIRENTRY
}
func (group _GRPICONDIR) Size() int64 {
return int64(binary.Size(group.ICONDIR) + len(group.Entries)*binary.Size(group.Entries[0]))
}
type _GRPICONDIRENTRY struct {
ico.IconDirEntryCommon
Id uint16
}
func Embed(fnameout, arch, fnamein, fnameico string) error {
lastid := uint16(0)
newid := func() uint16 {
lastid++
return lastid
}
out := coff.NewRSRC()
err := out.Arch(arch)
if err != nil {
return err
}
if fnamein != "" {
manifest, err := binutil.SizedOpen(fnamein)
if err != nil {
return fmt.Errorf("rsrc: error opening manifest file '%s': %s", fnamein, err)
}
defer manifest.Close()
id := newid()
out.AddResource(coff.RT_MANIFEST, id, manifest)
// TODO(akavel): reintroduce the Printlns in package main after Embed returns
// fmt.Println("Manifest ID: ", id)
}
if fnameico != "" {
for _, fnameicosingle := range strings.Split(fnameico, ",") {
f, err := addIcon(out, fnameicosingle, newid)
if err != nil {
return err
}
defer f.Close()
}
}
out.Freeze()
return internal.Write(out, fnameout)
}
func addIcon(out *coff.Coff, fname string, newid func() uint16) (io.Closer, error) {
f, err := os.Open(fname)
if err != nil {
return nil, err
}
icons, err := ico.DecodeHeaders(f)
if err != nil {
f.Close()
return nil, err
}
if len(icons) > 0 {
// RT_ICONs
group := _GRPICONDIR{ICONDIR: ico.ICONDIR{
Reserved: 0, // magic num.
Type: 1, // magic num.
Count: uint16(len(icons)),
}}
gid := newid()
for _, icon := range icons {
id := newid()
r := io.NewSectionReader(f, int64(icon.ImageOffset), int64(icon.BytesInRes))
out.AddResource(coff.RT_ICON, id, r)
group.Entries = append(group.Entries, _GRPICONDIRENTRY{icon.IconDirEntryCommon, id})
}
out.AddResource(coff.RT_GROUP_ICON, gid, group)
// TODO(akavel): reintroduce the Printlns in package main after Embed returns
// fmt.Println("Icon ", fname, " ID: ", id)
}
return f, nil
}