xulrunner/tools/redit/redit.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial