-
Notifications
You must be signed in to change notification settings - Fork 115
/
IconChanger.ahk
148 lines (110 loc) · 3.4 KB
/
IconChanger.ahk
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
;
; File encoding: UTF-8 with BOM
;
; This code is based on Ahk2Exe's changeicon.cpp
AddOrReplaceIcon(re, IcoFile, ExeFile, iconID := 0)
{
global _CI_HighestIconID, _CIG_HighestIconGroupID
CountIcons(ExeFile)
if !iconID
{
CountIconGroups(ExeFile)
iconID := ++ _CIG_HighestIconGroupID
}
ids := EnumIcons(ExeFile, iconID)
if !IsObject(ids)
return false
f := FileOpen(IcoFile, "r")
if !IsObject(f)
return false
VarSetCapacity(igh, 8), f.RawRead(igh, 6)
if NumGet(igh, 0, "UShort") != 0 || NumGet(igh, 2, "UShort") != 1
return false
wCount := NumGet(igh, 4, "UShort")
VarSetCapacity(rsrcIconGroup, rsrcIconGroupSize := 6 + wCount*14)
NumPut(NumGet(igh, "Int64"), rsrcIconGroup, "Int64") ; fast copy
ige := &rsrcIconGroup + 6
; Delete all the images
Loop, % ids.MaxIndex()
DllCall("UpdateResource", "ptr", re, "ptr", 3, "ptr", ids[A_Index], "ushort", 0x409, "ptr", 0, "uint", 0, "uint")
Loop, %wCount%
{
thisID := ids[A_Index]
if !thisID
thisID := ++ _CI_HighestIconID
f.RawRead(ige+0, 12) ; read all but the offset
NumPut(thisID, ige+12, "UShort")
imgOffset := f.ReadUInt()
oldPos := f.Pos
f.Pos := imgOffset
VarSetCapacity(iconData, iconDataSize := NumGet(ige+8, "UInt"))
f.RawRead(iconData, iconDataSize)
f.Pos := oldPos
if !DllCall("UpdateResource", "ptr", re, "ptr", 3, "ptr", thisID, "ushort", 0x409, "ptr", &iconData, "uint", iconDataSize, "uint")
return false
ige += 14
}
return !!DllCall("UpdateResource", "ptr", re, "ptr", 14, "ptr", iconID, "ushort", 0x409, "ptr", &rsrcIconGroup, "uint", rsrcIconGroupSize, "uint")
}
CountIcons(ExeFile)
{
; RT_ICON = 3
global _CI_HighestIconID
if _CI_HighestIconID
return
static pEnumFunc := RegisterCallback("CountIcons_Enum")
hModule := DllCall("LoadLibraryEx", "str", ExeFile, "ptr", 0, "ptr", 2, "ptr")
if !hModule
return
_CI_HighestIconID := 0
DllCall("EnumResourceNames", "ptr", hModule, "ptr", 3, "ptr", pEnumFunc, "uint", 0)
DllCall("FreeLibrary", "ptr", hModule)
}
CountIconGroups(ExeFile)
{
; RT_GROUP_ICON = 14
global _CIG_HighestIconGroupID
if _CIG_HighestIconGroupID
return
static pEnumFunc := RegisterCallback("CountIconGroups_Enum")
hModule := DllCall("LoadLibraryEx", "str", ExeFile, "ptr", 0, "ptr", 2, "ptr")
if !hModule
return
_CIG_HighestIconGroupID := 0
DllCall("EnumResourceNames", "ptr", hModule, "ptr", 14, "ptr", pEnumFunc, "uint", 0)
DllCall("FreeLibrary", "ptr", hModule)
}
EnumIcons(ExeFile, iconID)
{
; RT_GROUP_ICON = 14
hModule := DllCall("LoadLibraryEx", "str", ExeFile, "ptr", 0, "ptr", 2, "ptr")
if !hModule
return
hRsrc := DllCall("FindResource", "ptr", hModule, "ptr", iconID, "ptr", 14, "ptr")
hMem := DllCall("LoadResource", "ptr", hModule, "ptr", hRsrc, "ptr")
pDirHeader := DllCall("LockResource", "ptr", hMem, "ptr")
pResDir := pDirHeader + 6
wCount := NumGet(pDirHeader+4, "UShort")
iconIDs := []
Loop, %wCount%
{
pResDirEntry := pResDir + (A_Index-1)*14
iconIDs[A_Index] := NumGet(pResDirEntry+12, "UShort")
}
DllCall("FreeLibrary", "ptr", hModule)
return iconIDs
}
CountIcons_Enum(hModule, type, name, lParam)
{
global _CI_HighestIconID
if (name < 0x10000) && name > _CI_HighestIconID
_CI_HighestIconID := name
return 1
}
CountIconGroups_Enum(hModule, type, name, lParam)
{
global _CIG_HighestIconGroupID
if (name < 0x10000) && name > _CIG_HighestIconGroupID
_CIG_HighestIconGroupID := name
return 1
}