bug 753123. Use wide-string versions of Windows API calls to make redit.exe work with unicode file paths. Also updates redit to scopeguard its resources. r=jimm
authorTim Abraldes <tabraldes@mozilla.com>
Mon, 14 May 2012 16:54:25 -0700
changeset 93929 984d745ceda7146930ff1324a4d5dd012cffbc2e
parent 93928 793a4423093f14d189f4e01dadee698e59b056be
child 93930 ee66329e548a72379e069b28b48603c066449e0c
push id9386
push usertabraldes@mozilla.com
push dateMon, 14 May 2012 23:56:49 +0000
treeherdermozilla-inbound@984d745ceda7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs753123
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 753123. Use wide-string versions of Windows API calls to make redit.exe work with unicode file paths. Also updates redit to scopeguard its resources. r=jimm
xulrunner/tools/redit/Makefile.in
xulrunner/tools/redit/redit.cpp
--- a/xulrunner/tools/redit/Makefile.in
+++ b/xulrunner/tools/redit/Makefile.in
@@ -1,55 +1,33 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Mozilla XULRunner.
-#
-# The Initial Developer of the Original Code is
-# the Mozilla Foundation <http://www.mozilla.org/>.
-# Portions created by the Initial Developer are Copyright (C) 2008
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Mark Finkle <mfinkle@mozilla.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 DEPTH     = ../../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = redit
 
 ifeq ($(OS_ARCH),WINNT)
 CPPSRCS    = redit.cpp
 PROGRAM    = redit$(BIN_SUFFIX)
+
 SDK_BINARY =  \
 	$(PROGRAM) \
 	$(NULL)
+
+DEFINES += -DWIN32_LEAN_AND_MEAN \
+					 -DUNICODE \
+					 -D_UNICODE \
+					 -DXPCOM_GLUE \
+					 $(NULL)
+
+LIBS = \
+  $(XPCOM_STANDALONE_GLUE_LDOPTS) \
+  $(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/xulrunner/tools/redit/redit.cpp
+++ b/xulrunner/tools/redit/redit.cpp
@@ -1,50 +1,26 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is McCoy.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation <http://www.mozilla.org/>.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dave Townsend <dtownsend@oxymoronical.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
-#include <windows.h>
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// System headers (alphabetical)
+#include <fcntl.h>
+#include <io.h>
+#include <share.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <io.h>
-#include <fcntl.h>
+#include <sys/stat.h>
+#include <windows.h>
+
+// Mozilla headers (alphabetical)
+#include "mozilla/FileUtils.h"  // ScopedClose
+#include "nsAutoPtr.h"          // nsAutoArrayPtr
 
 /*
 Icon files are made up of:
 
 IconHeader
 IconDirEntry1
 IconDirEntry2
 ...
@@ -93,88 +69,116 @@ typedef struct
   BYTE Reserved;
   WORD Planes;
   WORD BitsPerPixel;
   DWORD ImageSize;
   WORD ResourceID;    // This field is the one difference to above
 } IconResEntry;
 #pragma pack(pop)
 
+namespace {
+  /**
+   * ScopedResourceUpdate is a RAII wrapper for Windows resource updating
+   *
+   * Instances |EndUpdateResourceW()| their handles when they go out of scope.
+   * They pass |TRUE| as the second argument to |EndUpdateResourceW()|, which
+   * causes the resource update to be aborted (changes are discarded).
+   */
+  struct ScopedResourceUpdateTraits
+  {
+    typedef HANDLE type;
+    static type empty() { return NULL; }
+    static void release(type handle) {
+      if(NULL != handle) {
+        EndUpdateResourceW(handle, TRUE); // Discard changes
+      }
+    }
+  };
+
+  typedef Scoped<ScopedResourceUpdateTraits> ScopedResourceUpdate;
+};
+
 int
