summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Yee <ny.nathan.yee@gmail.com>2015-07-14 14:36:37 -0700
committerJan Holesovsky <kendy@collabora.com>2015-07-22 07:18:22 +0200
commitb59955bf2124b558147033782bf067a3723e4730 (patch)
treeeb009a5eaa41daaba94cb17c5b6368c4b96dff83
parent591238e8a4f1164adb51d3bada0cd90c3e7c655e (diff)
online update tdf#68274: fix --enable-online-update=mar on Windows
Change-Id: I397566ae2488799399cad361b24a281d3599cc5b
-rw-r--r--RepositoryExternal.mk8
-rw-r--r--external/bzip2/ExternalProject_bzip2.mk30
-rw-r--r--external/bzip2/Makefile14
-rw-r--r--external/bzip2/Module_bzip2.mk17
-rw-r--r--external/bzip2/README1
-rw-r--r--external/bzip2/UnpackedTarball_bzip2.mk24
-rw-r--r--onlineupdate/Executable_mar.mk7
-rw-r--r--onlineupdate/Executable_updater.mk41
-rw-r--r--onlineupdate/source/libmar/sign/mar_sign.c4
-rw-r--r--onlineupdate/source/libmar/sign/nss_secutil.c4
-rw-r--r--onlineupdate/source/libmar/src/mar.h2
-rw-r--r--onlineupdate/source/libmar/src/mar_create.c2
-rw-r--r--onlineupdate/source/libmar/src/mar_extract.c6
-rw-r--r--onlineupdate/source/libmar/src/mar_private.h2
-rw-r--r--onlineupdate/source/libmar/src/mar_read.c4
-rw-r--r--onlineupdate/source/libmar/tool/mar.c24
-rw-r--r--onlineupdate/source/libmar/verify/cryptox.c4
-rw-r--r--onlineupdate/source/libmar/verify/cryptox.h4
-rw-r--r--onlineupdate/source/libmar/verify/mar_verify.c2
-rw-r--r--onlineupdate/source/update/common/readstrings.h1
-rw-r--r--onlineupdate/source/update/common/updatehelper.cxx1
-rw-r--r--onlineupdate/source/update/inc/mozilla/Char16.h239
-rw-r--r--onlineupdate/source/update/inc/mozilla/Move.h238
-rw-r--r--onlineupdate/source/update/inc/mozilla/Pair.h219
-rw-r--r--onlineupdate/source/update/inc/mozilla/UniquePtr.h659
-rw-r--r--onlineupdate/source/update/inc/nsAutoRef.h670
-rw-r--r--onlineupdate/source/update/inc/nsWindowsHelpers.h159
-rw-r--r--onlineupdate/source/update/src/mar.h2
-rw-r--r--onlineupdate/source/update/src/mar_create.c2
-rw-r--r--onlineupdate/source/update/src/mar_extract.c6
-rw-r--r--onlineupdate/source/update/src/mar_private.h2
-rw-r--r--onlineupdate/source/update/src/mar_read.c4
-rw-r--r--onlineupdate/source/update/updater/archivereader.cxx1
-rw-r--r--onlineupdate/source/update/updater/loaddlls.cxx3
-rw-r--r--onlineupdate/source/update/updater/nsWindowsRestart.cxx584
-rw-r--r--onlineupdate/source/update/updater/progressui_win.cxx3
-rw-r--r--onlineupdate/source/update/updater/updater.cxx2
-rw-r--r--onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx19
-rw-r--r--onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h14
39 files changed, 2969 insertions, 59 deletions
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 75f033f4a193..7398916b76bc 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -4146,9 +4146,17 @@ $(call gb_LinkTarget_set_include,$(1),\
-I$(call gb_UnpackedTarball_get_dir,bzip2) \
$$(INCLUDE) \
)
+
+ifeq ($(COM),MSC)
+$(call gb_LinkTarget_add_libs,$(1),\
+ $(call gb_UnpackedTarball_get_dir,bzip2)/libbz2.lib \
+)
+else
$(call gb_LinkTarget_add_libs,$(1),\
-L$(call gb_UnpackedTarball_get_dir,bzip2) -lbz2 \
)
+endif
+
$(call gb_LinkTarget_use_external_project,$(1),bzip2)
endef
diff --git a/external/bzip2/ExternalProject_bzip2.mk b/external/bzip2/ExternalProject_bzip2.mk
new file mode 100644
index 000000000000..5b88ced29b10
--- /dev/null
+++ b/external/bzip2/ExternalProject_bzip2.mk
@@ -0,0 +1,30 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# 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/.
+#
+
+$(eval $(call gb_ExternalProject_ExternalProject,bzip2))
+
+$(eval $(call gb_ExternalProject_register_targets,bzip2,\
+ build \
+))
+
+$(eval $(call gb_ExternalProject_use_nmake,bzip2,build))
+
+ifeq ($(COM),MSC)
+$(call gb_ExternalProject_get_state_target,bzip2,build):
+ $(call gb_ExternalProject_run,build,\
+ nmake -nologo -f makefile.msc \
+ )
+else
+$(call gb_ExternalProject_get_state_target,bzip2,build):
+ $(call gb_ExternalProject_run,build,\
+ $(MAKE) \
+ )
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/bzip2/Makefile b/external/bzip2/Makefile
new file mode 100644
index 000000000000..569ad8a0ba7a
--- /dev/null
+++ b/external/bzip2/Makefile
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# 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/.
+#
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/bzip2/Module_bzip2.mk b/external/bzip2/Module_bzip2.mk
new file mode 100644
index 000000000000..2a59f7a6ae9c
--- /dev/null
+++ b/external/bzip2/Module_bzip2.mk
@@ -0,0 +1,17 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# 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/.
+#
+
+$(eval $(call gb_Module_Module,bzip2))
+
+$(eval $(call gb_Module_add_targets,bzip2,\
+ ExternalProject_bzip2 \
+ UnpackedTarball_bzip2 \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/bzip2/README b/external/bzip2/README
new file mode 100644
index 000000000000..917a9d662ba3
--- /dev/null
+++ b/external/bzip2/README
@@ -0,0 +1 @@
+Data compression library from [http://bzip.org/].
diff --git a/external/bzip2/UnpackedTarball_bzip2.mk b/external/bzip2/UnpackedTarball_bzip2.mk
new file mode 100644
index 000000000000..f22ca2b5ca8f
--- /dev/null
+++ b/external/bzip2/UnpackedTarball_bzip2.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# 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/.
+#
+
+$(eval $(call gb_UnpackedTarball_UnpackedTarball,bzip2))
+
+$(eval $(call gb_UnpackedTarball_set_tarball,bzip2,$(BZIP2_TARBALL)))
+
+$(eval $(call gb_UnpackedTarball_fix_end_of_line,bzip2,\
+ blocksort.c \
+ bzlib.c \
+ compress.c \
+ crctable.c \
+ decompress.c \
+ huffman.c \
+ randtable.c \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/onlineupdate/Executable_mar.mk b/onlineupdate/Executable_mar.mk
index 391f272d11eb..7a42b3ca437d 100644
--- a/onlineupdate/Executable_mar.mk
+++ b/onlineupdate/Executable_mar.mk
@@ -17,6 +17,13 @@ $(eval $(call gb_Executable_set_include,mar,\
$$(INCLUDE) \
))
+ifeq ($(OS),WNT)
+$(eval $(call gb_Executable_add_libs,mar,\
+ ws2_32.lib \
+ Crypt32.lib \
+))
+endif
+
$(eval $(call gb_Executable_use_externals,mar,nss3))
$(eval $(call gb_Executable_add_cobjects,mar,\
diff --git a/onlineupdate/Executable_updater.mk b/onlineupdate/Executable_updater.mk
index a4c4f9563108..eb94e8b92610 100644
--- a/onlineupdate/Executable_updater.mk
+++ b/onlineupdate/Executable_updater.mk
@@ -9,6 +9,15 @@
$(eval $(call gb_Executable_Executable,updater))
+ifeq ($(OS),WNT)
+$(eval $(call gb_Executable_set_include,updater,\
+ -I$(SRCDIR)/onlineupdate/source/update/src \
+ -I$(SRCDIR)/onlineupdate/source/update/inc \
+ -I$(SRCDIR)/onlineupdate/source/update/common \
+ -I$(SRCDIR)/onlineupdate/source/update/updater/xpcom/glue \
+ $$(INCLUDE) \
+))
+else
$(eval $(call gb_Executable_set_include,updater,\
-I$(SRCDIR)/onlineupdate/source/update/src \
-I$(SRCDIR)/onlineupdate/source/update/inc \
@@ -17,22 +26,36 @@ $(eval $(call gb_Executable_set_include,updater,\
-lpthread \
$$(INCLUDE) \
))
+endif
+ifeq ($(OS),WNT)
+$(eval $(call gb_Executable_add_libs,updater,\
+ Ws2_32.lib \
+ Gdi32.lib \
+ Comctl32.lib \
+ Shell32.lib \
+ Shlwapi.lib \
+))
+else
$(eval $(call gb_Executable_add_libs,updater,\
- -lX11 \
- -lXext \
- -lXrender \
- -lSM \
- -lICE \
+ -lX11 \
+ -lXext \
+ -lXrender \
+ -lSM \
+ -lICE \
+ $(GTK3_LIBS) \
))
+endif
+ifeq ($(OS),WNT)
$(eval $(call gb_Executable_add_cxxflags,updater,\
- $$(GTK3_CFLAGS) \
+ /Zc:wchar_t \
))
-
-$(eval $(call gb_Executable_add_libs,updater,\
- $(GTK3_LIBS) \
+else
+$(eval $(call gb_Executable_add_cxxflags,updater,\
+ $$(GTK3_CFLAGS) \
))
+endif
$(eval $(call gb_Executable_use_externals,updater,\
gtk \
diff --git a/onlineupdate/source/libmar/sign/mar_sign.c b/onlineupdate/source/libmar/sign/mar_sign.c
index 775b545cf346..4a5fe87fd402 100644
--- a/onlineupdate/source/libmar/sign/mar_sign.c
+++ b/onlineupdate/source/libmar/sign/mar_sign.c
@@ -2,7 +2,7 @@
* 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/. */
-#ifdef XP_WIN
+#ifdef WNT
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -17,7 +17,7 @@
#include "mar_cmdline.h"
#include "mar.h"
#include "cryptox.h"
-#ifndef XP_WIN
+#ifndef WNT
#include <unistd.h>
#endif
diff --git a/onlineupdate/source/libmar/sign/nss_secutil.c b/onlineupdate/source/libmar/sign/nss_secutil.c
index b98834c46141..caa124e651d7 100644
--- a/onlineupdate/source/libmar/sign/nss_secutil.c
+++ b/onlineupdate/source/libmar/sign/nss_secutil.c
@@ -8,14 +8,14 @@
#include "nss_secutil.h"
#include "prprf.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <io.h>
#else
#include <unistd.h>
#endif
static char consoleName[] = {
-#ifdef XP_UNIX
+#ifdef UNIX
"/dev/tty"
#else
"CON:"
diff --git a/onlineupdate/source/libmar/src/mar.h b/onlineupdate/source/libmar/src/mar.h
index 0e9dc1f137bd..31cc3934e395 100644
--- a/onlineupdate/source/libmar/src/mar.h
+++ b/onlineupdate/source/libmar/src/mar.h
@@ -69,7 +69,7 @@ typedef int (* MarItemCallback)(MarFile *mar, const MarItem *item, void *data);
*/
MarFile *mar_open(const char *path);
-#ifdef XP_WIN
+#ifdef WNT
MarFile *mar_wopen(const wchar_t *path);
#endif
diff --git a/onlineupdate/source/libmar/src/mar_create.c b/onlineupdate/source/libmar/src/mar_create.c
index c2ce10126cbd..a87e937fe4a3 100644
--- a/onlineupdate/source/libmar/src/mar_create.c
+++ b/onlineupdate/source/libmar/src/mar_create.c
@@ -13,7 +13,7 @@
#include "mar_cmdline.h"
#include "mar.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <winsock2.h>
#else
#include <netinet/in.h>
diff --git a/onlineupdate/source/libmar/src/mar_extract.c b/onlineupdate/source/libmar/src/mar_extract.c
index ec1cd6c53446..f3512e99122c 100644
--- a/onlineupdate/source/libmar/src/mar_extract.c
+++ b/onlineupdate/source/libmar/src/mar_extract.c
@@ -12,7 +12,7 @@
#include "mar_private.h"
#include "mar.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <io.h>
#include <direct.h>
#endif
@@ -25,7 +25,7 @@ static int mar_ensure_parent_dir(const char *path)
{
*slash = '\0';
mar_ensure_parent_dir(path);
-#ifdef XP_WIN
+#ifdef WNT
_mkdir(path);
#else
mkdir(path, 0755);
@@ -43,7 +43,7 @@ static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) {
if (mar_ensure_parent_dir(item->name))
return -1;
-#ifdef XP_WIN
+#ifdef WNT
fd = _open(item->name, _O_BINARY|_O_CREAT|_O_TRUNC|_O_WRONLY, item->flags);
#else
fd = creat(item->name, item->flags);
diff --git a/onlineupdate/source/libmar/src/mar_private.h b/onlineupdate/source/libmar/src/mar_private.h
index 8a7fb45ccd82..39a77d1ac03e 100644
--- a/onlineupdate/source/libmar/src/mar_private.h
+++ b/onlineupdate/source/libmar/src/mar_private.h
@@ -53,7 +53,7 @@ MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < \
/* The mar program is compiled as a host bin so we don't have access to NSPR at
runtime. For that reason we use ntohl, htonl, and define HOST_TO_NETWORK64
instead of the NSPR equivalents. */
-#ifdef XP_WIN
+#ifdef WNT
#include <winsock2.h>
#define ftello _ftelli64
#define fseeko _fseeki64
diff --git a/onlineupdate/source/libmar/src/mar_read.c b/onlineupdate/source/libmar/src/mar_read.c
index 7be225385403..c7c4bdf19554 100644
--- a/onlineupdate/source/libmar/src/mar_read.c
+++ b/onlineupdate/source/libmar/src/mar_read.c
@@ -11,7 +11,7 @@
#include "mar_private.h"
#include "mar.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <winsock2.h>
#else
#include <netinet/in.h>
@@ -177,7 +177,7 @@ MarFile *mar_open(const char *path) {
return mar_fpopen(fp);
}
-#ifdef XP_WIN
+#ifdef WNT
MarFile *mar_wopen(const wchar_t *path) {
FILE *fp;
diff --git a/onlineupdate/source/libmar/tool/mar.c b/onlineupdate/source/libmar/tool/mar.c
index 9a50b387f839..9a961ae9aabd 100644
--- a/onlineupdate/source/libmar/tool/mar.c
+++ b/onlineupdate/source/libmar/tool/mar.c
@@ -10,7 +10,7 @@
#include "mar.h"
#include "mar_cmdline.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <windows.h>
#include <direct.h>
#define chdir _chdir
@@ -23,7 +23,7 @@
#define MAR_CHANNEL_ID "LOOnlineUpdater" /* Dummy value; replace or
remove in the future */
-#if !defined(NO_SIGN_VERIFY) && (!defined(XP_WIN) || defined(MAR_NSS))
+#if !defined(NO_SIGN_VERIFY) && (!defined(WNT) || defined(MAR_NSS))
#include "cert.h"
#include "pk11pub.h"
int NSSInitCryptoContext(const char *NSSConfigDir);
@@ -66,7 +66,7 @@ static void print_usage() {
"signed_input_archive.mar base_64_encoded_signature_file "
"changed_signed_output.mar\n");
printf("(i) is the index of the certificate to extract\n");
-#if defined(XP_MACOSX) || (defined(XP_WIN) && !defined(MAR_NSS))
+#if defined(MACOSX) || (defined(WNT) && !defined(MAR_NSS))
printf("Verify a MAR file:\n");
printf(" mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
printf("At most %d signature certificate DER files are specified by "
@@ -131,17 +131,17 @@ int main(int argc, char **argv) {
uint32_t fileSizes[MAX_SIGNATURES];
const uint8_t* certBuffers[MAX_SIGNATURES];
char* DERFilePaths[MAX_SIGNATURES];
-#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
+#if (!defined(WNT) && !defined(MACOSX)) || defined(MAR_NSS)
CERTCertificate* certs[MAX_SIGNATURES];
#endif
#endif
memset((void*)certNames, 0, sizeof(certNames));
-#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
+#if defined(WNT) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
memset((void*)certBuffers, 0, sizeof(certBuffers));
#endif
-#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
- defined(XP_MACOSX))
+#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(WNT)) || \
+ defined(MACOSX))
memset(DERFilePaths, 0, sizeof(DERFilePaths));
memset(fileSizes, 0, sizeof(fileSizes));
#endif
@@ -170,8 +170,8 @@ int main(int argc, char **argv) {
argv += 2;
argc -= 2;
}
-#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
- defined(XP_MACOSX))
+#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(WNT)) || \
+ defined(MACOSX))
/* -D DERFilePath, also matches -D[index] DERFilePath
We allow an index for verifying to be symmetric
with the import and export command line arguments. */
@@ -329,7 +329,7 @@ int main(int argc, char **argv) {
return -1;
}
-#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
+#if (!defined(WNT) && !defined(MACOSX)) || defined(MAR_NSS)
if (!NSSConfigDir || certCount == 0) {
print_usage();
return -1;
@@ -343,7 +343,7 @@ int main(int argc, char **argv) {
rv = 0;
for (k = 0; k < certCount; ++k) {
-#if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
+#if (defined(WNT) || defined(MACOSX)) && !defined(MAR_NSS)
rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE,
&certBuffers[k], &fileSizes[k]);
#else
@@ -380,7 +380,7 @@ int main(int argc, char **argv) {
}
}
for (k = 0; k < certCount; ++k) {
-#if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
+#if (defined(WNT) || defined(MACOSX)) && !defined(MAR_NSS)
free((void*)certBuffers[k]);
#else
/* certBuffers[k] is owned by certs[k] so don't free it */
diff --git a/onlineupdate/source/libmar/verify/cryptox.c b/onlineupdate/source/libmar/verify/cryptox.c
index 106ec29d8a27..b1859b72c749 100644
--- a/onlineupdate/source/libmar/verify/cryptox.c
+++ b/onlineupdate/source/libmar/verify/cryptox.c
@@ -2,7 +2,7 @@
* 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/. */
-#ifdef XP_WIN
+#ifdef WNT
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -99,7 +99,7 @@ NSS_VerifySignature(VFYContext * const *ctx,
return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
}
-#elif defined(XP_WIN)
+#elif defined(WNT)
/**
* Verifies if a signature + public key matches a hash context.
*
diff --git a/onlineupdate/source/libmar/verify/cryptox.h b/onlineupdate/source/libmar/verify/cryptox.h
index 9cca033a299e..8b926814a70b 100644
--- a/onlineupdate/source/libmar/verify/cryptox.h
+++ b/onlineupdate/source/libmar/verify/cryptox.h
@@ -57,7 +57,7 @@ CryptoX_Result NSS_VerifySignature(VFYContext * const *ctx ,
#define CryptoX_FreeCertificate(cert) \
CERT_DestroyCertificate(*cert)
-#elif XP_MACOSX
+#elif MACOSX
#define CryptoX_InvalidHandleValue NULL
#define CryptoX_ProviderHandle void*
@@ -104,7 +104,7 @@ void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey);
CryptoMac_FreePublicKey(aPublicKey)
#define CryptoX_FreeCertificate(aCertificate)
-#elif defined(XP_WIN)
+#elif defined(WNT)
#include <windows.h>
#include <wincrypt.h>
diff --git a/onlineupdate/source/libmar/verify/mar_verify.c b/onlineupdate/source/libmar/verify/mar_verify.c
index 6c421b27d08a..954fbbb5e659 100644
--- a/onlineupdate/source/libmar/verify/mar_verify.c
+++ b/onlineupdate/source/libmar/verify/mar_verify.c
@@ -2,7 +2,7 @@
* 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/. */
-#ifdef XP_WIN
+#ifdef WNT
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
diff --git a/onlineupdate/source/update/common/readstrings.h b/onlineupdate/source/update/common/readstrings.h
index 99e515daa611..ecef9aa5e6b9 100644
--- a/onlineupdate/source/update/common/readstrings.h
+++ b/onlineupdate/source/update/common/readstrings.h
@@ -10,6 +10,7 @@
#define MAX_TEXT_LEN 600
#ifdef WNT
+# define UNICODE
# include <windows.h>
typedef WCHAR NS_tchar;
#else
diff --git a/onlineupdate/source/update/common/updatehelper.cxx b/onlineupdate/source/update/common/updatehelper.cxx
index 579515430115..3e91feae3253 100644
--- a/onlineupdate/source/update/common/updatehelper.cxx
+++ b/onlineupdate/source/update/common/updatehelper.cxx
@@ -22,7 +22,6 @@
using mozilla::MakeUnique;
using mozilla::UniquePtr;
-WCHAR* MakeCommandLine(int argc, WCHAR **argv);
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra);
/**
diff --git a/onlineupdate/source/update/inc/mozilla/Char16.h b/onlineupdate/source/update/inc/mozilla/Char16.h
new file mode 100644
index 000000000000..f07494f7f47f
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Char16.h
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Implements a UTF-16 character type. */
+
+#ifndef mozilla_Char16_h
+#define mozilla_Char16_h
+
+#ifdef __cplusplus
+
+/*
+ * C++11 introduces a char16_t type and support for UTF-16 string and character
+ * literals. C++11's char16_t is a distinct builtin type. Technically, char16_t
+ * is a 16-bit code unit of a Unicode code point, not a "character".
+ */
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+ /*
+ * C++11 says char16_t is a distinct builtin type, but Windows's yvals.h
+ * typedefs char16_t as an unsigned short prior to MSVC 2015, which
+ * implemented C++11's distinct char16_t type. We would like to alias
+ * char16_t to Windows's 16-bit wchar_t so we can declare UTF-16 literals as
+ * constant expressions (and pass char16_t pointers to Windows APIs). We
+ * #define _CHAR16T here in order to prevent yvals.h from overriding our
+ * char16_t typedefs, which we set to wchar_t for C++ code.
+ *
+ * In addition, #defining _CHAR16T will prevent yvals.h from defining a
+ * char32_t type, so we have to undo that damage here and provide our own,
+ * which is identical to the yvals.h type.
+ */
+# define MOZ_UTF16_HELPER(s) L##s
+# define _CHAR16T
+typedef wchar_t char16_t;
+typedef unsigned int char32_t;
+#else
+ /* C++11 has a builtin char16_t type. */
+# define MOZ_UTF16_HELPER(s) u##s
+ /**
+ * This macro is used to distinguish when char16_t would be a distinct
+ * typedef from wchar_t.
+ */
+# define MOZ_CHAR16_IS_NOT_WCHAR
+# ifdef WIN32
+# define MOZ_USE_CHAR16_WRAPPER
+# endif
+#endif
+
+#ifdef MOZ_USE_CHAR16_WRAPPER
+# include <string>
+ /**
+ * Win32 API extensively uses wchar_t, which is represented by a separated
+ * builtin type than char16_t per spec. It's not the case for MSVC prior to
+ * MSVC 2015, but other compilers follow the spec. We want to mix wchar_t and
+ * char16_t on Windows builds. This class is supposed to make it easier. It
+ * stores char16_t const pointer, but provides implicit casts for wchar_t as
+ * well. On other platforms, we simply use
+ * |typedef const char16_t* char16ptr_t|. Here, we want to make the class as
+ * similar to this typedef, including providing some casts that are allowed
+ * by the typedef.
+ */
+class char16ptr_t
+{
+private:
+ const char16_t* mPtr;
+ static_assert(sizeof(char16_t) == sizeof(wchar_t),
+ "char16_t and wchar_t sizes differ");
+
+public:
+ char16ptr_t(const char16_t* aPtr) : mPtr(aPtr) {}
+ char16ptr_t(const wchar_t* aPtr) :
+ mPtr(reinterpret_cast<const char16_t*>(aPtr))
+ {}
+
+ /* Without this, nullptr assignment would be ambiguous. */
+ constexpr char16ptr_t(decltype(nullptr)) : mPtr(nullptr) {}
+
+ operator const char16_t*() const
+ {
+ return mPtr;
+ }
+ operator const wchar_t*() const
+ {
+ return reinterpret_cast<const wchar_t*>(mPtr);
+ }
+ operator const void*() const
+ {
+ return mPtr;
+ }
+ operator bool() const
+ {
+ return mPtr != nullptr;
+ }
+ operator std::wstring() const
+ {
+ return std::wstring(static_cast<const wchar_t*>(*this));
+ }
+
+ /* Explicit cast operators to allow things like (char16_t*)str. */
+ explicit operator char16_t*() const
+ {
+ return const_cast<char16_t*>(mPtr);
+ }
+ explicit operator wchar_t*() const
+ {
+ return const_cast<wchar_t*>(static_cast<const wchar_t*>(*this));
+ }
+ explicit operator int() const
+ {
+ return reinterpret_cast<intptr_t>(mPtr);
+ }
+ explicit operator unsigned int() const
+ {
+ return reinterpret_cast<uintptr_t>(mPtr);
+ }
+ explicit operator long() const
+ {
+ return reinterpret_cast<intptr_t>(mPtr);
+ }
+ explicit operator unsigned long() const
+ {
+ return reinterpret_cast<uintptr_t>(mPtr);
+ }
+ explicit operator long long() const
+ {
+ return reinterpret_cast<intptr_t>(mPtr);
+ }
+ explicit operator unsigned long long() const
+ {
+ return reinterpret_cast<uintptr_t>(mPtr);
+ }
+
+ /**
+ * Some Windows API calls accept BYTE* but require that data actually be
+ * WCHAR*. Supporting this requires explicit operators to support the
+ * requisite explicit casts.
+ */
+ explicit operator const char*() const
+ {
+ return reinterpret_cast<const char*>(mPtr);
+ }
+ explicit operator const unsigned char*() const
+ {
+ return reinterpret_cast<const unsigned char*>(mPtr);
+ }
+ explicit operator unsigned char*() const
+ {
+ return
+ const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(mPtr));
+ }
+ explicit operator void*() const
+ {
+ return const_cast<char16_t*>(mPtr);
+ }
+
+ /* Some operators used on pointers. */
+ char16_t operator[](size_t aIndex) const
+ {
+ return mPtr[aIndex];
+ }
+ bool operator==(const char16ptr_t& aOther) const
+ {
+ return mPtr == aOther.mPtr;
+ }
+ bool operator==(decltype(nullptr)) const
+ {
+ return mPtr == nullptr;
+ }
+ bool operator!=(const char16ptr_t& aOther) const
+ {
+ return mPtr != aOther.mPtr;
+ }
+ bool operator!=(decltype(nullptr)) const
+ {
+ return mPtr != nullptr;
+ }
+ char16ptr_t operator+(int aValue) const
+ {
+ return char16ptr_t(mPtr + aValue);
+ }
+ char16ptr_t operator+(unsigned int aValue) const
+ {
+ return char16ptr_t(mPtr + aValue);
+ }
+ char16ptr_t operator+(long aValue) const
+ {
+ return char16ptr_t(mPtr + aValue);
+ }
+ char16ptr_t operator+(unsigned long aValue) const
+ {
+ return char16ptr_t(mPtr + aValue);
+ }
+ char16ptr_t operator+(long long aValue) const
+ {
+ return char16ptr_t(mPtr + aValue);
+ }
+ char16ptr_t operator+(unsigned long long aValue) const
+ {
+ return char16ptr_t(mPtr + aValue);
+ }
+ ptrdiff_t operator-(const char16ptr_t& aOther) const
+ {
+ return mPtr - aOther.mPtr;
+ }
+};
+
+inline decltype((char*)0-(char*)0)
+operator-(const char16_t* aX, const char16ptr_t aY)
+{
+ return aX - static_cast<const char16_t*>(aY);
+}
+
+#else
+
+typedef const char16_t* char16ptr_t;
+
+#endif
+
+/*
+ * Macro arguments used in concatenation or stringification won't be expanded.
+ * Therefore, in order for |MOZ_UTF16(FOO)| to work as expected (which is to
+ * expand |FOO| before doing whatever |MOZ_UTF16| needs to do to it) a helper
+ * macro, |MOZ_UTF16_HELPER| needs to be inserted in between to allow the macro
+ * argument to expand. See "3.10.6 Separate Expansion of Macro Arguments" of the
+ * CPP manual for a more accurate and precise explanation.
+ */
+#define MOZ_UTF16(s) MOZ_UTF16_HELPER(s)
+
+static_assert(sizeof(char16_t) == 2, "Is char16_t type 16 bits?");
+static_assert(char16_t(-1) > char16_t(0), "Is char16_t type unsigned?");
+static_assert(sizeof(MOZ_UTF16('A')) == 2, "Is char literal 16 bits?");
+static_assert(sizeof(MOZ_UTF16("")[0]) == 2, "Is string char 16 bits?");
+
+#endif
+
+#endif /* mozilla_Char16_h */
+
diff --git a/onlineupdate/source/update/inc/mozilla/Move.h b/onlineupdate/source/update/inc/mozilla/Move.h
new file mode 100644
index 000000000000..f6d0bfc1ca38
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Move.h
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* C++11-style, but C++98-usable, "move references" implementation. */
+
+#ifndef mozilla_Move_h
+#define mozilla_Move_h
+
+#include "mozilla/TypeTraits.h"
+
+namespace mozilla {
+
+/*
+ * "Move" References
+ *
+ * Some types can be copied much more efficiently if we know the original's
+ * value need not be preserved --- that is, if we are doing a "move", not a
+ * "copy". For example, if we have:
+ *
+ * Vector<T> u;
+ * Vector<T> v(u);
+ *
+ * the constructor for v must apply a copy constructor to each element of u ---
+ * taking time linear in the length of u. However, if we know we will not need u
+ * any more once v has been initialized, then we could initialize v very
+ * efficiently simply by stealing u's dynamically allocated buffer and giving it
+ * to v --- a constant-time operation, regardless of the size of u.
+ *
+ * Moves often appear in container implementations. For example, when we append
+ * to a vector, we may need to resize its buffer. This entails moving each of
+ * its extant elements from the old, smaller buffer to the new, larger buffer.
+ * But once the elements have been migrated, we're just going to throw away the
+ * old buffer; we don't care if they still have their values. So if the vector's
+ * element type can implement "move" more efficiently than "copy", the vector
+ * resizing should by all means use a "move" operation. Hash tables should also
+ * use moves when resizing their internal array as entries are added and
+ * removed.
+ *
+ * The details of the optimization, and whether it's worth applying, vary
+ * from one type to the next: copying an 'int' is as cheap as moving it, so
+ * there's no benefit in distinguishing 'int' moves from copies. And while
+ * some constructor calls for complex types are moves, many really have to
+ * be copies, and can't be optimized this way. So we need:
+ *
+ * 1) a way for a type (like Vector) to announce that it can be moved more
+ * efficiently than it can be copied, and provide an implementation of that
+ * move operation; and
+ *
+ * 2) a way for a particular invocation of a copy constructor to say that it's
+ * really a move, not a copy, and that the value of the original isn't
+ * important afterwards (although it must still be safe to destroy).
+ *
+ * If a constructor has a single argument of type 'T&&' (an 'rvalue reference
+ * to T'), that indicates that it is a 'move constructor'. That's 1). It should
+ * move, not copy, its argument into the object being constructed. It may leave
+ * the original in any safely-destructible state.
+ *
+ * If a constructor's argument is an rvalue, as in 'C(f(x))' or 'C(x + y)', as
+ * opposed to an lvalue, as in 'C(x)', then overload resolution will prefer the
+ * move constructor, if there is one. The 'mozilla::Move' function, defined in
+ * this file, is an identity function you can use in a constructor invocation to
+ * make any argument into an rvalue, like this: C(Move(x)). That's 2). (You
+ * could use any function that works, but 'Move' indicates your intention
+ * clearly.)
+ *
+ * Where we might define a copy constructor for a class C like this:
+ *
+ * C(const C& rhs) { ... copy rhs to this ... }
+ *
+ * we would declare a move constructor like this:
+ *
+ * C(C&& rhs) { .. move rhs to this ... }
+ *
+ * And where we might perform a copy like this:
+ *
+ * C c2(c1);
+ *
+ * we would perform a move like this:
+ *
+ * C c2(Move(c1));
+ *
+ * Note that 'T&&' implicitly converts to 'T&'. So you can pass a 'T&&' to an
+ * ordinary copy constructor for a type that doesn't support a special move
+ * constructor, and you'll just get a copy. This means that templates can use
+ * Move whenever they know they won't use the original value any more, even if
+ * they're not sure whether the type at hand has a specialized move constructor.
+ * If it doesn't, the 'T&&' will just convert to a 'T&', and the ordinary copy
+ * constructor will apply.
+ *
+ * A class with a move constructor can also provide a move assignment operator.
+ * A generic definition would run this's destructor, and then apply the move
+ * constructor to *this's memory. A typical definition:
+ *
+ * C& operator=(C&& rhs) {
+ * MOZ_ASSERT(&rhs != this, "self-moves are prohibited");
+ * this->~C();
+ * new(this) C(Move(rhs));
+ * return *this;
+ * }
+ *
+ * With that in place, one can write move assignments like this:
+ *
+ * c2 = Move(c1);
+ *
+ * This destroys c2, moves c1's value to c2, and leaves c1 in an undefined but
+ * destructible state.
+ *
+ * As we say, a move must leave the original in a "destructible" state. The
+ * original's destructor will still be called, so if a move doesn't
+ * actually steal all its resources, that's fine. We require only that the
+ * move destination must take on the original's value; and that destructing
+ * the original must not break the move destination.
+ *
+ * (Opinions differ on whether move assignment operators should deal with move
+ * assignment of an object onto itself. It seems wise to either handle that
+ * case, or assert that it does not occur.)
+ *
+ * Forwarding:
+ *
+ * Sometimes we want copy construction or assignment if we're passed an ordinary
+ * value, but move construction if passed an rvalue reference. For example, if
+ * our constructor takes two arguments and either could usefully be a move, it
+ * seems silly to write out all four combinations:
+ *
+ * C::C(X& x, Y& y) : x(x), y(y) { }
+ * C::C(X& x, Y&& y) : x(x), y(Move(y)) { }
+ * C::C(X&& x, Y& y) : x(Move(x)), y(y) { }
+ * C::C(X&& x, Y&& y) : x(Move(x)), y(Move(y)) { }
+ *
+ * To avoid this, C++11 has tweaks to make it possible to write what you mean.
+ * The four constructor overloads above can be written as one constructor
+ * template like so[0]:
+ *
+ * template <typename XArg, typename YArg>
+ * C::C(XArg&& x, YArg&& y) : x(Forward<XArg>(x)), y(Forward<YArg>(y)) { }
+ *
+ * ("'Don't Repeat Yourself'? What's that?")
+ *
+ * This takes advantage of two new rules in C++11:
+ *
+ * - First, when a function template takes an argument that is an rvalue
+ * reference to a template argument (like 'XArg&& x' and 'YArg&& y' above),
+ * then when the argument is applied to an lvalue, the template argument
+ * resolves to 'T&'; and when it is applied to an rvalue, the template
+ * argument resolves to 'T'. Thus, in a call to C::C like:
+ *
+ * X foo(int);
+ * Y yy;
+ *
+ * C(foo(5), yy)
+ *
+ * XArg would resolve to 'X', and YArg would resolve to 'Y&'.
+ *
+ * - Second, Whereas C++ used to forbid references to references, C++11 defines
+ * 'collapsing rules': 'T& &', 'T&& &', and 'T& &&' (that is, any combination
+ * involving an lvalue reference) now collapse to simply 'T&'; and 'T&& &&'
+ * collapses to 'T&&'.
+ *
+ * Thus, in the call above, 'XArg&&' is 'X&&'; and 'YArg&&' is 'Y& &&', which
+ * collapses to 'Y&'. Because the arguments are declared as rvalue references
+ * to template arguments, the lvalue-ness "shines through" where present.
+ *
+ * Then, the 'Forward<T>' function --- you must invoke 'Forward' with its type
+ * argument --- returns an lvalue reference or an rvalue reference to its
+ * argument, depending on what T is. In our unified constructor definition, that
+ * means that we'll invoke either the copy or move constructors for x and y,
+ * depending on what we gave C's constructor. In our call, we'll move 'foo()'
+ * into 'x', but copy 'yy' into 'y'.
+ *
+ * This header file defines Move and Forward in the mozilla namespace. It's up
+ * to individual containers to annotate moves as such, by calling Move; and it's
+ * up to individual types to define move constructors and assignment operators
+ * when valuable.
+ *
+ * (C++11 says that the <utility> header file should define 'std::move' and
+ * 'std::forward', which are just like our 'Move' and 'Forward'; but those
+ * definitions aren't available in that header on all our platforms, so we
+ * define them ourselves here.)
+ *
+ * 0. This pattern is known as "perfect forwarding". Interestingly, it is not
+ * actually perfect, and it can't forward all possible argument expressions!
+ * There is a C++11 issue: you can't form a reference to a bit-field. As a
+ * workaround, assign the bit-field to a local variable and use that:
+ *
+ * // C is as above
+ * struct S { int x : 1; } s;
+ * C(s.x, 0); // BAD: s.x is a reference to a bit-field, can't form those
+ * int tmp = s.x;
+ * C(tmp, 0); // OK: tmp not a bit-field
+ */
+
+/**
+ * Identical to std::Move(); this is necessary until our stlport supports
+ * std::move().
+ */
+template<typename T>
+inline typename RemoveReference<T>::Type&&
+Move(T&& aX)
+{
+ return static_cast<typename RemoveReference<T>::Type&&>(aX);
+}
+
+/**
+ * These two overloads are identical to std::forward(); they are necessary until
+ * our stlport supports std::forward().
+ */
+template<typename T>
+inline T&&
+Forward(typename RemoveReference<T>::Type& aX)
+{
+ return static_cast<T&&>(aX);
+}
+
+template<typename T>
+inline T&&
+Forward(typename RemoveReference<T>::Type&& aX)
+{
+ static_assert(!IsLvalueReference<T>::value,
+ "misuse of Forward detected! try the other overload");
+ return static_cast<T&&>(aX);
+}
+
+/** Swap |aX| and |aY| using move-construction if possible. */
+template<typename T>
+inline void
+Swap(T& aX, T& aY)
+{
+ T tmp(Move(aX));
+ aX = Move(aY);
+ aY = Move(tmp);
+}
+
+} // namespace mozilla
+
+#endif /* mozilla_Move_h */
diff --git a/onlineupdate/source/update/inc/mozilla/Pair.h b/onlineupdate/source/update/inc/mozilla/Pair.h
new file mode 100644
index 000000000000..ad7b86a29c62
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/Pair.h
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* A class holding a pair of objects that tries to conserve storage space. */
+
+#ifndef mozilla_Pair_h
+#define mozilla_Pair_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
+#include "mozilla/TypeTraits.h"
+
+namespace mozilla {
+
+namespace detail {
+
+enum StorageType { AsBase, AsMember };
+
+// Optimize storage using the Empty Base Optimization -- that empty base classes
+// don't take up space -- to optimize size when one or the other class is
+// stateless and can be used as a base class.
+//
+// The extra conditions on storage for B are necessary so that PairHelper won't
+// ambiguously inherit from either A or B, such that one or the other base class
+// would be inaccessible.
+template<typename A, typename B,
+ detail::StorageType =
+ IsEmpty<A>::value ? detail::AsBase : detail::AsMember,
+ detail::StorageType =
+ IsEmpty<B>::value && !IsBaseOf<A, B>::value && !IsBaseOf<B, A>::value
+ ? detail::AsBase
+ : detail::AsMember>
+struct PairHelper;
+
+template<typename A, typename B>
+struct PairHelper<A, B, AsMember, AsMember>
+{
+protected:
+ template<typename AArg, typename BArg>
+ PairHelper(AArg&& aA, BArg&& aB)
+ : mFirstA(Forward<AArg>(aA)),
+ mSecondB(Forward<BArg>(aB))
+ {}
+
+ A& first() { return mFirstA; }
+ const A& first() const { return mFirstA; }
+ B& second() { return mSecondB; }
+ const B& second() const { return mSecondB; }
+
+ void swap(PairHelper& aOther)
+ {
+ Swap(mFirstA, aOther.mFirstA);
+ Swap(mSecondB, aOther.mSecondB);
+ }
+
+private:
+ A mFirstA;
+ B mSecondB;
+};
+
+template<typename A, typename B>
+struct PairHelper<A, B, AsMember, AsBase> : private B
+{
+protected:
+ template<typename AArg, typename BArg>
+ PairHelper(AArg&& aA, BArg&& aB)
+ : B(Forward<BArg>(aB)),
+ mFirstA(Forward<AArg>(aA))
+ {}
+
+ A& first() { return mFirstA; }
+ const A& first() const { return mFirstA; }
+ B& second() { return *this; }
+ const B& second() const { return *this; }
+
+ void swap(PairHelper& aOther)
+ {
+ Swap(mFirstA, aOther.mFirstA);
+ Swap(static_cast<B&>(*this), static_cast<B&>(aOther));
+ }
+
+private:
+ A mFirstA;
+};
+
+template<typename A, typename B>
+struct PairHelper<A, B, AsBase, AsMember> : private A
+{
+protected:
+ template<typename AArg, typename BArg>
+ PairHelper(AArg&& aA, BArg&& aB)
+ : A(Forward<AArg>(aA)),
+ mSecondB(Forward<BArg>(aB))
+ {}
+
+ A& first() { return *this; }
+ const A& first() const { return *this; }
+ B& second() { return mSecondB; }
+ const B& second() const { return mSecondB; }
+
+ void swap(PairHelper& aOther)
+ {
+ Swap(static_cast<A&>(*this), static_cast<A&>(aOther));
+ Swap(mSecondB, aOther.mSecondB);
+ }
+
+private:
+ B mSecondB;
+};
+
+template<typename A, typename B>
+struct PairHelper<A, B, AsBase, AsBase> : private A, private B
+{
+protected:
+ template<typename AArg, typename BArg>
+ PairHelper(AArg&& aA, BArg&& aB)
+ : A(Forward<AArg>(aA)),
+ B(Forward<BArg>(aB))
+ {}
+
+ A& first() { return static_cast<A&>(*this); }
+ const A& first() const { return static_cast<A&>(*this); }
+ B& second() { return static_cast<B&>(*this); }
+ const B& second() const { return static_cast<B&>(*this); }
+
+ void swap(PairHelper& aOther)
+ {
+ Swap(static_cast<A&>(*this), static_cast<A&>(aOther));
+ Swap(static_cast<B&>(*this), static_cast<B&>(aOther));
+ }
+};
+
+} // namespace detail
+
+/**
+ * Pair is the logical concatenation of an instance of A with an instance B.
+ * Space is conserved when possible. Neither A nor B may be a final class.
+ *
+ * It's typically clearer to have individual A and B member fields. Except if
+ * you want the space-conserving qualities of Pair, you're probably better off
+ * not using this!
+ *
+ * No guarantees are provided about the memory layout of A and B, the order of
+ * initialization or destruction of A and B, and so on. (This is approximately
+ * required to optimize space usage.) The first/second names are merely
+ * conceptual!
+ */
+template<typename A, typename B>
+struct Pair
+ : private detail::PairHelper<A, B>
+{
+ typedef typename detail::PairHelper<A, B> Base;
+
+public:
+ template<typename AArg, typename BArg>
+ Pair(AArg&& aA, BArg&& aB)
+ : Base(Forward<AArg>(aA), Forward<BArg>(aB))
+ {}
+
+ Pair(Pair&& aOther)
+ : Base(Move(aOther.first()), Move(aOther.second()))
+ { }
+
+ Pair(const Pair& aOther) = default;
+
+ Pair& operator=(Pair&& aOther)
+ {
+ MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
+
+ first() = Move(aOther.first());
+ second() = Move(aOther.second());
+
+ return *this;
+ }
+
+ Pair& operator=(const Pair& aOther) = default;
+
+ /** The A instance. */
+ using Base::first;
+ /** The B instance. */
+ using Base::second;
+
+ /** Swap this pair with another pair. */
+ void swap(Pair& aOther) { Base::swap(aOther); }
+};
+
+template<typename A, class B>
+void
+Swap(Pair<A, B>& aX, Pair<A, B>& aY)
+{
+ aX.swap(aY);
+}
+
+/**
+ * MakePair allows you to construct a Pair instance using type inference. A call
+ * like this:
+ *
+ * MakePair(Foo(), Bar())
+ *
+ * will return a Pair<Foo, Bar>.
+ */
+template<typename A, typename B>
+Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
+ typename RemoveCV<typename RemoveReference<B>::Type>::Type>
+MakePair(A&& aA, B&& aB)
+{
+ return
+ Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
+ typename RemoveCV<typename RemoveReference<B>::Type>::Type>(
+ Forward<A>(aA),
+ Forward<B>(aB));
+}
+
+} // namespace mozilla
+
+#endif /* mozilla_Pair_h */
diff --git a/onlineupdate/source/update/inc/mozilla/UniquePtr.h b/onlineupdate/source/update/inc/mozilla/UniquePtr.h
new file mode 100644
index 000000000000..d58ffe335c53
--- /dev/null
+++ b/onlineupdate/source/update/inc/mozilla/UniquePtr.h
@@ -0,0 +1,659 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Smart pointer managing sole ownership of a resource. */
+
+#ifndef mozilla_UniquePtr_h
+#define mozilla_UniquePtr_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Compiler.h"
+#include "mozilla/Move.h"
+#include "mozilla/Pair.h"
+#include "mozilla/TypeTraits.h"
+
+namespace mozilla {
+
+template<typename T> class DefaultDelete;
+template<typename T, class D = DefaultDelete<T>> class UniquePtr;
+
+} // namespace mozilla
+
+namespace mozilla {
+
+/**
+ * UniquePtr is a smart pointer that wholly owns a resource. Ownership may be
+ * transferred out of a UniquePtr through explicit action, but otherwise the
+ * resource is destroyed when the UniquePtr is destroyed.
+ *
+ * UniquePtr is similar to C++98's std::auto_ptr, but it improves upon auto_ptr
+ * in one crucial way: it's impossible to copy a UniquePtr. Copying an auto_ptr
+ * obviously *can't* copy ownership of its singly-owned resource. So what
+ * happens if you try to copy one? Bizarrely, ownership is implicitly
+ * *transferred*, preserving single ownership but breaking code that assumes a
+ * copy of an object is identical to the original. (This is why auto_ptr is
+ * prohibited in STL containers.)
+ *
+ * UniquePtr solves this problem by being *movable* rather than copyable.
+ * Instead of passing a |UniquePtr u| directly to the constructor or assignment
+ * operator, you pass |Move(u)|. In doing so you indicate that you're *moving*
+ * ownership out of |u|, into the target of the construction/assignment. After
+ * the transfer completes, |u| contains |nullptr| and may be safely destroyed.
+ * This preserves single ownership but also allows UniquePtr to be moved by
+ * algorithms that have been made move-safe. (Note: if |u| is instead a
+ * temporary expression, don't use |Move()|: just pass the expression, because
+ * it's already move-ready. For more information see Move.h.)
+ *
+ * UniquePtr is also better than std::auto_ptr in that the deletion operation is
+ * customizable. An optional second template parameter specifies a class that
+ * (through its operator()(T*)) implements the desired deletion policy. If no
+ * policy is specified, mozilla::DefaultDelete<T> is used -- which will either
+ * |delete| or |delete[]| the resource, depending whether the resource is an
+ * array. Custom deletion policies ideally should be empty classes (no member
+ * fields, no member fields in base classes, no virtual methods/inheritance),
+ * because then UniquePtr can be just as efficient as a raw pointer.
+ *
+ * Use of UniquePtr proceeds like so:
+ *
+ * UniquePtr<int> g1; // initializes to nullptr
+ * g1.reset(new int); // switch resources using reset()
+ * g1 = nullptr; // clears g1, deletes the int
+ *
+ * UniquePtr<int> g2(new int); // owns that int
+ * int* p = g2.release(); // g2 leaks its int -- still requires deletion
+ * delete p; // now freed
+ *
+ * struct S { int x; S(int x) : x(x) {} };
+ * UniquePtr<S> g3, g4(new S(5));
+ * g3 = Move(g4); // g3 owns the S, g4 cleared
+ * S* p = g3.get(); // g3 still owns |p|
+ * assert(g3->x == 5); // operator-> works (if .get() != nullptr)
+ * assert((*g3).x == 5); // also operator* (again, if not cleared)
+ * Swap(g3, g4); // g4 now owns the S, g3 cleared
+ * g3.swap(g4); // g3 now owns the S, g4 cleared
+ * UniquePtr<S> g5(Move(g3)); // g5 owns the S, g3 cleared
+ * g5.reset(); // deletes the S, g5 cleared
+ *
+ * struct FreePolicy { void operator()(void* p) { free(p); } };
+ * UniquePtr<int, FreePolicy> g6(static_cast<int*>(malloc(sizeof(int))));
+ * int* ptr = g6.get();
+ * g6 = nullptr; // calls free(ptr)
+ *
+ * Now, carefully note a few things you *can't* do:
+ *
+ * UniquePtr<int> b1;
+ * b1 = new int; // BAD: can only assign another UniquePtr
+ * int* ptr = b1; // BAD: no auto-conversion to pointer, use get()
+ *
+ * UniquePtr<int> b2(b1); // BAD: can't copy a UniquePtr
+ * UniquePtr<int> b3 = b1; // BAD: can't copy-assign a UniquePtr
+ *
+ * (Note that changing a UniquePtr to store a direct |new| expression is
+ * permitted, but usually you should use MakeUnique, defined at the end of this
+ * header.)
+ *
+ * A few miscellaneous notes:
+ *
+ * UniquePtr, when not instantiated for an array type, can be move-constructed
+ * and move-assigned, not only from itself but from "derived" UniquePtr<U, E>
+ * instantiations where U converts to T and E converts to D. If you want to use
+ * this, you're going to have to specify a deletion policy for both UniquePtr
+ * instantations, and T pretty much has to have a virtual destructor. In other
+ * words, this doesn't work:
+ *
+ * struct Base { virtual ~Base() {} };
+ * struct Derived : Base {};
+ *
+ * UniquePtr<Base> b1;
+ * // BAD: DefaultDelete<Base> and DefaultDelete<Derived> don't interconvert
+ * UniquePtr<Derived> d1(Move(b));
+ *
+ * UniquePtr<Base> b2;
+ * UniquePtr<Derived, DefaultDelete<Base>> d2(Move(b2)); // okay
+ *
+ * UniquePtr is specialized for array types. Specializing with an array type
+ * creates a smart-pointer version of that array -- not a pointer to such an
+ * array.
+ *
+ * UniquePtr<int[]> arr(new int[5]);
+ * arr[0] = 4;
+ *
+ * What else is different? Deletion of course uses |delete[]|. An operator[]
+ * is provided. Functionality that doesn't make sense for arrays is removed.
+ * The constructors and mutating methods only accept array pointers (not T*, U*
+ * that converts to T*, or UniquePtr<U[]> or UniquePtr<U>) or |nullptr|.
+ *
+ * It's perfectly okay to return a UniquePtr from a method to assure the related
+ * resource is properly deleted. You'll need to use |Move()| when returning a
+ * local UniquePtr. Otherwise you can return |nullptr|, or you can return
+ * |UniquePtr(ptr)|.
+ *
+ * UniquePtr will commonly be a member of a class, with lifetime equivalent to
+ * that of that class. If you want to expose the related resource, you could
+ * expose a raw pointer via |get()|, but ownership of a raw pointer is
+ * inherently unclear. So it's better to expose a |const UniquePtr&| instead.
+ * This prohibits mutation but still allows use of |get()| when needed (but
+ * operator-> is preferred). Of course, you can only use this smart pointer as
+ * long as the enclosing class instance remains live -- no different than if you
+ * exposed the |get()| raw pointer.
+ *
+ * To pass a UniquePtr-managed resource as a pointer, use a |const UniquePtr&|
+ * argument. To specify an inout parameter (where the method may or may not
+ * take ownership of the resource, or reset it), or to specify an out parameter
+ * (where simply returning a |UniquePtr| isn't possible), use a |UniquePtr&|
+ * argument. To unconditionally transfer ownership of a UniquePtr
+ * into a method, use a |UniquePtr| argument. To conditionally transfer
+ * ownership of a resource into a method, should the method want it, use a
+ * |UniquePtr&&| argument.
+ */
+template<typename T, class D>
+class UniquePtr
+{
+public:
+ typedef T* Pointer;
+ typedef T ElementType;
+ typedef D DeleterType;
+
+private:
+ Pair<Pointer, DeleterType> mTuple;
+
+ Pointer& ptr() { return mTuple.first(); }
+ const Pointer& ptr() const { return mTuple.first(); }
+
+ DeleterType& del() { return mTuple.second(); }
+ const DeleterType& del() const { return mTuple.second(); }
+
+public:
+ /**
+ * Construct a UniquePtr containing |nullptr|.
+ */
+ MOZ_CONSTEXPR UniquePtr()
+ : mTuple(static_cast<Pointer>(nullptr), DeleterType())
+ {
+ static_assert(!IsPointer<D>::value, "must provide a deleter instance");
+ static_assert(!IsReference<D>::value, "must provide a deleter instance");
+ }
+
+ /**
+ * Construct a UniquePtr containing |aPtr|.
+ */
+ explicit UniquePtr(Pointer aPtr)
+ : mTuple(aPtr, DeleterType())
+ {
+ static_assert(!IsPointer<D>::value, "must provide a deleter instance");
+ static_assert(!IsReference<D>::value, "must provide a deleter instance");
+ }
+
+ UniquePtr(Pointer aPtr,
+ typename Conditional<IsReference<D>::value,
+ D,
+ const D&>::Type aD1)
+ : mTuple(aPtr, aD1)
+ {}
+
+ // If you encounter an error with MSVC10 about RemoveReference below, along
+ // the lines that "more than one partial specialization matches the template
+ // argument list": don't use UniquePtr<T, reference to function>! Ideally
+ // you should make deletion use the same function every time, using a
+ // deleter policy:
+ //
+ // // BAD, won't compile with MSVC10, deleter doesn't need to be a
+ // // variable at all
+ // typedef void (&FreeSignature)(void*);
+ // UniquePtr<int, FreeSignature> ptr((int*) malloc(sizeof(int)), free);
+ //
+ // // GOOD, compiles with MSVC10, deletion behavior statically known and
+ // // optimizable
+ // struct DeleteByFreeing
+ // {
+ // void operator()(void* aPtr) { free(aPtr); }
+ // };
+ //
+ // If deletion really, truly, must be a variable: you might be able to work
+ // around this with a deleter class that contains the function reference.
+ // But this workaround is untried and untested, because variable deletion
+ // behavior really isn't something you should use.
+ UniquePtr(Pointer aPtr,
+ typename RemoveReference<D>::Type&& aD2)
+ : mTuple(aPtr, Move(aD2))
+ {
+ static_assert(!IsReference<D>::value,
+ "rvalue deleter can't be stored by reference");
+ }
+
+ UniquePtr(UniquePtr&& aOther)
+ : mTuple(aOther.release(), Forward<DeleterType>(aOther.getDeleter()))
+ {}
+
+ MOZ_IMPLICIT
+ UniquePtr(decltype(nullptr))
+ : mTuple(nullptr, DeleterType())
+ {
+ static_assert(!IsPointer<D>::value, "must provide a deleter instance");
+ static_assert(!IsReference<D>::value, "must provide a deleter instance");
+ }
+
+ template<typename U, class E>
+ UniquePtr(UniquePtr<U, E>&& aOther,
+ typename EnableIf<IsConvertible<typename UniquePtr<U, E>::Pointer,
+ Pointer>::value &&
+ !IsArray<U>::value &&
+ (IsReference<D>::value
+ ? IsSame<D, E>::value
+ : IsConvertible<E, D>::value),
+ int>::Type aDummy = 0)
+ : mTuple(aOther.release(), Forward<E>(aOther.getDeleter()))
+ {
+ }
+
+ ~UniquePtr() { reset(nullptr); }
+
+ UniquePtr& operator=(UniquePtr&& aOther)
+ {
+ reset(aOther.release());
+ getDeleter() = Forward<DeleterType>(aOther.getDeleter());
+ return *this;
+ }
+
+ template<typename U, typename E>
+ UniquePtr& operator=(UniquePtr<U, E>&& aOther)
+ {
+ static_assert(IsConvertible<typename UniquePtr<U, E>::Pointer,
+ Pointer>::value,
+ "incompatible UniquePtr pointees");
+ static_assert(!IsArray<U>::value,
+ "can't assign from UniquePtr holding an array");
+
+ reset(aOther.release());
+ getDeleter() = Forward<E>(aOther.getDeleter());
+ return *this;
+ }
+
+ UniquePtr& operator=(decltype(nullptr))
+ {
+ reset(nullptr);
+ return *this;
+ }
+
+ T& operator*() const { return *get(); }
+ Pointer operator->() const
+ {
+ MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr");
+ return get();
+ }
+
+ explicit operator bool() const { return get() != nullptr; }
+
+ Pointer get() const { return ptr(); }
+
+ DeleterType& getDeleter() { return del(); }
+ const DeleterType& getDeleter() const { return del(); }
+
+ Pointer release()
+ {
+ Pointer p = ptr();
+ ptr() = nullptr;
+ return p;
+ }
+
+ void reset(Pointer aPtr = Pointer())
+ {
+ Pointer old = ptr();
+ ptr() = aPtr;
+ if (old != nullptr) {
+ getDeleter()(old);
+ }
+ }
+
+ void swap(UniquePtr& aOther)
+ {
+ mTuple.swap(aOther.mTuple);
+ }
+
+private:
+ UniquePtr(const UniquePtr& aOther) = delete; // construct using Move()!
+ void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
+};
+
+// In case you didn't read the comment by the main definition (you should!): the
+// UniquePtr<T[]> specialization exists to manage array pointers. It deletes
+// such pointers using delete[], it will reject construction and modification
+// attempts using U* or U[]. Otherwise it works like the normal UniquePtr.
+template<typename T, class D>
+class UniquePtr<T[], D>
+{
+public:
+ typedef T* Pointer;
+ typedef T ElementType;
+ typedef D DeleterType;
+
+private:
+ Pair<Pointer, DeleterType> mTuple;
+
+public:
+ /**
+ * Construct a UniquePtr containing nullptr.
+ */
+ MOZ_CONSTEXPR UniquePtr()
+ : mTuple(static_cast<Pointer>(nullptr), DeleterType())
+ {
+ static_assert(!IsPointer<D>::value, "must provide a deleter instance");
+ static_assert(!IsReference<D>::value, "must provide a deleter instance");
+ }
+
+ /**
+ * Construct a UniquePtr containing |aPtr|.
+ */
+ explicit UniquePtr(Pointer aPtr)
+ : mTuple(aPtr, DeleterType())
+ {
+ static_assert(!IsPointer<D>::value, "must provide a deleter instance");
+ static_assert(!IsReference<D>::value, "must provide a deleter instance");
+ }
+
+private:
+ // delete[] knows how to handle *only* an array of a single class type. For
+ // delete[] to work correctly, it must know the size of each element, the
+ // fields and base classes of each element requiring destruction, and so on.
+ // So forbid all overloads which would end up invoking delete[] on a pointer
+ // of the wrong type.
+ template<typename U>
+ UniquePtr(U&& aU,
+ typename EnableIf<IsPointer<U>::value &&
+ IsConvertible<U, Pointer>::value,
+ int>::Type aDummy = 0)
+ = delete;
+
+public:
+ UniquePtr(Pointer aPtr,
+ typename Conditional<IsReference<D>::value,
+ D,
+ const D&>::Type aD1)
+ : mTuple(aPtr, aD1)
+ {}
+
+ // If you encounter an error with MSVC10 about RemoveReference below, along
+ // the lines that "more than one partial specialization matches the template
+ // argument list": don't use UniquePtr<T[], reference to function>! See the
+ // comment by this constructor in the non-T[] specialization above.
+ UniquePtr(Pointer aPtr,
+ typename RemoveReference<D>::Type&& aD2)
+ : mTuple(aPtr, Move(aD2))
+ {
+ static_assert(!IsReference<D>::value,
+ "rvalue deleter can't be stored by reference");
+ }
+
+private:
+ // Forbidden for the same reasons as stated above.
+ template<typename U, typename V>
+ UniquePtr(U&& aU, V&& aV,
+ typename EnableIf<IsPointer<U>::value &&
+ IsConvertible<U, Pointer>::value,
+ int>::Type aDummy = 0)
+ = delete;
+
+public:
+ UniquePtr(UniquePtr&& aOther)
+ : mTuple(aOther.release(), Forward<DeleterType>(aOther.getDeleter()))
+ {}
+
+ MOZ_IMPLICIT
+ UniquePtr(decltype(nullptr))
+ : mTuple(nullptr, DeleterType())
+ {
+ static_assert(!IsPointer<D>::value, "must provide a deleter instance");
+ static_assert(!IsReference<D>::value, "must provide a deleter instance");
+ }
+
+ ~UniquePtr() { reset(nullptr); }
+
+ UniquePtr& operator=(UniquePtr&& aOther)
+ {
+ reset(aOther.release());
+ getDeleter() = Forward<DeleterType>(aOther.getDeleter());
+ return *this;
+ }
+
+ UniquePtr& operator=(decltype(nullptr))
+ {
+ reset();
+ return *this;
+ }
+
+ explicit operator bool() const { return get() != nullptr; }
+
+ T& operator[](decltype(sizeof(int)) aIndex) const { return get()[aIndex]; }
+ Pointer get() const { return mTuple.first(); }
+
+ DeleterType& getDeleter() { return mTuple.second(); }
+ const DeleterType& getDeleter() const { return mTuple.second(); }
+
+ Pointer release()
+ {
+ Pointer p = mTuple.first();
+ mTuple.first() = nullptr;
+ return p;
+ }
+
+ void reset(Pointer aPtr = Pointer())
+ {
+ Pointer old = mTuple.first();
+ mTuple.first() = aPtr;
+ if (old != nullptr) {
+ mTuple.second()(old);
+ }
+ }
+
+ void reset(decltype(nullptr))
+ {
+ Pointer old = mTuple.first();
+ mTuple.first() = nullptr;
+ if (old != nullptr) {
+ mTuple.second()(old);
+ }
+ }
+
+private:
+ template<typename U>
+ void reset(U) = delete;
+
+public:
+ void swap(UniquePtr& aOther) { mTuple.swap(aOther.mTuple); }
+
+private:
+ UniquePtr(const UniquePtr& aOther) = delete; // construct using Move()!
+ void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
+};
+
+/** A default deletion policy using plain old operator delete. */
+template<typename T>
+class DefaultDelete
+{
+public:
+ MOZ_CONSTEXPR DefaultDelete() {}
+
+ template<typename U>
+ DefaultDelete(const DefaultDelete<U>& aOther,
+ typename EnableIf<mozilla::IsConvertible<U*, T*>::value,
+ int>::Type aDummy = 0)
+ {}
+
+ void operator()(T* aPtr) const
+ {
+ static_assert(sizeof(T) > 0, "T must be complete");
+ delete aPtr;
+ }
+};
+
+/** A default deletion policy using operator delete[]. */
+template<typename T>
+class DefaultDelete<T[]>
+{
+public:
+ MOZ_CONSTEXPR DefaultDelete() {}
+
+ void operator()(T* aPtr) const
+ {
+ static_assert(sizeof(T) > 0, "T must be complete");
+ delete[] aPtr;
+ }
+
+private:
+ template<typename U>
+ void operator()(U* aPtr) const = delete;
+};
+
+template<typename T, class D>
+void
+Swap(UniquePtr<T, D>& aX, UniquePtr<T, D>& aY)
+{
+ aX.swap(aY);
+}
+
+template<typename T, class D, typename U, class E>
+bool
+operator==(const UniquePtr<T, D>& aX, const UniquePtr<U, E>& aY)
+{
+ return aX.get() == aY.get();
+}
+
+template<typename T, class D, typename U, class E>
+bool
+operator!=(const UniquePtr<T, D>& aX, const UniquePtr<U, E>& aY)
+{
+ return aX.get() != aY.get();
+}
+
+template<typename T, class D>
+bool
+operator==(const UniquePtr<T, D>& aX, decltype(nullptr))
+{
+ return !aX;
+}
+
+template<typename T, class D>
+bool
+operator==(decltype(nullptr), const UniquePtr<T, D>& aX)
+{
+ return !aX;
+}
+
+template<typename T, class D>
+bool
+operator!=(const UniquePtr<T, D>& aX, decltype(nullptr))
+{
+ return bool(aX);
+}
+
+template<typename T, class D>
+bool
+operator!=(decltype(nullptr), const UniquePtr<T, D>& aX)
+{
+ return bool(aX);
+}
+
+// No operator<, operator>, operator<=, operator>= for now because simplicity.
+
+namespace detail {
+
+template<typename T>
+struct UniqueSelector
+{
+ typedef UniquePtr<T> SingleObject;
+};
+
+template<typename T>
+struct UniqueSelector<T[]>
+{
+ typedef UniquePtr<T[]> UnknownBound;
+};
+
+template<typename T, decltype(sizeof(int)) N>
+struct UniqueSelector<T[N]>
+{
+ typedef UniquePtr<T[N]> KnownBound;
+};
+
+} // namespace detail
+
+/**
+ * MakeUnique is a helper function for allocating new'd objects and arrays,
+ * returning a UniquePtr containing the resulting pointer. The semantics of
+ * MakeUnique<Type>(...) are as follows.
+ *
+ * If Type is an array T[n]:
+ * Disallowed, deleted, no overload for you!
+ * If Type is an array T[]:
+ * MakeUnique<T[]>(size_t) is the only valid overload. The pointer returned
+ * is as if by |new T[n]()|, which value-initializes each element. (If T
+ * isn't a class type, this will zero each element. If T is a class type,
+ * then roughly speaking, each element will be constructed using its default
+ * constructor. See C++11 [dcl.init]p7 for the full gory details.)
+ * If Type is non-array T:
+ * The arguments passed to MakeUnique<T>(...) are forwarded into a
+ * |new T(...)| call, initializing the T as would happen if executing
+ * |T(...)|.
+ *
+ * There are various benefits to using MakeUnique instead of |new| expressions.
+ *
+ * First, MakeUnique eliminates use of |new| from code entirely. If objects are
+ * only created through UniquePtr, then (assuming all explicit release() calls
+ * are safe, including transitively, and no type-safety casting funniness)
+ * correctly maintained ownership of the UniquePtr guarantees no leaks are
+ * possible. (This pays off best if a class is only ever created through a
+ * factory method on the class, using a private constructor.)
+ *
+ * Second, initializing a UniquePtr using a |new| expression requires repeating
+ * the name of the new'd type, whereas MakeUnique in concert with the |auto|
+ * keyword names it only once:
+ *
+ * UniquePtr<char> ptr1(new char()); // repetitive
+ * auto ptr2 = MakeUnique<char>(); // shorter
+ *
+ * Of course this assumes the reader understands the operation MakeUnique
+ * performs. In the long run this is probably a reasonable assumption. In the
+ * short run you'll have to use your judgment about what readers can be expected
+ * to know, or to quickly look up.
+ *
+ * Third, a call to MakeUnique can be assigned directly to a UniquePtr. In
+ * contrast you can't assign a pointer into a UniquePtr without using the
+ * cumbersome reset().
+ *
+ * UniquePtr<char> p;
+ * p = new char; // ERROR
+ * p.reset(new char); // works, but fugly
+ * p = MakeUnique<char>(); // preferred
+ *
+ * (And third, although not relevant to Mozilla: MakeUnique is exception-safe.
+ * An exception thrown after |new T| succeeds will leak that memory, unless the
+ * pointer is assigned to an object that will manage its ownership. UniquePtr
+ * ably serves this function.)
+ */
+
+template<typename T, typename... Args>
+typename detail::UniqueSelector<T>::SingleObject
+MakeUnique(Args&&... aArgs)
+{
+ return UniquePtr<T>(new T(Forward<Args>(aArgs)...));
+}
+
+template<typename T>
+typename detail::UniqueSelector<T>::UnknownBound
+MakeUnique(decltype(sizeof(int)) aN)
+{
+ typedef typename RemoveExtent<T>::Type ArrayType;
+ return UniquePtr<T>(new ArrayType[aN]());
+}
+
+template<typename T, typename... Args>
+typename detail::UniqueSelector<T>::KnownBound
+MakeUnique(Args&&... aArgs) = delete;
+
+} // namespace mozilla
+
+#endif /* mozilla_UniquePtr_h */
diff --git a/onlineupdate/source/update/inc/nsAutoRef.h b/onlineupdate/source/update/inc/nsAutoRef.h
new file mode 100644
index 000000000000..a159f5954e96
--- /dev/null
+++ b/onlineupdate/source/update/inc/nsAutoRef.h
@@ -0,0 +1,670 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef nsAutoRef_h_
+#define nsAutoRef_h_
+
+#include "mozilla/Attributes.h"
+
+template <class T> class nsSimpleRef;
+template <class T> class nsAutoRefBase;
+template <class T> class nsReturnRef;
+template <class T> class nsReturningRef;
+
+/**
+ * template <class T> class nsAutoRef
+ *
+ * A class that holds a handle to a resource that must be released.
+ * No reference is added on construction.
+ *
+ * No copy constructor nor copy assignment operators are available, so the
+ * resource will be held until released on destruction or explicitly
+ * |reset()| or transferred through provided methods.
+ *
+ * The publicly available methods are the public methods on this class and its
+ * public base classes |nsAutoRefBase<T>| and |nsSimpleRef<T>|.
+ *
+ * For ref-counted resources see also |nsCountedRef<T>|.
+ * For function return values see |nsReturnRef<T>|.
+ *
+ * For each class |T|, |nsAutoRefTraits<T>| or |nsSimpleRef<T>| must be
+ * specialized to use |nsAutoRef<T>| and |nsCountedRef<T>|.
+ *
+ * @param T A class identifying the type of reference held by the
+ * |nsAutoRef<T>| and the unique set methods for managing references
+ * to the resource (defined by |nsAutoRefTraits<T>| or
+ * |nsSimpleRef<T>|).
+ *
+ * Often this is the class representing the resource. Sometimes a
+ * new possibly-incomplete class may need to be declared.
+ *
+ *
+ * Example: An Automatically closing file descriptor
+ *
+ * // References that are simple integral types (as file-descriptors are)
+ * // usually need a new class to represent the resource and how to handle its
+ * // references.
+ * class nsRawFD;
+ *
+ * // Specializing nsAutoRefTraits<nsRawFD> describes how to manage file
+ * // descriptors, so that nsAutoRef<nsRawFD> provides automatic closing of
+ * // its file descriptor on destruction.
+ * template <>
+ * class nsAutoRefTraits<nsRawFD> {
+ * public:
+ * // The file descriptor is held in an int.
+ * typedef int RawRef;
+ * // -1 means that there is no file associated with the handle.
+ * static int Void() { return -1; }
+ * // The file associated with a file descriptor is released with close().
+ * static void Release(RawRef aFD) { close(aFD); }
+ * };
+ *
+ * // A function returning a file descriptor that must be closed.
+ * nsReturnRef<nsRawFD> get_file(const char *filename) {
+ * // Constructing from a raw file descriptor assumes ownership.
+ * nsAutoRef<nsRawFD> fd(open(filename, O_RDONLY));
+ * fcntl(fd, F_SETFD, FD_CLOEXEC);
+ * return fd.out();
+ * }
+ *
+ * void f() {
+ * unsigned char buf[1024];
+ *
+ * // Hold a file descriptor for /etc/hosts in fd1.
+ * nsAutoRef<nsRawFD> fd1(get_file("/etc/hosts"));
+ *
+ * nsAutoRef<nsRawFD> fd2;
+ * fd2.steal(fd1); // fd2 takes the file descriptor from fd1
+ * ssize_t count = read(fd1, buf, 1024); // error fd1 has no file
+ * count = read(fd2, buf, 1024); // reads from /etc/hosts
+ *
+ * // If the file descriptor is not stored then it is closed.
+ * get_file("/etc/login.defs"); // login.defs is closed
+ *
+ * // Now use fd1 to hold a file descriptor for /etc/passwd.
+ * fd1 = get_file("/etc/passwd");
+ *
+ * // The nsAutoRef<nsRawFD> can give up the file descriptor if explicitly
+ * // instructed, but the caller must then ensure that the file is closed.
+ * int rawfd = fd1.disown();
+ *
+ * // Assume ownership of another file descriptor.
+ * fd1.own(open("/proc/1/maps");
+ *
+ * // On destruction, fd1 closes /proc/1/maps and fd2 closes /etc/hosts,
+ * // but /etc/passwd is not closed.
+ * }
+ *
+ */
+
+
+template <class T>
+class nsAutoRef : public nsAutoRefBase<T>
+{
+protected:
+ typedef nsAutoRef<T> ThisClass;
+ typedef nsAutoRefBase<T> BaseClass;
+ typedef nsSimpleRef<T> SimpleRef;
+ typedef typename BaseClass::RawRefOnly RawRefOnly;
+ typedef typename BaseClass::LocalSimpleRef LocalSimpleRef;
+
+public:
+ nsAutoRef()
+ {
+ }
+
+ // Explicit construction is required so as not to risk unintentionally
+ // releasing the resource associated with a raw ref.
+ explicit nsAutoRef(RawRefOnly aRefToRelease)
+ : BaseClass(aRefToRelease)
+ {
+ }
+
+ // Construction from a nsReturnRef<T> function return value, which expects
+ // to give up ownership, transfers ownership.
+ // (nsReturnRef<T> is converted to const nsReturningRef<T>.)
+ explicit nsAutoRef(const nsReturningRef<T>& aReturning)
+ : BaseClass(aReturning)
+ {
+ }
+
+ // The only assignment operator provided is for transferring from an
+ // nsReturnRef smart reference, which expects to pass its ownership to
+ // another object.
+ //
+ // With raw references and other smart references, the type of the lhs and
+ // its taking and releasing nature is often not obvious from an assignment
+ // statement. Assignment from a raw ptr especially is not normally
+ // expected to release the reference.
+ //
+ // Use |steal| for taking ownership from other smart refs.
+ //
+ // For raw references, use |own| to indicate intention to have the
+ // resource released.
+ //
+ // Or, to create another owner of the same reference, use an nsCountedRef.
+
+ ThisClass& operator=(const nsReturningRef<T>& aReturning)
+ {
+ BaseClass::steal(aReturning.mReturnRef);
+ return *this;
+ }
+
+ // Conversion to a raw reference allow the nsAutoRef<T> to often be used
+ // like a raw reference.
+ operator typename SimpleRef::RawRef() const
+ {
+ return this->get();
+ }
+
+ // Transfer ownership from another smart reference.
+ void steal(ThisClass& aOtherRef)
+ {
+ BaseClass::steal(aOtherRef);
+ }
+
+ // Assume ownership of a raw ref.
+ //
+ // |own| has similar function to |steal|, and is useful for receiving
+ // ownership from a return value of a function. It is named differently
+ // because |own| requires more care to ensure that the function intends to
+ // give away ownership, and so that |steal| can be safely used, knowing
+ // that it won't steal ownership from any methods returning raw ptrs to
+ // data owned by a foreign object.
+ void own(RawRefOnly aRefToRelease)
+ {
+ BaseClass::own(aRefToRelease);
+ }
+
+ // Exchange ownership with |aOther|
+ void swap(ThisClass& aOther)
+ {
+ LocalSimpleRef temp;
+ temp.SimpleRef::operator=(*this);
+ SimpleRef::operator=(aOther);
+ aOther.SimpleRef::operator=(temp);
+ }
+
+ // Release the reference now.
+ void reset()
+ {
+ this->SafeRelease();
+ LocalSimpleRef empty;
+ SimpleRef::operator=(empty);
+ }
+
+ // Pass out the reference for a function return values.
+ nsReturnRef<T> out()
+ {
+ return nsReturnRef<T>(this->disown());
+ }
+
+ // operator->() and disown() are provided by nsAutoRefBase<T>.
+ // The default nsSimpleRef<T> provides get().
+
+private:
+ // No copy constructor
+ explicit nsAutoRef(ThisClass& aRefToSteal);
+};
+
+/**
+ * template <class T> class nsCountedRef
+ *
+ * A class that creates (adds) a new reference to a resource on construction
+ * or assignment and releases on destruction.
+ *
+ * This class is similar to nsAutoRef<T> and inherits its methods, but also
+ * provides copy construction and assignment operators that enable more than
+ * one concurrent reference to the same resource.
+ *
+ * Specialize |nsAutoRefTraits<T>| or |nsSimpleRef<T>| to use this. This
+ * class assumes that the resource itself counts references and so can only be
+ * used when |T| represents a reference-counting resource.
+ */
+
+template <class T>
+class nsCountedRef : public nsAutoRef<T>
+{
+protected:
+ typedef nsCountedRef<T> ThisClass;
+ typedef nsAutoRef<T> BaseClass;
+ typedef nsSimpleRef<T> SimpleRef;
+ typedef typename BaseClass::RawRef RawRef;
+
+public:
+ nsCountedRef()
+ {
+ }
+
+ // Construction and assignment from a another nsCountedRef
+ // or a raw ref copies and increments the ref count.
+ nsCountedRef(const ThisClass& aRefToCopy)
+ {
+ SimpleRef::operator=(aRefToCopy);
+ SafeAddRef();
+ }
+ ThisClass& operator=(const ThisClass& aRefToCopy)
+ {
+ if (this == &aRefToCopy) {
+ return *this;
+ }
+
+ this->SafeRelease();
+ SimpleRef::operator=(aRefToCopy);
+ SafeAddRef();
+ return *this;
+ }
+
+ // Implicit conversion from another smart ref argument (to a raw ref) is
+ // accepted here because construction and assignment safely creates a new
+ // reference without interfering with the reference to copy.
+ explicit nsCountedRef(RawRef aRefToCopy)
+ : BaseClass(aRefToCopy)
+ {
+ SafeAddRef();
+ }
+ ThisClass& operator=(RawRef aRefToCopy)
+ {
+ this->own(aRefToCopy);
+ SafeAddRef();
+ return *this;
+ }
+
+ // Construction and assignment from an nsReturnRef function return value,
+ // which expects to give up ownership, transfers ownership.
+ explicit nsCountedRef(const nsReturningRef<T>& aReturning)
+ : BaseClass(aReturning)
+ {
+ }
+ ThisClass& operator=(const nsReturningRef<T>& aReturning)
+ {
+ BaseClass::operator=(aReturning);
+ return *this;
+ }
+
+protected:
+ // Increase the reference count if there is a resource.
+ void SafeAddRef()
+ {
+ if (this->HaveResource()) {
+ this->AddRef(this->get());
+ }
+ }
+};
+
+/**
+ * template <class T> class nsReturnRef
+ *
+ * A type for function return values that hold a reference to a resource that
+ * must be released. See also |nsAutoRef<T>::out()|.
+ */
+
+template <class T>
+class nsReturnRef : public nsAutoRefBase<T>
+{
+protected:
+ typedef nsAutoRefBase<T> BaseClass;
+ typedef typename BaseClass::RawRefOnly RawRefOnly;
+
+public:
+ // For constructing a return value with no resource
+ nsReturnRef()
+ {
+ }
+
+ // For returning a smart reference from a raw reference that must be
+ // released. Explicit construction is required so as not to risk
+ // unintentionally releasing the resource associated with a raw ref.
+ MOZ_IMPLICIT nsReturnRef(RawRefOnly aRefToRelease)
+ : BaseClass(aRefToRelease)
+ {
+ }
+
+ // Copy construction transfers ownership
+ nsReturnRef(nsReturnRef<T>& aRefToSteal)
+ : BaseClass(aRefToSteal)
+ {
+ }
+
+ MOZ_IMPLICIT nsReturnRef(const nsReturningRef<T>& aReturning)
+ : BaseClass(aReturning)
+ {
+ }
+
+ // Conversion to a temporary (const) object referring to this object so
+ // that the reference may be passed from a function return value
+ // (temporary) to another smart reference. There is no need to use this
+ // explicitly. Simply assign a nsReturnRef<T> function return value to a
+ // smart reference.
+ operator nsReturningRef<T>()
+ {
+ return nsReturningRef<T>(*this);
+ }
+
+ // No conversion to RawRef operator is provided on nsReturnRef, to ensure
+ // that the return value is not carelessly assigned to a raw ptr (and the
+ // resource then released). If passing to a function that takes a raw
+ // ptr, use get or disown as appropriate.
+};
+
+/**
+ * template <class T> class nsReturningRef
+ *
+ * A class to allow ownership to be transferred from nsReturnRef function
+ * return values.
+ *
+ * It should not be necessary for clients to reference this
+ * class directly. Simply pass an nsReturnRef<T> to a parameter taking an
+ * |nsReturningRef<T>|.
+ *
+ * The conversion operator on nsReturnRef constructs a temporary wrapper of
+ * class nsReturningRef<T> around a non-const reference to the nsReturnRef.
+ * The wrapper can then be passed as an rvalue parameter.
+ */
+
+template <class T>
+class nsReturningRef
+{
+private:
+ friend class nsReturnRef<T>;
+
+ explicit nsReturningRef(nsReturnRef<T>& aReturnRef)
+ : mReturnRef(aReturnRef)
+ {
+ }
+public:
+ nsReturnRef<T>& mReturnRef;
+};
+
+/**
+ * template <class T> class nsAutoRefTraits
+ *
+ * A class describing traits of references managed by the default
+ * |nsSimpleRef<T>| implementation and thus |nsAutoRef<T>| and |nsCountedRef|.
+ * The default |nsSimpleRef<T> is suitable for resources with handles that
+ * have a void value. (If there is no such void value for a handle,
+ * specialize |nsSimpleRef<T>|.)
+ *
+ * Specializations must be provided for each class |T| according to the
+ * following pattern:
+ *
+ * // The template parameter |T| should be a class such that the set of fields
+ * // in class nsAutoRefTraits<T> is unique for class |T|. Usually the
+ * // resource object class is sufficient. For handles that are simple
+ * // integral typedefs, a new unique possibly-incomplete class may need to be
+ * // declared.
+ *
+ * template <>
+ * class nsAutoRefTraits<T>
+ * {
+ * // Specializations must provide a typedef for RawRef, describing the
+ * // type of the handle to the resource.
+ * typedef <handle-type> RawRef;
+ *
+ * // Specializations should define Void(), a function returning a value
+ * // suitable for a handle that does not have an associated resource.
+ * //
+ * // The return type must be a suitable as the parameter to a RawRef
+ * // constructor and operator==.
+ * //
+ * // If this method is not accessible then some limited nsAutoRef
+ * // functionality will still be available, but the default constructor,
+ * // |reset|, and most transfer of ownership methods will not be available.
+ * static <return-type> Void();
+ *
+ * // Specializations must define Release() to properly finalize the
+ * // handle to a non-void custom-deleted or reference-counted resource.
+ * static void Release(RawRef aRawRef);
+ *
+ * // For reference-counted resources, if |nsCountedRef<T>| is to be used,
+ * // specializations must define AddRef to increment the reference count
+ * // held by a non-void handle.
+ * // (AddRef() is not necessary for |nsAutoRef<T>|.)
+ * static void AddRef(RawRef aRawRef);
+ * };
+ *
+ * See nsPointerRefTraits for example specializations for simple pointer
+ * references. See nsAutoRef for an example specialization for a non-pointer
+ * reference.
+ */
+
+template <class T> class nsAutoRefTraits;
+
+/**
+ * template <class T> class nsPointerRefTraits
+ *
+ * A convenience class useful as a base class for specializations of
+ * |nsAutoRefTraits<T>| where the handle to the resource is a pointer to |T|.
+ * By inheriting from this class, definitions of only Release(RawRef) and
+ * possibly AddRef(RawRef) need to be added.
+ *
+ * Examples of use:
+ *
+ * template <>
+ * class nsAutoRefTraits<PRFileDesc> : public nsPointerRefTraits<PRFileDesc>
+ * {
+ * public:
+ * static void Release(PRFileDesc *ptr) { PR_Close(ptr); }
+ * };
+ *
+ * template <>
+ * class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
+ * {
+ * public:
+ * static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); }
+ * static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
+ * };
+ */
+
+template <class T>
+class nsPointerRefTraits
+{
+public:
+ // The handle is a pointer to T.
+ typedef T* RawRef;
+ // A nullptr does not have a resource.
+ static RawRef Void()
+ {
+ return nullptr;
+ }
+};
+
+/**
+ * template <class T> class nsSimpleRef
+ *
+ * Constructs a non-smart reference, and provides methods to test whether
+ * there is an associated resource and (if so) get its raw handle.
+ *
+ * A default implementation is suitable for resources with handles that have a
+ * void value. This is not intended for direct use but used by |nsAutoRef<T>|
+ * and thus |nsCountedRef<T>|.
+ *
+ * Specialize this class if there is no particular void value for the resource
+ * handle. A specialized implementation must also provide Release(RawRef),
+ * and, if |nsCountedRef<T>| is required, AddRef(RawRef), as described in
+ * nsAutoRefTraits<T>.
+ */
+
+template <class T>
+class nsSimpleRef : protected nsAutoRefTraits<T>
+{
+protected:
+ // The default implementation uses nsAutoRefTrait<T>.
+ // Specializations need not define this typedef.
+ typedef nsAutoRefTraits<T> Traits;
+ // The type of the handle to the resource.
+ // A specialization must provide a typedef for RawRef.
+ typedef typename Traits::RawRef RawRef;
+
+ // Construct with no resource.
+ //
+ // If this constructor is not accessible then some limited nsAutoRef
+ // functionality will still be available, but the default constructor,
+ // |reset|, and most transfer of ownership methods will not be available.
+ nsSimpleRef()
+ : mRawRef(Traits::Void())
+ {
+ }
+ // Construct with a handle to a resource.
+ // A specialization must provide this.
+ explicit nsSimpleRef(RawRef aRawRef)
+ : mRawRef(aRawRef)
+ {
+ }
+
+ // Test whether there is an associated resource. A specialization must
+ // provide this. The function is permitted to always return true if the
+ // default constructor is not accessible, or if Release (and AddRef) can
+ // deal with void handles.
+ bool HaveResource() const
+ {
+ return mRawRef != Traits::Void();
+ }
+
+public:
+ // A specialization must provide get() or loose some functionality. This
+ // is inherited by derived classes and the specialization may choose
+ // whether it is public or protected.
+ RawRef get() const
+ {
+ return mRawRef;
+ }
+
+private:
+ RawRef mRawRef;
+};
+
+
+/**
+ * template <class T> class nsAutoRefBase
+ *
+ * Internal base class for |nsAutoRef<T>| and |nsReturnRef<T>|.
+ * Adds release on destruction to a |nsSimpleRef<T>|.
+ */
+
+template <class T>
+class nsAutoRefBase : public nsSimpleRef<T>
+{
+protected:
+ typedef nsAutoRefBase<T> ThisClass;
+ typedef nsSimpleRef<T> SimpleRef;
+ typedef typename SimpleRef::RawRef RawRef;
+
+ nsAutoRefBase()
+ {
+ }
+
+ // A type for parameters that should be passed a raw ref but should not
+ // accept implicit conversions (from another smart ref). (The only
+ // conversion to this type is from a raw ref so only raw refs will be
+ // accepted.)
+ class RawRefOnly
+ {
+ public:
+ MOZ_IMPLICIT RawRefOnly(RawRef aRawRef)
+ : mRawRef(aRawRef)
+ {
+ }
+ operator RawRef() const
+ {
+ return mRawRef;
+ }
+ private:
+ RawRef mRawRef;
+ };
+
+ // Construction from a raw ref assumes ownership
+ explicit nsAutoRefBase(RawRefOnly aRefToRelease)
+ : SimpleRef(aRefToRelease)
+ {
+ }
+
+ // Constructors that steal ownership
+ explicit nsAutoRefBase(ThisClass& aRefToSteal)
+ : SimpleRef(aRefToSteal.disown())
+ {
+ }
+ explicit nsAutoRefBase(const nsReturningRef<T>& aReturning)
+ : SimpleRef(aReturning.mReturnRef.disown())
+ {
+ }
+
+ ~nsAutoRefBase()
+ {
+ SafeRelease();
+ }
+
+ // An internal class providing access to protected nsSimpleRef<T>
+ // constructors for construction of temporary simple references (that are
+ // not ThisClass).
+ class LocalSimpleRef : public SimpleRef
+ {
+ public:
+ LocalSimpleRef()
+ {
+ }
+ explicit LocalSimpleRef(RawRef aRawRef)
+ : SimpleRef(aRawRef)
+ {
+ }
+ };
+
+private:
+ ThisClass& operator=(const ThisClass& aSmartRef) = delete;
+
+public:
+ RawRef operator->() const
+ {
+ return this->get();
+ }
+
+ // Transfer ownership to a raw reference.
+ //
+ // THE CALLER MUST ENSURE THAT THE REFERENCE IS EXPLICITLY RELEASED.
+ //
+ // Is this really what you want to use? Using this removes any guarantee
+ // of release. Use nsAutoRef<T>::out() for return values, or an
+ // nsAutoRef<T> modifiable lvalue for an out parameter. Use disown() when
+ // the reference must be stored in a POD type object, such as may be
+ // preferred for a namespace-scope object with static storage duration,
+ // for example.
+ RawRef disown()
+ {
+ RawRef temp = this->get();
+ LocalSimpleRef empty;
+ SimpleRef::operator=(empty);
+ return temp;
+ }
+
+protected:
+ // steal and own are protected because they make no sense on nsReturnRef,
+ // but steal is implemented on this class for access to aOtherRef.disown()
+ // when aOtherRef is an nsReturnRef;
+
+ // Transfer ownership from another smart reference.
+ void steal(ThisClass& aOtherRef)
+ {
+ own(aOtherRef.disown());
+ }
+ // Assume ownership of a raw ref.
+ void own(RawRefOnly aRefToRelease)
+ {
+ SafeRelease();
+ LocalSimpleRef ref(aRefToRelease);
+ SimpleRef::operator=(ref);
+ }
+
+ // Release a resource if there is one.
+ void SafeRelease()
+ {
+ if (this->HaveResource()) {
+ this->Release(this->get());
+ }
+ }
+};
+
+#endif // !defined(nsAutoRef_h_)
diff --git a/onlineupdate/source/update/inc/nsWindowsHelpers.h b/onlineupdate/source/update/inc/nsWindowsHelpers.h
new file mode 100644
index 000000000000..c9284292691a
--- /dev/null
+++ b/onlineupdate/source/update/inc/nsWindowsHelpers.h
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef nsWindowsHelpers_h
+#define nsWindowsHelpers_h
+
+#include <windows.h>
+#include "nsAutoRef.h"
+
+// ----------------------------------------------------------------------------
+// Critical Section helper class
+// ----------------------------------------------------------------------------
+
+class AutoCriticalSection
+{
+public:
+ AutoCriticalSection(LPCRITICAL_SECTION aSection)
+ : mSection(aSection)
+ {
+ ::EnterCriticalSection(mSection);
+ }
+ ~AutoCriticalSection()
+ {
+ ::LeaveCriticalSection(mSection);
+ }
+private:
+ LPCRITICAL_SECTION mSection;
+};
+
+template<>
+class nsAutoRefTraits<HKEY>
+{
+public:
+ typedef HKEY RawRef;
+ static HKEY Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ RegCloseKey(aFD);
+ }
+ }
+};
+
+template<>
+class nsAutoRefTraits<SC_HANDLE>
+{
+public:
+ typedef SC_HANDLE RawRef;
+ static SC_HANDLE Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ CloseServiceHandle(aFD);
+ }
+ }
+};
+
+template<>
+class nsSimpleRef<HANDLE>
+{
+protected:
+ typedef HANDLE RawRef;
+
+ nsSimpleRef() : mRawRef(nullptr)
+ {
+ }
+
+ nsSimpleRef(RawRef aRawRef) : mRawRef(aRawRef)
+ {
+ }
+
+ bool HaveResource() const
+ {
+ return mRawRef && mRawRef != INVALID_HANDLE_VALUE;
+ }
+
+public:
+ RawRef get() const
+ {
+ return mRawRef;
+ }
+
+ static void Release(RawRef aRawRef)
+ {
+ if (aRawRef && aRawRef != INVALID_HANDLE_VALUE) {
+ CloseHandle(aRawRef);
+ }
+ }
+ RawRef mRawRef;
+};
+
+
+template<>
+class nsAutoRefTraits<HMODULE>
+{
+public:
+ typedef HMODULE RawRef;
+ static RawRef Void()
+ {
+ return nullptr;
+ }
+
+ static void Release(RawRef aFD)
+ {
+ if (aFD != Void()) {
+ FreeLibrary(aFD);
+ }
+ }
+};
+
+typedef nsAutoRef<HKEY> nsAutoRegKey;
+typedef nsAutoRef<SC_HANDLE> nsAutoServiceHandle;
+typedef nsAutoRef<HANDLE> nsAutoHandle;
+typedef nsAutoRef<HMODULE> nsModuleHandle;
+
+namespace {
+
+HMODULE inline
+LoadLibrarySystem32(LPCWSTR aModule)
+{
+ WCHAR systemPath[MAX_PATH + 1] = { L'\0' };
+
+ // If GetSystemPath fails we accept that we'll load the DLLs from the
+ // normal search path.
+ GetSystemDirectoryW(systemPath, MAX_PATH + 1);
+ size_t systemDirLen = wcslen(systemPath);
+
+ // Make the system directory path terminate with a slash
+ if (systemDirLen && systemPath[systemDirLen - 1] != L'\\') {
+ systemPath[systemDirLen] = L'\\';
+ ++systemDirLen;
+ // No need to re-nullptr terminate
+ }
+
+ size_t fileLen = wcslen(aModule);
+ wcsncpy(systemPath + systemDirLen, aModule,
+ MAX_PATH - systemDirLen);
+ if (systemDirLen + fileLen <= MAX_PATH) {
+ systemPath[systemDirLen + fileLen] = L'\0';
+ } else {
+ systemPath[MAX_PATH] = L'\0';
+ }
+ return LoadLibraryW(systemPath);
+}
+
+}
+
+#endif
diff --git a/onlineupdate/source/update/src/mar.h b/onlineupdate/source/update/src/mar.h
index 0e9dc1f137bd..31cc3934e395 100644
--- a/onlineupdate/source/update/src/mar.h
+++ b/onlineupdate/source/update/src/mar.h
@@ -69,7 +69,7 @@ typedef int (* MarItemCallback)(MarFile *mar, const MarItem *item, void *data);
*/
MarFile *mar_open(const char *path);
-#ifdef XP_WIN
+#ifdef WNT
MarFile *mar_wopen(const wchar_t *path);
#endif
diff --git a/onlineupdate/source/update/src/mar_create.c b/onlineupdate/source/update/src/mar_create.c
index c2ce10126cbd..a87e937fe4a3 100644
--- a/onlineupdate/source/update/src/mar_create.c
+++ b/onlineupdate/source/update/src/mar_create.c
@@ -13,7 +13,7 @@
#include "mar_cmdline.h"
#include "mar.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <winsock2.h>
#else
#include <netinet/in.h>
diff --git a/onlineupdate/source/update/src/mar_extract.c b/onlineupdate/source/update/src/mar_extract.c
index ec1cd6c53446..f3512e99122c 100644
--- a/onlineupdate/source/update/src/mar_extract.c
+++ b/onlineupdate/source/update/src/mar_extract.c
@@ -12,7 +12,7 @@
#include "mar_private.h"
#include "mar.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <io.h>
#include <direct.h>
#endif
@@ -25,7 +25,7 @@ static int mar_ensure_parent_dir(const char *path)
{
*slash = '\0';
mar_ensure_parent_dir(path);
-#ifdef XP_WIN
+#ifdef WNT
_mkdir(path);
#else
mkdir(path, 0755);
@@ -43,7 +43,7 @@ static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) {
if (mar_ensure_parent_dir(item->name))
return -1;
-#ifdef XP_WIN
+#ifdef WNT
fd = _open(item->name, _O_BINARY|_O_CREAT|_O_TRUNC|_O_WRONLY, item->flags);
#else
fd = creat(item->name, item->flags);
diff --git a/onlineupdate/source/update/src/mar_private.h b/onlineupdate/source/update/src/mar_private.h
index 8a7fb45ccd82..39a77d1ac03e 100644
--- a/onlineupdate/source/update/src/mar_private.h
+++ b/onlineupdate/source/update/src/mar_private.h
@@ -53,7 +53,7 @@ MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < \
/* The mar program is compiled as a host bin so we don't have access to NSPR at
runtime. For that reason we use ntohl, htonl, and define HOST_TO_NETWORK64
instead of the NSPR equivalents. */
-#ifdef XP_WIN
+#ifdef WNT
#include <winsock2.h>
#define ftello _ftelli64
#define fseeko _fseeki64
diff --git a/onlineupdate/source/update/src/mar_read.c b/onlineupdate/source/update/src/mar_read.c
index 7be225385403..c7c4bdf19554 100644
--- a/onlineupdate/source/update/src/mar_read.c
+++ b/onlineupdate/source/update/src/mar_read.c
@@ -11,7 +11,7 @@
#include "mar_private.h"
#include "mar.h"
-#ifdef XP_WIN
+#ifdef WNT
#include <winsock2.h>
#else
#include <netinet/in.h>
@@ -177,7 +177,7 @@ MarFile *mar_open(const char *path) {
return mar_fpopen(fp);
}
-#ifdef XP_WIN
+#ifdef WNT
MarFile *mar_wopen(const wchar_t *path) {
FILE *fp;
diff --git a/onlineupdate/source/update/updater/archivereader.cxx b/onlineupdate/source/update/updater/archivereader.cxx
index 0bdb99220334..4629d330e5cc 100644
--- a/onlineupdate/source/update/updater/archivereader.cxx
+++ b/onlineupdate/source/update/updater/archivereader.cxx
@@ -11,7 +11,6 @@
#include "archivereader.h"
#include "errors.h"
#ifdef WNT
-#include "nsAlgorithm.h" // Needed by nsVersionComparator.cpp
#include "updatehelper.h"
#endif
diff --git a/onlineupdate/source/update/updater/loaddlls.cxx b/onlineupdate/source/update/updater/loaddlls.cxx
index b910723953f8..541cf4a3a683 100644
--- a/onlineupdate/source/update/updater/loaddlls.cxx
+++ b/onlineupdate/source/update/updater/loaddlls.cxx
@@ -5,6 +5,9 @@
#ifdef WNT
+#ifndef UNICODE
+#define UNICODE
+#endif
#include <windows.h>
// Delayed load libraries are loaded when the first symbol is used.
diff --git a/onlineupdate/source/update/updater/nsWindowsRestart.cxx b/onlineupdate/source/update/updater/nsWindowsRestart.cxx
new file mode 100644
index 000000000000..8623d5117baf
--- /dev/null
+++ b/onlineupdate/source/update/updater/nsWindowsRestart.cxx
@@ -0,0 +1,584 @@
+/* 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/. */
+
+// This file is not build directly. Instead, it is included in multiple
+// shared objects.
+
+#ifdef nsWindowsRestart_cxx
+#error "nsWindowsRestart.cxx is not a header file, and must only be included once."
+#else
+#define nsWindowsRestart_cxx
+#endif
+
+#ifdef WNT
+#include <windows.h>
+#endif
+#include <stdint.h>
+#include <cassert>
+#include <iostream>
+
+#include <shellapi.h>
+
+// Needed for CreateEnvironmentBlock
+#include <userenv.h>
+#pragma comment(lib, "userenv.lib")
+
+// Adapted from Mozilla's nsCharTraits.h
+/*
+ * Some macros for converting char16_t (UTF-16) to and from Unicode scalar
+ * values.
+ *
+ * Note that UTF-16 represents all Unicode scalar values up to U+10FFFF by
+ * using "surrogate pairs". These consist of a high surrogate, i.e. a code
+ * point in the range U+D800 - U+DBFF, and a low surrogate, i.e. a code point
+ * in the range U+DC00 - U+DFFF, like this:
+ *
+ * U+D800 U+DC00 = U+10000
+ * U+D800 U+DC01 = U+10001
+ * ...
+ * U+DBFF U+DFFE = U+10FFFE
+ * U+DBFF U+DFFF = U+10FFFF
+ *
+ * These surrogate code points U+D800 - U+DFFF are not themselves valid Unicode
+ * scalar values and are not well-formed UTF-16 except as high-surrogate /
+ * low-surrogate pairs.
+ */
+
+#define PLANE1_BASE uint32_t(0x00010000)
+// High surrogates are in the range 0xD800 -- OxDBFF
+#define NS_IS_HIGH_SURROGATE(u) ((uint32_t(u) & 0xFFFFFC00) == 0xD800)
+// Low surrogates are in the range 0xDC00 -- 0xDFFF
+#define NS_IS_LOW_SURROGATE(u) ((uint32_t(u) & 0xFFFFFC00) == 0xDC00)
+// Faster than testing NS_IS_HIGH_SURROGATE || NS_IS_LOW_SURROGATE
+#define IS_SURROGATE(u) ((uint32_t(u) & 0xFFFFF800) == 0xD800)
+
+// Everything else is not a surrogate: 0x000 -- 0xD7FF, 0xE000 -- 0xFFFF
+
+// N = (H - 0xD800) * 0x400 + 0x10000 + (L - 0xDC00)
+// I wonder whether we could somehow assert that H is a high surrogate
+// and L is a low surrogate
+#define SURROGATE_TO_UCS4(h, l) (((uint32_t(h) & 0x03FF) << 10) + \
+ (uint32_t(l) & 0x03FF) + PLANE1_BASE)
+
+// Extract surrogates from a UCS4 char
+// Reference: the Unicode standard 4.0, section 3.9
+// Since (c - 0x10000) >> 10 == (c >> 10) - 0x0080 and
+// 0xD7C0 == 0xD800 - 0x0080,
+// ((c - 0x10000) >> 10) + 0xD800 can be simplified to
+#define H_SURROGATE(c) char16_t(char16_t(uint32_t(c) >> 10) + \
+ char16_t(0xD7C0))
+// where it's to be noted that 0xD7C0 is not bitwise-OR'd
+// but added.
+
+// Since 0x10000 & 0x03FF == 0,
+// (c - 0x10000) & 0x03FF == c & 0x03FF so that
+// ((c - 0x10000) & 0x03FF) | 0xDC00 is equivalent to
+#define L_SURROGATE(c) char16_t(char16_t(uint32_t(c) & uint32_t(0x03FF)) | \
+ char16_t(0xDC00))
+
+#define IS_IN_BMP(ucs) (uint32_t(ucs) < PLANE1_BASE)
+#define UCS2_REPLACEMENT_CHAR char16_t(0xFFFD)
+
+#define UCS_END uint32_t(0x00110000)
+#define IS_VALID_CHAR(c) ((uint32_t(c) < UCS_END) && !IS_SURROGATE(c))
+#define ENSURE_VALID_CHAR(c) (IS_VALID_CHAR(c) ? (c) : UCS2_REPLACEMENT_CHAR)
+
+// UTF8traits adapted from Mozilla's nsUTF8Utils.h
+class UTF8traits
+{
+public:
+ static bool isASCII(char aChar)
+ {
+ return (aChar & 0x80) == 0x00;
+ }
+ static bool isInSeq(char aChar)
+ {
+ return (aChar & 0xC0) == 0x80;
+ }
+ static bool is2byte(char aChar)
+ {
+ return (aChar & 0xE0) == 0xC0;
+ }
+ static bool is3byte(char aChar)
+ {
+ return (aChar & 0xF0) == 0xE0;
+ }
+ static bool is4byte(char aChar)
+ {
+ return (aChar & 0xF8) == 0xF0;
+ }
+ static bool is5byte(char aChar)
+ {
+ return (aChar & 0xFC) == 0xF8;
+ }
+ static bool is6byte(char aChar)
+ {
+ return (aChar & 0xFE) == 0xFC;
+ }
+};
+
+// UTF8CharEnumerator adapted from Mozilla's nsUTF8Utils.h
+/**
+ * Extract the next UCS-4 character from the buffer and return it. The
+ * pointer passed in is advanced to the start of the next character in the
+ * buffer. If non-null, the parameters err and overlong are filled in to
+ * indicate that the character was represented by an overlong sequence, or
+ * that an error occurred.
+ */
+
+class UTF8CharEnumerator
+{
+public:
+ static uint32_t NextChar(const char** aBuffer, const char* aEnd, bool* aErr)
+ {
+ // If this assert fails check if the buffer is null
+ assert(aBuffer && *aBuffer);
+
+ const char* p = *aBuffer;
+ *aErr = false;
+
+ if (p >= aEnd) {
+ *aErr = true;
+
+ return 0;
+ }
+
+ char c = *p++;
+
+ if (UTF8traits::isASCII(c)) {
+ *aBuffer = p;
+ return c;
+ }
+
+ uint32_t ucs4;
+ uint32_t minUcs4;
+ int32_t state = 0;
+
+ if (!CalcState(c, ucs4, minUcs4, state)) {
+ std::cerr << "Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings."
+ << '\n';
+ *aErr = true;
+
+ return 0;
+ }
+
+ while (state--) {
+ if (p == aEnd) {
+ *aErr = true;
+
+ return 0;
+ }
+
+ c = *p++;
+
+ if (!AddByte(c, state, ucs4)) {
+ *aErr = true;
+
+ return 0;
+ }
+ }
+
+ if (ucs4 < minUcs4) {
+ // Overlong sequence
+ ucs4 = UCS2_REPLACEMENT_CHAR;
+ } else if (ucs4 >= 0xD800 &&
+ (ucs4 <= 0xDFFF || ucs4 >= UCS_END)) {
+ // Surrogates and code points outside the Unicode range.
+ ucs4 = UCS2_REPLACEMENT_CHAR;
+ }
+
+ *aBuffer = p;
+ return ucs4;
+ }
+
+private:
+ static bool CalcState(char aChar, uint32_t& aUcs4, uint32_t& aMinUcs4,
+ int32_t& aState)
+ {
+ if (UTF8traits::is2byte(aChar)) {
+ aUcs4 = (uint32_t(aChar) << 6) & 0x000007C0L;
+ aState = 1;
+ aMinUcs4 = 0x00000080;
+ } else if (UTF8traits::is3byte(aChar)) {
+ aUcs4 = (uint32_t(aChar) << 12) & 0x0000F000L;
+ aState = 2;
+ aMinUcs4 = 0x00000800;
+ } else if (UTF8traits::is4byte(aChar)) {
+ aUcs4 = (uint32_t(aChar) << 18) & 0x001F0000L;
+ aState = 3;
+ aMinUcs4 = 0x00010000;
+ } else if (UTF8traits::is5byte(aChar)) {
+ aUcs4 = (uint32_t(aChar) << 24) & 0x03000000L;
+ aState = 4;
+ aMinUcs4 = 0x00200000;
+ } else if (UTF8traits::is6byte(aChar)) {
+ aUcs4 = (uint32_t(aChar) << 30) & 0x40000000L;
+ aState = 5;
+ aMinUcs4 = 0x04000000;
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool AddByte(char aChar, int32_t aState, uint32_t& aUcs4)
+ {
+ if (UTF8traits::isInSeq(aChar)) {
+ int32_t shift = aState * 6;
+ aUcs4 |= (uint32_t(aChar) & 0x3F) << shift;
+ return true;
+ }
+
+ return false;
+ }
+};
+
+// ConvertUTF8toUTF16 adapted from Mozilla's nsUTF8Utils.h
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for converting
+ * UTF-8 to UTF-16
+ */
+class ConvertUTF8toUTF16
+{
+public:
+ typedef char value_type;
+ typedef char16_t buffer_type;
+
+ explicit ConvertUTF8toUTF16(buffer_type* aBuffer)
+ : mStart(aBuffer), mBuffer(aBuffer), mErrorEncountered(false)
+ {
+ }
+
+ size_t Length() const
+ {
+ return mBuffer - mStart;
+ }
+
+ bool ErrorEncountered() const
+ {
+ return mErrorEncountered;
+ }
+
+ void write(const value_type* aStart, uint32_t aN)
+ {
+ if (mErrorEncountered) {
+ return;
+ }
+
+ // algorithm assumes utf8 units won't
+ // be spread across fragments
+ const value_type* p = aStart;
+ const value_type* end = aStart + aN;
+ buffer_type* out = mBuffer;
+ for (; p != end /* && *p */;) {
+ bool err;
+ uint32_t ucs4 = UTF8CharEnumerator::NextChar(&p, end, &err);
+
+ if (err) {
+ mErrorEncountered = true;
+ mBuffer = out;
+ return;
+ }
+
+ if (ucs4 >= PLANE1_BASE) {
+ *out++ = (buffer_type)H_SURROGATE(ucs4);
+ *out++ = (buffer_type)L_SURROGATE(ucs4);
+ } else {
+ *out++ = ucs4;
+ }
+ }
+ mBuffer = out;
+ }
+
+ void write_terminator()
+ {
+ *mBuffer = buffer_type(0);
+ }
+
+private:
+ buffer_type* const mStart;
+ buffer_type* mBuffer;
+ bool mErrorEncountered;
+};
+
+/**
+ * Get the length that the string will take and takes into account the
+ * additional length if the string needs to be quoted and if characters need to
+ * be escaped.
+ */
+static int ArgStrLen(const wchar_t *s)
+{
+ int backslashes = 0;
+ int i = wcslen(s);
+ BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
+ // Only add doublequotes if the string contains a space or a tab
+ BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
+
+ if (addDoubleQuotes) {
+ i += 2; // initial and final duoblequote
+ }
+
+ if (hasDoubleQuote) {
+ while (*s) {
+ if (*s == '\\') {
+ ++backslashes;
+ } else {
+ if (*s == '"') {
+ // Escape the doublequote and all backslashes preceding the doublequote
+ i += backslashes + 1;
+ }
+
+ backslashes = 0;
+ }
+
+ ++s;
+ }
+ }
+
+ return i;
+}
+
+/**
+ * Copy string "s" to string "d", quoting the argument as appropriate and
+ * escaping doublequotes along with any backslashes that immediately precede
+ * doublequotes.
+ * The CRT parses this to retrieve the original argc/argv that we meant,
+ * see STDARGV.C in the MSVC CRT sources.
+ *
+ * @return the end of the string
+ */
+static wchar_t* ArgToString(wchar_t *d, const wchar_t *s)
+{
+ int backslashes = 0;
+ BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
+ // Only add doublequotes if the string contains a space or a tab
+ BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
+
+ if (addDoubleQuotes) {
+ *d = '"'; // initial doublequote
+ ++d;
+ }
+
+ if (hasDoubleQuote) {
+ int i;
+ while (*s) {
+ if (*s == '\\') {
+ ++backslashes;
+ } else {
+ if (*s == '"') {
+ // Escape the doublequote and all backslashes preceding the doublequote
+ for (i = 0; i <= backslashes; ++i) {
+ *d = '\\';
+ ++d;
+ }
+ }
+
+ backslashes = 0;
+ }
+
+ *d = *s;
+ ++d; ++s;
+ }
+ } else {
+ wcscpy(d, s);
+ d += wcslen(s);
+ }
+
+ if (addDoubleQuotes) {
+ *d = '"'; // final doublequote
+ ++d;
+ }
+
+ return d;
+}
+
+/**
+ * Creates a command line from a list of arguments. The returned
+ * string is allocated with "malloc" and should be "free"d.
+ *
+ * argv is UTF8
+ */
+wchar_t*
+MakeCommandLine(int argc, wchar_t **argv)
+{
+ int i;
+ int len = 0;
+
+ // The + 1 of the last argument handles the allocation for null termination
+ for (i = 0; i < argc; ++i)
+ len += ArgStrLen(argv[i]) + 1;
+
+ // Protect against callers that pass 0 arguments
+ if (len == 0)
+ len = 1;
+
+ wchar_t *s = (wchar_t*) malloc(len * sizeof(wchar_t));
+ if (!s)
+ return nullptr;
+
+ wchar_t *c = s;
+ for (i = 0; i < argc; ++i) {
+ c = ArgToString(c, argv[i]);
+ if (i + 1 != argc) {
+ *c = ' ';
+ ++c;
+ }
+ }
+
+ *c = '\0';
+
+ return s;
+}
+
+/**
+ * Convert UTF8 to UTF16 without using the normal XPCOM goop, which we
+ * can't link to updater.exe.
+ */
+static char16_t*
+AllocConvertUTF8toUTF16(const char *arg)
+{
+ // UTF16 can't be longer in units than UTF8
+ int len = strlen(arg);
+ char16_t *s = new char16_t[(len + 1) * sizeof(char16_t)];
+ if (!s)
+ return nullptr;
+
+ ConvertUTF8toUTF16 convert(s);
+ convert.write(arg, len);
+ convert.write_terminator();
+ return s;
+}
+
+static void
+FreeAllocStrings(int argc, wchar_t **argv)
+{
+ while (argc) {
+ --argc;
+ delete [] argv[argc];
+ }
+
+ delete [] argv;
+}
+
+
+
+/**
+ * Launch a child process with the specified arguments.
+ * @note argv[0] is ignored
+ * @note The form of this function that takes char **argv expects UTF-8
+ */
+
+BOOL
+WinLaunchChild(const wchar_t *exePath,
+ int argc, wchar_t **argv,
+ HANDLE userToken = nullptr,
+ HANDLE *hProcess = nullptr);
+
+BOOL
+WinLaunchChild(const wchar_t *exePath,
+ int argc, char **argv,
+ HANDLE userToken,
+ HANDLE *hProcess)
+{
+ wchar_t** argvConverted = new wchar_t*[argc];
+ if (!argvConverted)
+ return FALSE;
+
+ for (int i = 0; i < argc; ++i) {
+ argvConverted[i] = reinterpret_cast<wchar_t*>(AllocConvertUTF8toUTF16(argv[i]));
+ if (!argvConverted[i]) {
+ FreeAllocStrings(i, argvConverted);
+ return FALSE;
+ }
+ }
+
+ BOOL ok = WinLaunchChild(exePath, argc, argvConverted, userToken, hProcess);
+ FreeAllocStrings(argc, argvConverted);
+ return ok;
+}
+
+BOOL
+WinLaunchChild(const wchar_t *exePath,
+ int argc,
+ wchar_t **argv,
+ HANDLE userToken,
+ HANDLE *hProcess)
+{
+ wchar_t *cl;
+ BOOL ok;
+
+ cl = MakeCommandLine(argc, argv);
+ if (!cl) {
+ return FALSE;
+ }
+
+ STARTUPINFOW si = {0};
+ si.cb = sizeof(STARTUPINFOW);
+ si.lpDesktop = L"winsta0\\Default";
+ PROCESS_INFORMATION pi = {0};
+
+ if (userToken == nullptr) {
+ ok = CreateProcessW(exePath,
+ cl,
+ nullptr, // no special security attributes
+ nullptr, // no special thread attributes
+ FALSE, // don't inherit filehandles
+ 0, // creation flags
+ nullptr, // inherit my environment
+ nullptr, // use my current directory
+ &si,
+ &pi);
+ } else {
+ // Create an environment block for the process we're about to start using
+ // the user's token.
+ LPVOID environmentBlock = nullptr;
+ if (!CreateEnvironmentBlock(&environmentBlock, userToken, TRUE)) {
+ environmentBlock = nullptr;
+ }
+
+ ok = CreateProcessAsUserW(userToken,
+ exePath,
+ cl,
+ nullptr, // no special security attributes
+ nullptr, // no special thread attributes
+ FALSE, // don't inherit filehandles
+ 0, // creation flags
+ environmentBlock,
+ nullptr, // use my current directory
+ &si,
+ &pi);
+
+ if (environmentBlock) {
+ DestroyEnvironmentBlock(environmentBlock);
+ }
+ }
+
+ if (ok) {
+ if (hProcess) {
+ *hProcess = pi.hProcess; // the caller now owns the HANDLE
+ } else {
+ CloseHandle(pi.hProcess);
+ }
+ CloseHandle(pi.hThread);
+ } else {
+ LPVOID lpMsgBuf = nullptr;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ nullptr);
+ wprintf(L"Error restarting: %s\n", lpMsgBuf ? lpMsgBuf : L"(null)");
+ if (lpMsgBuf)
+ LocalFree(lpMsgBuf);
+ }
+
+ free(cl);
+
+ return ok;
+}
diff --git a/onlineupdate/source/update/updater/progressui_win.cxx b/onlineupdate/source/update/updater/progressui_win.cxx
index d0b268edaa26..3cbbc6b9891d 100644
--- a/onlineupdate/source/update/updater/progressui_win.cxx
+++ b/onlineupdate/source/update/updater/progressui_win.cxx
@@ -6,6 +6,9 @@
#ifdef WNT
#include <stdio.h>
+#ifndef UNICODE
+#define UNICODE
+#endif
#include <windows.h>
#include <commctrl.h>
#include <process.h>
diff --git a/onlineupdate/source/update/updater/updater.cxx b/onlineupdate/source/update/updater/updater.cxx
index 998a3109bf3f..1685995c6fdf 100644
--- a/onlineupdate/source/update/updater/updater.cxx
+++ b/onlineupdate/source/update/updater/updater.cxx
@@ -1802,7 +1802,7 @@ PatchIfFile::Finish(int status)
//-----------------------------------------------------------------------------
#ifdef WNT
-#include "nsWindowsRestart.cpp"
+#include "nsWindowsRestart.cxx"
#include "nsWindowsHelpers.h"
#include "uachelper.h"
#include "pathhash.h"
diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx
index 1193f867efa7..3f859db06aae 100644
--- a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx
+++ b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.cxx
@@ -11,7 +11,18 @@
#include <stdint.h>
#if defined(WNT) && !defined(UPDATER_NO_STRING_GLUE_STL)
#include <wchar.h>
-#include "nsStringGlue.h"
+#include <stdint.h>
+#include "mozilla/Char16.h"
+#endif
+
+#ifdef WNT
+// from Mozilla's nsAlgorithm.h
+template <class T>
+inline const T&
+XPCOM_MIN(const T& aA, const T& aB)
+{
+ return aB < aA ? aB : aA;
+}
#endif
struct VersionPart
@@ -301,14 +312,14 @@ namespace mozilla {
#ifdef WNT
int32_t
-CompareVersions(const char16_t* aStrA, const char16_t* aStrB)
+CompareVersions(const wchar_t* aStrA, const wchar_t* aStrB)
{
- wchar_t* A2 = wcsdup(char16ptr_t(aStrA));
+ wchar_t* A2 = wcsdup(aStrA);
if (!A2) {
return 1;
}
- wchar_t* B2 = wcsdup(char16ptr_t(aStrB));
+ wchar_t* B2 = wcsdup(aStrB);
if (!B2) {
free(A2);
return 1;
diff --git a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h
index 431d181ef722..a54c7fdd10e2 100644
--- a/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h
+++ b/onlineupdate/source/update/updater/xpcom/glue/nsVersionComparator.h
@@ -12,7 +12,9 @@
#include <assert.h>
#if defined(WNT) && !defined(UPDATER_NO_STRING_GLUE_STL)
#include <wchar.h>
-#include "nsStringGlue.h"
+#include <stdint.h>
+#include "mozilla/Char16.h"
+
#endif
/**
@@ -45,7 +47,7 @@ namespace mozilla {
int32_t CompareVersions(const char* aStrA, const char* aStrB);
#ifdef WNT
-int32_t CompareVersions(const char16_t* aStrA, const char16_t* aStrB);
+int32_t CompareVersions(const wchar_t* aStrA, const wchar_t* aStrB);
#endif
struct Version
@@ -121,13 +123,13 @@ private:
#ifdef WNT
struct VersionW
{
- VersionW(const char16_t* aVersionStringW)
+ VersionW(const wchar_t* aVersionStringW)
{
versionContentW =
- reinterpret_cast<char16_t*>(wcsdup(char16ptr_t(aVersionStringW)));
+ reinterpret_cast<wchar_t*>(wcsdup(aVersionStringW));
}
- const char16_t* ReadContentW() const
+ const wchar_t* ReadContentW() const
{
return versionContentW;
}
@@ -163,7 +165,7 @@ struct VersionW
}
private:
- char16_t* versionContentW;
+ wchar_t* versionContentW;
};
#endif