xulrunner/tools/redit/redit.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:f52f21f625cb
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 // System headers (alphabetical)
8 #include <fcntl.h>
9 #include <io.h>
10 #include <share.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/stat.h>
14 #include <windows.h>
15
16 // Mozilla headers (alphabetical)
17 #include "mozilla/FileUtils.h" // ScopedClose
18 #include "nsAutoPtr.h" // nsAutoArrayPtr
19
20 /*
21 Icon files are made up of:
22
23 IconHeader
24 IconDirEntry1
25 IconDirEntry2
26 ...
27 IconDirEntryN
28 IconData1
29 IconData2
30 ...
31 IconDataN
32
33 Each IconData must be added as a new RT_ICON resource to the exe. Then
34 an RT_GROUP_ICON resource must be added that contains an equivalent
35 header:
36
37 IconHeader
38 IconResEntry1
39 IconResEntry2
40 ...
41 IconResEntryN
42 */
43
44 #pragma pack(push, 2)
45 typedef struct
46 {
47 WORD Reserved;
48 WORD ResourceType;
49 WORD ImageCount;
50 } IconHeader;
51
52 typedef struct
53 {
54 BYTE Width;
55 BYTE Height;
56 BYTE Colors;
57 BYTE Reserved;
58 WORD Planes;
59 WORD BitsPerPixel;
60 DWORD ImageSize;
61 DWORD ImageOffset;
62 } IconDirEntry;
63
64 typedef struct
65 {
66 BYTE Width;
67 BYTE Height;
68 BYTE Colors;
69 BYTE Reserved;
70 WORD Planes;
71 WORD BitsPerPixel;
72 DWORD ImageSize;
73 WORD ResourceID; // This field is the one difference to above
74 } IconResEntry;
75 #pragma pack(pop)
76
77 namespace {
78 /**
79 * ScopedResourceUpdate is a RAII wrapper for Windows resource updating
80 *
81 * Instances |EndUpdateResourceW()| their handles when they go out of scope.
82 * They pass |TRUE| as the second argument to |EndUpdateResourceW()|, which
83 * causes the resource update to be aborted (changes are discarded).
84 */
85 struct ScopedResourceUpdateTraits
86 {
87 typedef HANDLE type;
88 static type empty() { return nullptr; }
89 static void release(type handle) {
90 if(nullptr != handle) {
91 EndUpdateResourceW(handle, TRUE); // Discard changes
92 }
93 }
94 };
95
96 typedef mozilla::Scoped<ScopedResourceUpdateTraits> ScopedResourceUpdate;
97 };
98
99 #ifdef __MINGW32__
100 extern "C"
101 #endif
102 int
103 wmain(int argc, wchar_t** argv)
104 {
105 if (argc != 3) {
106 printf("Usage: redit <exe file> <icon file>\n");
107 return 1;
108 }
109
110 mozilla::ScopedClose file;
111 if (0 != _wsopen_s(&file.rwget(),
112 argv[2],
113 _O_BINARY | _O_RDONLY,
114 _SH_DENYWR,
115 _S_IREAD)
116 || (-1 == file)) {
117 fprintf(stderr, "Unable to open icon file.\n");
118 return 1;
119 }
120
121 // Load all the data from the icon file
122 long filesize = _filelength(file);
123 nsAutoArrayPtr<BYTE> data(new BYTE[filesize]);
124 if(!data) {
125 fprintf(stderr, "Failed to allocate memory for icon file.\n");
126 return 1;
127 }
128 _read(file, data, filesize);
129
130 IconHeader* header = reinterpret_cast<IconHeader*>(data.get());
131
132 // Open the target library for updating
133 ScopedResourceUpdate updateRes(BeginUpdateResourceW(argv[1], FALSE));
134 if (nullptr == updateRes) {
135 fprintf(stderr, "Unable to open library for modification.\n");
136 return 1;
137 }
138
139 // Allocate the group resource entry
140 long groupSize = sizeof(IconHeader)
141 + header->ImageCount * sizeof(IconResEntry);
142 nsAutoArrayPtr<BYTE> group(new BYTE[groupSize]);
143 if(!group) {
144 fprintf(stderr, "Failed to allocate memory for new images.\n");
145 return 1;
146 }
147 memcpy(group, data, sizeof(IconHeader));
148
149 IconDirEntry* sourceIcon =
150 reinterpret_cast<IconDirEntry*>(data
151 + sizeof(IconHeader));
152 IconResEntry* targetIcon =
153 reinterpret_cast<IconResEntry*>(group
154 + sizeof(IconHeader));
155
156 for (int id = 1; id <= header->ImageCount; id++) {
157 // Add the individual icon
158 if (!UpdateResourceW(updateRes, RT_ICON, MAKEINTRESOURCE(id),
159 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
160 data + sourceIcon->ImageOffset,
161 sourceIcon->ImageSize)) {
162 fprintf(stderr, "Unable to update resource (RT_ICON).\n");
163 return 1;
164 }
165 // Copy the data for this icon
166 // (note that the structs have different sizes)
167 memcpy(targetIcon, sourceIcon, sizeof(IconResEntry));
168 targetIcon->ResourceID = id;
169 sourceIcon++;
170 targetIcon++;
171 }
172
173 if (!UpdateResourceW(updateRes, RT_GROUP_ICON, L"MAINICON",
174 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
175 group, groupSize)) {
176 fprintf(stderr, "Unable to update resource (RT_GROUP_ICON).\n");
177 return 1;
178 }
179
180 // Save the modifications
181 if(!EndUpdateResourceW(updateRes.forget(), FALSE)) {
182 fprintf(stderr, "Unable to write changes to library.\n");
183 return 1;
184 }
185
186 return 0;
187 }

mercurial