-main(int argc, char **argv)
+wmain(int argc, wchar_t** argv)
 {
   if (argc != 3) {
     printf("Usage: redit <exe file> <icon file>\n");
     return 1;
   }
 
-  int file = _open(argv[2], _O_BINARY | _O_RDONLY);
-  if (file == -1) {
+  mozilla::ScopedClose file;
+  if (0 != _wsopen_s(&file.rwget(),
+                     argv[2],
+                     _O_BINARY | _O_RDONLY,
+                     _SH_DENYWR,
+                     _S_IREAD)
+  || (-1 == file)) {
     fprintf(stderr, "Unable to open icon file.\n");
     return 1;
   }
 
   // Load all the data from the icon file
   long filesize = _filelength(file);
-  char* data = (char*)malloc(filesize);
+  nsAutoArrayPtr<BYTE> data(new BYTE[filesize]);
+  if(!data) {
+    fprintf(stderr, "Failed to allocate memory for icon file.\n");
+    return 1;
+  }
   _read(file, data, filesize);
-  _close(file);
-  IconHeader* header = (IconHeader*)data;
+
+  IconHeader* header = reinterpret_cast<IconHeader*>(data.get());
 
   // Open the target library for updating
-  HANDLE updateRes = BeginUpdateResource(argv[1], FALSE);
-  if (updateRes == NULL) {
+  ScopedResourceUpdate updateRes(BeginUpdateResourceW(argv[1], FALSE));
+  if (NULL == updateRes) {
     fprintf(stderr, "Unable to open library for modification.\n");
-    free(data);
     return 1;
   }
 
   // Allocate the group resource entry
-  long groupsize = sizeof(IconHeader) + header->ImageCount * sizeof(IconResEntry);
-  char* group = (char*)malloc(groupsize);
-  if (!group) {
+  long groupSize = sizeof(IconHeader)
+                 + header->ImageCount * sizeof(IconResEntry);
+  nsAutoArrayPtr<BYTE> group(new BYTE[groupSize]);
+  if(!group) {
     fprintf(stderr, "Failed to allocate memory for new images.\n");
-    free(data);
     return 1;
   }
   memcpy(group, data, sizeof(IconHeader));
 
-  IconDirEntry* sourceIcon = (IconDirEntry*)(data + sizeof(IconHeader));
-  IconResEntry* targetIcon = (IconResEntry*)(group + sizeof(IconHeader));
+  IconDirEntry* sourceIcon =
+                    reinterpret_cast<IconDirEntry*>(data
+                                                  + sizeof(IconHeader));
+  IconResEntry* targetIcon =
+                    reinterpret_cast<IconResEntry*>(group
+                                                  + sizeof(IconHeader));
 
   for (int id = 1; id <= header->ImageCount; id++) {
     // Add the individual icon
-    if (!UpdateResource(updateRes, RT_ICON, MAKEINTRESOURCE(id),
-                        MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
-                        data + sourceIcon->ImageOffset, sourceIcon->ImageSize)) {
-      fprintf(stderr, "Unable to update resource.\n");
-      EndUpdateResource(updateRes, TRUE);  // Discard changes, ignore errors
-      free(data);
-      free(group);
+    if (!UpdateResourceW(updateRes, RT_ICON, MAKEINTRESOURCE(id),
+                         MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+                         data + sourceIcon->ImageOffset,
+                         sourceIcon->ImageSize)) {
+      fprintf(stderr, "Unable to update resource (RT_ICON).\n");
       return 1;
     }
-    // Copy the data for this icon (note that the structs have different sizes)
+    // Copy the data for this icon
+    // (note that the structs have different sizes)
     memcpy(targetIcon, sourceIcon, sizeof(IconResEntry));
     targetIcon->ResourceID = id;
     sourceIcon++;
     targetIcon++;
   }
-  free(data);
 
-  if (!UpdateResource(updateRes, RT_GROUP_ICON, "MAINICON",
-                      MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
-                      group, groupsize)) {
-    fprintf(stderr, "Unable to update resource.\n");
-    EndUpdateResource(updateRes, TRUE);  // Discard changes
-    free(group);
+  if (!UpdateResourceW(updateRes, RT_GROUP_ICON, L"MAINICON",
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+                       group, groupSize)) {
+    fprintf(stderr, "Unable to update resource (RT_GROUP_ICON).\n");
     return 1;
   }
 
-  free(group);
-
   // Save the modifications
-  if (!EndUpdateResource(updateRes, FALSE)) {
+  if(!EndUpdateResourceW(updateRes.forget(), FALSE)) {
     fprintf(stderr, "Unable to write changes to library.\n");
     return 1;
   }
 
   return 0;
 }