--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -146,16 +146,23 @@ MOZ_WINCONSOLE = 1
else
MOZ_WINCONSOLE = 0
endif
endif
NSDISTMODE = copy
include $(topsrcdir)/config/config.mk
+
+ifdef _MSC_VER
+# Always enter a Windows program through wmain, whether or not we're
+# a console application.
+WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
+endif
+
ifndef BUILD_STATIC_LIBS
ifdef NS_TRACE_MALLOC
# when libxul is enabled, trace-malloc is part of it
ifndef MOZ_ENABLE_LIBXUL
EXTRA_DSO_LIBS += tracemalloc
endif
endif
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -48,16 +48,21 @@
#include "plstr.h"
#include "prprf.h"
#include "prenv.h"
#include "nsCOMPtr.h"
#include "nsILocalFile.h"
#include "nsStringGlue.h"
+#ifdef XP_WIN
+// we want a wmain entry point
+#include "nsWindowsWMain.cpp"
+#endif
+
static void Output(const char *fmt, ... )
{
va_list ap;
va_start(ap, fmt);
#if defined(XP_WIN) && !MOZ_WINCONSOLE
char msg[2048];
@@ -151,18 +156,8 @@ int main(int argc, char* argv[])
}
int result = XRE_main(argc, argv, appData);
XRE_FreeAppData(appData);
if (appEnv)
PR_smprintf_free(appEnv);
return result;
}
-
-#if defined( XP_WIN ) && defined( WIN32 ) && !defined(__GNUC__)
-// We need WinMain in order to not be a console app. This function is
-// unused if we are a console application.
-int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR args, int )
-{
- // Do the real work.
- return main( __argc, __argv );
-}
-#endif
--- a/toolkit/components/commandlines/public/nsICommandLineRunner.idl
+++ b/toolkit/components/commandlines/public/nsICommandLineRunner.idl
@@ -54,16 +54,18 @@
interface nsICommandLineRunner : nsICommandLine
{
/**
* This method assumes a native character set, and is meant to be called
* with the argc/argv passed to main(). Talk to bsmedberg if you need to
* create a command line using other data. argv will not be altered in any
* way.
*
+ * On Windows, the "native" character set is UTF-8, not the native codepage.
+ *
* @param workingDir The working directory for resolving file and URI paths.
* @param state The nsICommandLine.state flag.
*/
void init(in long argc, in nsCharPtrArray argv,
in nsIFile workingDir, in unsigned long state);
/**
* Set the windowContext parameter.
--- a/toolkit/components/commandlines/src/nsCommandLine.cpp
+++ b/toolkit/components/commandlines/src/nsCommandLine.cpp
@@ -379,30 +379,27 @@ nsCommandLine::ResolveFile(const nsAStri
rv = lf->InitWithPath(aArgument);
if (NS_FAILED(rv)) {
// If it's a relative path, the Init is *going* to fail. We use string magic and
// win32 _fullpath. Note that paths of the form "\Relative\To\CurDrive" are
// going to fail, and I haven't figured out a way to work around this without
// the PathCombine() function, which is not available in plain win95/nt4
- nsCAutoString fullPath;
- mWorkingDir->GetNativePath(fullPath);
-
- nsCAutoString carg;
- NS_CopyUnicodeToNative(aArgument, carg);
+ nsAutoString fullPath;
+ mWorkingDir->GetPath(fullPath);
fullPath.Append('\\');
- fullPath.Append(carg);
+ fullPath.Append(aArgument);
- char pathBuf[MAX_PATH];
- if (!_fullpath(pathBuf, fullPath.get(), MAX_PATH))
+ WCHAR pathBuf[MAX_PATH];
+ if (!_wfullpath(pathBuf, fullPath.get(), MAX_PATH))
return NS_ERROR_FAILURE;
- rv = lf->InitWithNativePath(nsDependentCString(pathBuf));
+ rv = lf->InitWithPath(nsDependentString(pathBuf));
if (NS_FAILED(rv)) return rv;
}
NS_ADDREF(*aResult = lf);
return NS_OK;
#elif defined(XP_OS2)
nsCOMPtr<nsILocalFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY);
@@ -466,17 +463,21 @@ nsCommandLine::ResolveURI(const nsAStrin
void
nsCommandLine::appendArg(const char* arg)
{
#ifdef DEBUG_COMMANDLINE
printf("Adding XP arg: %s\n", arg);
#endif
nsAutoString warg;
+#ifdef XP_WIN
+ CopyUTF8toUTF16(nsDependentCString(arg), warg);
+#else
NS_CopyNativeToUnicode(nsDependentCString(arg), warg);
+#endif
mArgs.AppendString(warg);
}
NS_IMETHODIMP
nsCommandLine::Init(PRInt32 argc, char** argv, nsIFile* aWorkingDir,
PRUint32 aState)
{
--- a/toolkit/mozapps/update/src/updater/Makefile.in
+++ b/toolkit/mozapps/update/src/updater/Makefile.in
@@ -47,29 +47,30 @@ include $(DEPTH)/config/autoconf.mk
CPPSRCS = \
updater.cpp \
bspatch.cpp \
archivereader.cpp \
$(NULL)
PROGRAM = updater$(BIN_SUFFIX)
-REQUIRES = libmar libbz2
+REQUIRES = libmar libbz2 string
LIBS += \
$(DEPTH)/modules/libmar/src/$(LIB_PREFIX)mar.$(LIB_SUFFIX) \
$(DEPTH)/modules/libbz2/src/$(LIB_PREFIX)bz2.$(LIB_SUFFIX) \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
USE_STATIC_LIBS = 1
HAVE_PROGRESSUI = 1
RCINCLUDE = updater.rc
CPPSRCS += progressui_win.cpp
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32)
+DEFINES += -DUNICODE -D_UNICODE
ifndef GNU_CC
RCFLAGS += -I$(srcdir)
else
RCFLAGS += --include-dir $(srcdir)
DEFINES += -D_WIN32_IE=0x300
endif
endif
@@ -99,16 +100,22 @@ ifdef MOZ_DEBUG
MOZ_WINCONSOLE = 1
else
MOZ_WINCONSOLE = 0
endif
endif
include $(topsrcdir)/config/rules.mk
+DEFINES += -DNS_NO_XPCOM
+
+ifdef _MSC_VER
+WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
+endif
+
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
libs::
$(NSINSTALL) -D $(DIST)/bin/updater.app
rsync -a -C --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/bin/updater.app
sed -e "s/@APP_NAME@/$(MOZ_APP_DISPLAYNAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | \
iconv -f UTF-8 -t UTF-16 > $(DIST)/bin/updater.app/Contents/Resources/English.lproj/InfoPlist.strings
$(NSINSTALL) -D $(DIST)/bin/updater.app/Contents/MacOS
$(NSINSTALL) $(DIST)/bin/updater $(DIST)/bin/updater.app/Contents/MacOS
--- a/toolkit/mozapps/update/src/updater/archivereader.cpp
+++ b/toolkit/mozapps/update/src/updater/archivereader.cpp
@@ -91,16 +91,26 @@ ArchiveReader::ExtractFile(const char *n
int rv = ExtractItemToStream(item, fp);
fclose(fp);
return rv;
}
int
+ArchiveReader::ExtractFileToStream(const char *name, FILE *fp)
+{
+ const MarItem *item = mar_find_item(mArchive, name);
+ if (!item)
+ return READ_ERROR;
+
+ return ExtractItemToStream(item, fp);
+}
+
+int
ArchiveReader::ExtractItemToStream(const MarItem *item, FILE *fp)
{
/* decompress the data chunk by chunk */
char inbuf[BUFSIZ], outbuf[BUFSIZ];
bz_stream strm;
int offset, inlen, ret = OK;
--- a/toolkit/mozapps/update/src/updater/archivereader.h
+++ b/toolkit/mozapps/update/src/updater/archivereader.h
@@ -48,16 +48,17 @@ class ArchiveReader
public:
ArchiveReader() : mArchive(NULL) {}
~ArchiveReader() { Close(); }
int Open(const char *path);
void Close();
int ExtractFile(const char *item, const char *destination);
+ int ExtractFileToStream(const char *item, FILE *fp);
private:
int ExtractItemToStream(const MarItem *item, FILE *fp);
MarFile *mArchive;
};
#endif // ArchiveReader_h__
--- a/toolkit/mozapps/update/src/updater/progressui.h
+++ b/toolkit/mozapps/update/src/updater/progressui.h
@@ -34,18 +34,26 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef PROGRESSUI_H__
#define PROGRESSUI_H__
+#if defined(XP_WIN)
+ typedef WCHAR NS_tchar;
+ #define NS_main wmain
+#else
+ typedef char NS_tchar;
+ #define NS_main main
+#endif
+
// Called to perform any initialization of the widget toolkit
-int InitProgressUI(int *argc, char ***argv);
+int InitProgressUI(int *argc, NS_tchar ***argv);
// Called on the main thread at startup
int ShowProgressUI();
// May be called from any thread
void QuitProgressUI();
// May be called from any thread: progress is a number between 0 and 100
--- a/toolkit/mozapps/update/src/updater/progressui_win.cpp
+++ b/toolkit/mozapps/update/src/updater/progressui_win.cpp
@@ -38,16 +38,17 @@
* ***** END LICENSE BLOCK ***** */
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
#include <process.h>
#include <io.h>
#include "resource.h"
+#include "progressui.h"
#define TIMER_ID 1
#define TIMER_INTERVAL 100
#define MAX_INFO_LENGTH 512
#define RESIZE_WINDOW(hwnd, extrax, extray) \
{ \
@@ -67,40 +68,40 @@
SWP_NOSIZE | SWP_NOZORDER); \
}
static float sProgress; // between 0 and 100
static BOOL sQuit = FALSE;
static HFONT sSystemFont = 0;
static BOOL
-GetStringsFile(char filename[MAX_PATH])
+GetStringsFile(WCHAR filename[MAX_PATH])
{
- if (!GetModuleFileName(NULL, filename, MAX_PATH))
+ if (!GetModuleFileNameW(NULL, filename, MAX_PATH))
+ return FALSE;
+
+ WCHAR *dot = wcsrchr(filename, '.');
+ if (!dot || wcsicmp(dot + 1, L"exe"))
return FALSE;
- char *dot = strrchr(filename, '.');
- if (!dot || stricmp(dot + 1, "exe"))
- return FALSE;
-
- strcpy(dot + 1, "ini");
+ wcscpy(dot + 1, L"ini");
return TRUE;
}
static void
UpdateDialog(HWND hDlg)
{
int pos = int(sProgress + 0.5f);
SendDlgItemMessage(hDlg, IDC_PROGRESS, PBM_SETPOS, pos, 0L);
}
static void
ResizeDialogToFit(HWND hDlg)
{
- char text[MAX_INFO_LENGTH];
+ WCHAR text[MAX_INFO_LENGTH];
RECT infoSize, textSize;
HFONT hInfoFont, hOldFont;
HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO);
HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
// Get the text that is displayed - this is what we're going to make fit.
if (!GetWindowText(hWndInfo, text, sizeof(text)))
@@ -168,33 +169,33 @@ CenterDialog(HWND hDlg)
HWND_TOP,
rcOwner.left + (rc.right / 2),
rcOwner.top + (rc.bottom / 2),
0, 0, // ignores size arguments
SWP_NOSIZE);
}
static void
-SetItemText(HWND hwnd, const char *key, const char *ini)
+SetItemText(HWND hwnd, const WCHAR *key, const WCHAR *ini)
{
- char text[MAX_INFO_LENGTH];
- if (!GetPrivateProfileString("Strings", key, NULL, text, sizeof(text), ini))
+ WCHAR text[MAX_INFO_LENGTH];
+ if (!GetPrivateProfileStringW(L"Strings", key, NULL, text, sizeof(text), ini))
return;
- SetWindowText(hwnd, text);
+ SetWindowTextW(hwnd, text);
}
static void
InitDialog(HWND hDlg)
{
- char filename[MAX_PATH];
+ WCHAR filename[MAX_PATH];
if (!GetStringsFile(filename))
return;
- SetItemText(hDlg, "Title", filename);
- SetItemText(GetDlgItem(hDlg, IDC_INFO), "Info", filename);
+ SetItemText(hDlg, L"Title", filename);
+ SetItemText(GetDlgItem(hDlg, IDC_INFO), L"Info", filename);
// On Win9x, we need to send WM_SETFONT for l10n builds. Yes, we shouldn't
// use the system font. For example, if the text has Japanese characters on
// Win98-en, then the text may not be displayed correctly. We should perhaps
// support loading a font named in updater.ini; however, even then there are
// cases where it might not work properly.
if (!sSystemFont) {
NONCLIENTMETRICS ncm;
@@ -245,37 +246,37 @@ DialogProc(HWND hDlg, UINT message, WPAR
case WM_COMMAND:
return TRUE;
}
return FALSE;
}
int
-InitProgressUI(int *argc, char ***argv)
+InitProgressUI(int *argc, NS_tchar ***argv)
{
return 0;
}
int
ShowProgressUI()
{
// Only show the Progress UI if the process is taking significant time.
// Here we measure significant time as taking more than one second.
Sleep(500);
if (sQuit || sProgress > 50.0f)
return 0;
// If we do not have updater.ini, then we should not bother showing UI.
- char filename[MAX_PATH];
+ WCHAR filename[MAX_PATH];
if (!GetStringsFile(filename))
return -1;
- if (_access(filename, 04))
+ if (_waccess(filename, 04))
return -1;
INITCOMMONCONTROLSEX icc = {
sizeof(INITCOMMONCONTROLSEX),
ICC_PROGRESS_CLASS
};
InitCommonControlsEx(&icc);
--- a/toolkit/mozapps/update/src/updater/updater.cpp
+++ b/toolkit/mozapps/update/src/updater/updater.cpp
@@ -42,16 +42,51 @@
*
* contents = 1*( line )
* line = method LWS *( param LWS ) CRLF
* method = "add" | "remove" | "patch"
* CRLF = "\r\n"
* LWS = 1*( " " | "\t" )
*/
+#if defined(XP_WIN)
+# include <windows.h>
+# include <direct.h>
+# include <io.h>
+# define F_OK 00
+# define W_OK 02
+# define R_OK 04
+# define access _access
+# define putenv _putenv
+# define snprintf _snprintf
+# define fchmod(a,b)
+# define mkdir(path, perms) _mkdir(path)
+
+# define NS_T(str) L ## str
+# define NS_tsnprintf _snwprintf
+# define NS_tstrrchr wcsrchr
+# define NS_tchdir _wchdir
+# define NS_tremove _wremove
+# define NS_topen _wopen
+# define NS_tfopen _wfopen
+# define NS_tatoi _wtoi64
+#else
+# include <sys/wait.h>
+# include <unistd.h>
+
+# define NS_T(str) str
+# define NS_tsnprintf snprintf
+# define NS_tstrrchr strrchr
+# define NS_tchdir chdir
+# define NS_tremove remove
+# define NS_topen open
+# define NS_tfopen fopen
+# define NS_tatoi atoi
+#endif
+
#include "bspatch.h"
#include "progressui.h"
#include "archivereader.h"
#include "errors.h"
#include "bzlib.h"
#include <stdio.h>
#include <string.h>
@@ -59,34 +94,16 @@
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
-#if defined(XP_WIN)
-# include <windows.h>
-# include <direct.h>
-# include <io.h>
-# define F_OK 00
-# define W_OK 02
-# define R_OK 04
-# define access _access
-# define snprintf _snprintf
-# define putenv _putenv
-# define fchmod(a,b)
-# define mkdir(path, perm) _mkdir(path)
-# define chdir(path) _chdir(path)
-#else
-# include <sys/wait.h>
-# include <unistd.h>
-#endif
-
#if defined(XP_MACOSX)
// This function is defined in launchchild_osx.mm
void LaunchChild(int argc, char **argv);
#endif
#ifndef _O_BINARY
# define _O_BINARY 0
#endif
@@ -256,17 +273,17 @@ private:
};
#else
#error "Unsupported platform"
#endif
//-----------------------------------------------------------------------------
-static char* gSourcePath;
+static NS_tchar* gSourcePath;
static ArchiveReader gArchiveReader;
#ifdef XP_WIN
static bool gSucceeded = FALSE;
#endif
static const char kWhitespace[] = " \t";
static const char kNL[] = "\r\n";
static const char kQuote[] = "\"";
@@ -276,20 +293,20 @@ static const char kQuote[] = "\"";
static FILE *gLogFP = NULL;
static void LogInit()
{
if (gLogFP)
return;
- char logFile[MAXPATHLEN];
- snprintf(logFile, MAXPATHLEN, "%s/update.log", gSourcePath);
+ NS_tchar logFile[MAXPATHLEN];
+ NS_tsnprintf(logFile, MAXPATHLEN, NS_T("%s/update.log"), gSourcePath);
- gLogFP = fopen(logFile, "w");
+ gLogFP = NS_tfopen(logFile, NS_T("w"));
}
static void LogFinish()
{
if (!gLogFP)
return;
fclose(gLogFP);
@@ -354,17 +371,17 @@ mstrtok(const char *delims, char **str)
*str = NULL;
return ret;
}
static void ensure_write_permissions(const char *path)
{
#ifdef XP_WIN
- (void)_chmod(path, _S_IREAD | _S_IWRITE);
+ (void) chmod(path, _S_IREAD | _S_IWRITE);
#else
struct stat fs;
if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) {
(void)chmod(path, fs.st_mode | S_IWUSR);
}
#endif
}
@@ -736,19 +753,21 @@ private:
int PatchFile::sPatchIndex = 0;
PatchFile::~PatchFile()
{
if (pfd >= 0)
close(pfd);
// delete the temporary patch file
- char spath[MAXPATHLEN];
- snprintf(spath, MAXPATHLEN, "%s/%d.patch", gSourcePath, mPatchIndex);
- ensure_remove(spath);
+ NS_tchar spath[MAXPATHLEN];
+ NS_tsnprintf(spath, MAXPATHLEN, NS_T("%s/%d.patch"),
+ gSourcePath, mPatchIndex);
+
+ NS_tremove(spath);
free(buf);
}
int
PatchFile::LoadSourceFile(int ofd)
{
struct stat os;
@@ -813,30 +832,36 @@ PatchFile::Parse(char *line)
int
PatchFile::Prepare()
{
LOG(("PREPARE PATCH %s\n", mFile));
// extract the patch to a temporary file
mPatchIndex = sPatchIndex++;
- char spath[MAXPATHLEN];
- snprintf(spath, MAXPATHLEN, "%s/%d.patch", gSourcePath, mPatchIndex);
+ NS_tchar spath[MAXPATHLEN];
+ NS_tsnprintf(spath, MAXPATHLEN, NS_T("%s/%d.patch"),
+ gSourcePath, mPatchIndex);
+
+ NS_tremove(spath);
- ensure_remove(spath);
+ FILE *fp = NS_tfopen(spath, NS_T("wb"));
+ if (!fp)
+ return WRITE_ERROR;
- int rv = gArchiveReader.ExtractFile(mPatchFile, spath);
+ int rv = gArchiveReader.ExtractFileToStream(mPatchFile, fp);
+ fclose(fp);
if (rv)
return rv;
// XXXdarin from here down should be moved into the Execute command.
// no need to open all of the patch files and read all of
// the source files before applying any patches.
- pfd = open(spath, O_RDONLY | _O_BINARY);
+ pfd = NS_topen(spath, O_RDONLY | _O_BINARY);
if (pfd < 0)
return READ_ERROR;
rv = MBS_ReadHeader(pfd, &header);
if (rv)
return rv;
AutoFD ofd = open(mFile, O_RDONLY | _O_BINARY);
@@ -1006,79 +1031,90 @@ PatchIfFile::Finish(int status)
}
//-----------------------------------------------------------------------------
#ifdef XP_WIN
#include "nsWindowsRestart.cpp"
static void
-LaunchWinPostProcess(const char *appExe)
+copyASCIItoWCHAR(WCHAR *dest, const char *src)
+{
+ while (*src) {
+ *dest = *src;
+ ++src; ++dest;
+ }
+}
+
+static void
+LaunchWinPostProcess(const WCHAR *appExe)
{
// Launch helper.exe to perform post processing (e.g. registry and log file
// modifications) for the update.
- char inifile[MAXPATHLEN];
- strcpy(inifile, appExe);
+ WCHAR inifile[MAXPATHLEN];
+ wcscpy(inifile, appExe);
- char *slash = strrchr(inifile, '\\');
+ WCHAR *slash = wcsrchr(inifile, '\\');
if (!slash)
return;
- strcpy(slash + 1, "updater.ini");
+ wcscpy(slash + 1, L"updater.ini");
- char exefile[MAXPATHLEN];
- char exearg[MAXPATHLEN];
- if (!GetPrivateProfileString("PostUpdateWin", "ExeRelPath", NULL, exefile,
- sizeof(exefile), inifile))
+ WCHAR exefile[MAXPATHLEN];
+ WCHAR exearg[MAXPATHLEN];
+
+ if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeRelPath", NULL, exefile,
+ MAXPATHLEN, inifile))
return;
- if (!GetPrivateProfileString("PostUpdateWin", "ExeArg", NULL, exearg,
- sizeof(exearg), inifile))
+ if (!GetPrivateProfileStringW(L"PostUpdateWin", L"ExeArg", NULL, exearg,
+ MAXPATHLEN, inifile))
return;
- char exefullpath[MAXPATHLEN];
- strcpy(exefullpath, appExe);
+ WCHAR exefullpath[MAXPATHLEN];
+ wcscpy(exefullpath, appExe);
- slash = strrchr(exefullpath, '\\');
- strcpy(slash + 1, exefile);
+ slash = wcsrchr(exefullpath, '\\');
+ wcscpy(slash + 1, exefile);
- char dlogFile[MAXPATHLEN];
- strcpy(dlogFile, exefullpath);
+ WCHAR dlogFile[MAXPATHLEN];
+ wcscpy(dlogFile, exefullpath);
- slash = strrchr(dlogFile, '\\');
- strcpy(slash + 1, "uninstall.update");
+ slash = wcsrchr(dlogFile, '\\');
+ wcscpy(slash + 1, L"uninstall.update");
- char slogFile[MAXPATHLEN];
- snprintf(slogFile, MAXPATHLEN, "%s/update.log", gSourcePath);
+ WCHAR slogFile[MAXPATHLEN];
+ _snwprintf(slogFile, MAXPATHLEN, L"%s/update.log", gSourcePath);
// We want to launch the post update helper app to update the Windows
// registry even if there is a failure with removing the uninstall.update
// file or copying the update.log file.
- ensure_remove(dlogFile);
- copy_file(slogFile, dlogFile);
+ NS_tremove(dlogFile);
+ CopyFile(slogFile, dlogFile, FALSE);
static int argc = 2;
- static char **argv = (char**) malloc(sizeof(char*) * (argc + 1));
- argv[0] = "argv0ignoredbywinlaunchchild";
- argv[1] = exearg;
- argv[2] = "\0";
+ static WCHAR* argv[3] = {
+ L"argv0ignoredbywinlaunchchild",
+ exearg,
+ L"\0"
+ };
WinLaunchChild(exefullpath, argc, argv, 1);
free(argv);
}
#endif
static void
-LaunchCallbackApp(const char *workingDir, int argc, char **argv)
+LaunchCallbackApp(const NS_tchar *workingDir, int argc, NS_tchar **argv)
{
putenv("NO_EM_RESTART=");
putenv("MOZ_LAUNCHED_CHILD=1");
// Run from the specified working directory (see bug 312360).
- chdir(workingDir);
+ NS_tchdir(workingDir);
#if defined(USE_EXECV)
execv(argv[0], argv);
#elif defined(XP_MACOSX)
LaunchChild(argc, argv);
#elif defined(XP_WIN)
WinLaunchChild(argv[0], argc, argv, -1);
#else
@@ -1129,33 +1165,33 @@ UpdateThreadFunc(void *param)
else
LOG(("succeeded\n"));
WriteStatusFile(rv);
LOG(("calling QuitProgressUI\n"));
QuitProgressUI();
}
-int main(int argc, char **argv)
+int NS_main(int argc, NS_tchar **argv)
{
InitProgressUI(&argc, &argv);
// The updater command line consists of the directory path containing the
// updater.mar file to process followed by the PID of the calling process.
// The updater will wait on the parent process to exit if the PID is non-
// zero. This is leveraged on platforms such as Windows where it is
// necessary for the parent process to exit before its executable image may
// be altered.
if (argc < 3) {
fprintf(stderr, "Usage: updater <dir-path> <parent-pid> [working-dir callback args...]\n");
return 1;
}
- int pid = atoi(argv[2]);
+ int pid = NS_tatoi(argv[2]);
if (pid) {
#ifdef XP_WIN
HANDLE parent = OpenProcess(SYNCHRONIZE, FALSE, (DWORD) pid);
// May return NULL if the parent process has already gone away.
// Otherwise, wait for the parent process to exit before starting the
// update.
if (parent) {
DWORD result = WaitForSingleObject(parent, 5000);
@@ -1301,25 +1337,30 @@ ActionList::Finish(int status)
gSucceeded = TRUE;
#endif
UpdateProgressUI(100.0f);
}
int DoUpdate()
{
- char manifest[MAXPATHLEN];
- snprintf(manifest, MAXPATHLEN, "%s/update.manifest", gSourcePath);
+ NS_tchar manifest[MAXPATHLEN];
+ NS_tsnprintf(manifest, MAXPATHLEN, NS_T("%s/update.manifest"), gSourcePath);
// extract the manifest
- int rv = gArchiveReader.ExtractFile("update.manifest", manifest);
+ FILE *fp = NS_tfopen(manifest, NS_T("wb"));
+ if (!fp)
+ return READ_ERROR;
+
+ int rv = gArchiveReader.ExtractFileToStream("update.manifest", fp);
+ fclose(fp);
if (rv)
return rv;
- AutoFD mfd = open(manifest, O_RDONLY | _O_BINARY);
+ AutoFD mfd = NS_topen(manifest, O_RDONLY | _O_BINARY);
if (mfd < 0)
return READ_ERROR;
struct stat ms;
rv = fstat(mfd, &ms);
if (rv)
return READ_ERROR;
@@ -1389,18 +1430,8 @@ int DoUpdate()
if (rv)
return rv;
rv = list.Execute();
list.Finish(rv);
return rv;
}
-
-#if defined(XP_WIN) && !defined(DEBUG) && !defined(__GNUC__)
-// We need WinMain in order to not be a console app. This function is unused
-// if we are a console application.
-int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR args, int )
-{
- // Do the real work.
- return main(__argc, __argv);
-}
-#endif
--- a/toolkit/profile/src/nsToolkitProfileService.cpp
+++ b/toolkit/profile/src/nsToolkitProfileService.cpp
@@ -924,23 +924,23 @@ XRE_GetFileFromPath(const char *aPath, n
// realpath on OS/2 returns a unix-ized path, so re-native-ize
for (char* ptr = strchr(fullPath, '/'); ptr; ptr = strchr(ptr, '/'))
*ptr = '\\';
return NS_NewNativeLocalFile(nsDependentCString(fullPath), PR_TRUE,
aResult);
#elif defined(XP_WIN)
- char fullPath[MAXPATHLEN];
+ WCHAR fullPath[MAXPATHLEN];
- if (!_fullpath(fullPath, aPath, MAXPATHLEN))
+ if (!_wfullpath(fullPath, NS_ConvertUTF8toUTF16(aPath).get(), MAXPATHLEN))
return NS_ERROR_FAILURE;
- return NS_NewNativeLocalFile(nsDependentCString(fullPath), PR_TRUE,
- aResult);
+ return NS_NewLocalFile(nsDependentString(fullPath), PR_TRUE,
+ aResult);
#elif defined(XP_BEOS)
BPath fullPath;
if (fullPath.SetTo(aPath, NULL, true))
return NS_ERROR_FAILURE;
return NS_NewNativeLocalFile(nsDependentCString(fullPath.Leaf()), PR_TRUE,
aResult);
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -286,19 +286,56 @@ SaveWordToEnv(const char *name, const ns
PR_SetEnv(expr);
// We intentionally leak |expr| here since it is required by PR_SetEnv.
}
// Save the path of the given file to the specified environment variable.
static void
SaveFileToEnv(const char *name, nsIFile *file)
{
+#ifdef XP_WIN
+ nsAutoString path;
+ file->GetPath(path);
+ SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
+#else
nsCAutoString path;
file->GetNativePath(path);
SaveWordToEnv(name, path);
+#endif
+}
+
+// Load the path of a file saved with SaveFileToEnv
+static already_AddRefed<nsILocalFile>
+GetFileFromEnv(const char *name)
+{
+ nsresult rv;
+ nsILocalFile *file = nsnull;
+
+#ifdef XP_WIN
+ WCHAR path[_MAX_PATH];
+ if (!GetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),
+ path, _MAX_PATH))
+ return nsnull;
+
+ rv = NS_NewLocalFile(nsDependentString(path), PR_TRUE, &file);
+ if (NS_FAILED(rv))
+ return nsnull;
+
+ return file;
+#else
+ const char *arg = PR_GetEnv(name);
+ if (!arg || !*arg)
+ return nsnull;
+
+ rv = NS_NewNativeLocalFile(nsDependentCString(arg), PR_TRUE, &file);
+ if (NS_FAILED(rv))
+ return nsnull;
+
+ return file;
+#endif
}
// Save the path of the given word to the specified environment variable
// provided the environment variable does not have a value.
static void
SaveWordToEnvIfUnset(const char *name, const nsACString & word)
{
const char *val = PR_GetEnv(name);
@@ -686,18 +723,18 @@ nsXULAppInfo::LaunchAppHelperWithArgs(in
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("uninstall"));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
NS_ENSURE_SUCCESS(rv, rv);
- nsCAutoString appHelperPath;
- rv = appHelper->GetNativePath(appHelperPath);
+ nsAutoString appHelperPath;
+ rv = appHelper->GetPath(appHelperPath);
NS_ENSURE_SUCCESS(rv, rv);
if (!WinLaunchChild(appHelperPath.get(), aArgc, aArgv, 1))
return NS_ERROR_FAILURE;
else
return NS_OK;
}
@@ -1320,23 +1357,23 @@ XRE_GetBinaryPath(const char* argv0, nsI
nsresult rv;
nsCOMPtr<nsILocalFile> lf;
// We need to use platform-specific hackery to find the
// path of this executable. This is copied, with some modifications, from
// nsGREDirServiceProvider.cpp
#ifdef XP_WIN
- char exePath[MAXPATHLEN];
-
- if (!::GetModuleFileName(0, exePath, MAXPATHLEN))
+ PRUnichar exePath[MAXPATHLEN];
+
+ if (!::GetModuleFileNameW(0, exePath, MAXPATHLEN))
return NS_ERROR_FAILURE;
- rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE,
- getter_AddRefs(lf));
+ rv = NS_NewLocalFile(nsDependentString(exePath), PR_TRUE,
+ getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
#elif defined(XP_MACOSX)
if (gBinaryPath)
return NS_NewNativeLocalFile(nsDependentCString(gBinaryPath), PR_FALSE,
aResult);
@@ -1574,25 +1611,32 @@ static nsresult LaunchChild(nsINativeApp
#if defined(XP_MACOSX)
LaunchChildMac(gRestartArgc, gRestartArgv);
#else
nsCOMPtr<nsILocalFile> lf;
nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
if (NS_FAILED(rv))
return rv;
+#if defined(XP_WIN)
+ nsAutoString exePath;
+ rv = lf->GetPath(exePath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, needElevation))
+ return NS_ERROR_FAILURE;
+
+#else
nsCAutoString exePath;
rv = lf->GetNativePath(exePath);
if (NS_FAILED(rv))
return rv;
-#if defined(XP_WIN)
- if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, needElevation))
- return NS_ERROR_FAILURE;
-#elif defined(XP_OS2) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
+#if defined(XP_OS2) && (__GNUC__ == 3 && __GNUC_MINOR__ == 3)
// implementation of _execv() is broken with GCC 3.3.x on OS/2
if (OS2LaunchChild(exePath.get(), gRestartArgc, gRestartArgv) == -1)
return NS_ERROR_FAILURE;
#elif defined(XP_OS2)
if (_execv(exePath.get(), gRestartArgv) == -1)
return NS_ERROR_FAILURE;
#elif defined(XP_UNIX)
if (execv(exePath.get(), gRestartArgv) == -1)
@@ -1607,18 +1651,19 @@ static nsresult LaunchChild(nsINativeApp
PRProcess* process = PR_CreateProcess(exePath.get(), gRestartArgv,
nsnull, nsnull);
if (!process) return NS_ERROR_FAILURE;
PRInt32 exitCode;
PRStatus failed = PR_WaitProcess(process, &exitCode);
if (failed || exitCode)
return NS_ERROR_FAILURE;
-#endif
-#endif
+#endif // XP_OS2 series
+#endif // WP_WIN
+#endif // WP_MACOSX
return NS_ERROR_LAUNCHED_CHILD_PROCESS;
}
static const char kProfileProperties[] =
"chrome://mozapps/locale/profile/profileSelection.properties";
static nsresult
@@ -1850,38 +1895,28 @@ SelectProfile(nsIProfileLock* *aResult,
return NS_ERROR_FAILURE;
}
arg = PR_GetEnv("XRE_START_OFFLINE");
if ((arg && *arg) || ar)
*aStartOffline = PR_TRUE;
- arg = PR_GetEnv("XRE_PROFILE_PATH");
- if (arg && *arg) {
- nsCOMPtr<nsILocalFile> lf;
- rv = NS_NewNativeLocalFile(nsDependentCString(arg), PR_TRUE,
- getter_AddRefs(lf));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsILocalFile> localDir;
- arg = PR_GetEnv("XRE_PROFILE_LOCAL_PATH");
- if (arg && *arg) {
- rv = NS_NewNativeLocalFile(nsDependentCString(arg), PR_TRUE,
- getter_AddRefs(localDir));
- NS_ENSURE_SUCCESS(rv, rv);
- } else {
+ nsCOMPtr<nsILocalFile> lf = GetFileFromEnv("XRE_PROFILE_PATH");
+ if (lf) {
+ nsCOMPtr<nsILocalFile> localDir =
+ GetFileFromEnv("XRE_PROFILE_LOCAL_PATH");
+ if (!localDir) {
localDir = lf;
}
arg = PR_GetEnv("XRE_PROFILE_NAME");
if (arg && *arg && aProfileName)
aProfileName->Assign(nsDependentCString(arg));
-
// Clear out flags that we handled (or should have handled!) last startup.
const char *dummy;
CheckArg("p", PR_FALSE, &dummy);
CheckArg("profile", PR_FALSE, &dummy);
CheckArg("profilemanager");
return NS_LockProfilePath(lf, localDir, nsnull, aResult);
}
--- a/toolkit/xre/nsAppRunner.h
+++ b/toolkit/xre/nsAppRunner.h
@@ -128,17 +128,17 @@ NS_HIDDEN_(nsresult)
NS_LockProfilePath(nsILocalFile* aPath, nsILocalFile* aTempPath,
nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult);
NS_HIDDEN_(void)
WriteConsoleLog();
#ifdef XP_WIN
BOOL
-WinLaunchChild(const char *exePath, int argc, char **argv, int needElevation);
+WinLaunchChild(const PRUnichar *exePath, int argc, char **argv, int needElevation);
#endif
#define NS_NATIVEAPPSUPPORT_CONTRACTID "@mozilla.org/toolkit/native-app-support;1"
// Like nsXREAppData, but releases all strong refs/allocated memory
// in the destructor.
class ScopedAppData : public nsXREAppData
{
--- a/toolkit/xre/nsNativeAppSupportWin.cpp
+++ b/toolkit/xre/nsNativeAppSupportWin.cpp
@@ -558,39 +558,39 @@ struct MessageWindow {
else {
retval = NS_ERROR_FAILURE;
}
}
return retval;
}
- // SendRequest: Pass string via WM_COPYDATA to message window.
- NS_IMETHOD SendRequest( const char *cmd ) {
- // Construct a data buffer <commandline>\0<workingdir>\0
- int cmdlen = strlen(cmd);
- char* cmdbuf = (char*) malloc(cmdlen + MAX_PATH + 1);
- if (!cmdbuf)
- return NS_ERROR_OUT_OF_MEMORY;
+ // SendRequest: Pass the command line via WM_COPYDATA to message window.
+ NS_IMETHOD SendRequest() {
+ WCHAR *cmd = ::GetCommandLineW();
+ WCHAR cwd[MAX_PATH];
+ _wgetcwd(cwd, MAX_PATH);
- strcpy(cmdbuf, cmd);
- _getcwd(cmdbuf + cmdlen + 1, MAX_PATH);
+ // Construct a narrow UTF8 buffer <commandline>\0<workingdir>\0
+ NS_ConvertUTF16toUTF8 utf8buffer(cmd);
+ utf8buffer.Append('\0');
+ AppendUTF16toUTF8(cwd, utf8buffer);
+ utf8buffer.Append('\0');
// We used to set dwData to zero, when we didn't send the working dir.
// Now we're using it as a version number.
COPYDATASTRUCT cds = {
1,
- cmdlen + strlen(cmdbuf + cmdlen + 1) + 2,
- (void*) cmdbuf
+ utf8buffer.Length(),
+ (void*) utf8buffer.get()
};
// Bring the already running Mozilla process to the foreground.
// nsWindow will restore the window (if minimized) and raise it.
::SetForegroundWindow( mHandle );
::SendMessage( mHandle, WM_COPYDATA, 0, (LPARAM)&cds );
- free (cmdbuf);
return NS_OK;
}
// Window proc.
static long CALLBACK WindowProc( HWND msgWindow, UINT msg, WPARAM wp, LPARAM lp ) {
if ( msg == WM_COPYDATA ) {
if (!nsNativeAppSupportWin::mCanHandleRequests)
return FALSE;
@@ -610,19 +610,19 @@ struct MessageWindow {
++wdpath;
++wdpath;
#ifdef MOZ_DEBUG_DDE
printf( "Working dir: %s\n", wdpath);
#endif
- NS_NewNativeLocalFile(nsDependentCString(wdpath),
- PR_FALSE,
- getter_AddRefs(workingDir));
+ NS_NewLocalFile(NS_ConvertUTF8toUTF16(wdpath),
+ PR_FALSE,
+ getter_AddRefs(workingDir));
}
(void)nsNativeAppSupportWin::HandleCommandLine((char*)cds->lpData, workingDir, nsICommandLine::STATE_REMOTE_AUTO);
// Get current window and return its window handle.
nsCOMPtr<nsIDOMWindowInternal> win;
GetMostRecentWindow( 0, getter_AddRefs( win ) );
return win ? (long)hwndForDOMWindow( win ) : 0;
} else if ( msg == WM_QUERYENDSESSION ) {
@@ -696,18 +696,17 @@ nsNativeAppSupportWin::Start( PRBool *aR
Mutex startupLock = Mutex( mMutexName );
NS_ENSURE_TRUE( startupLock.Lock( MOZ_DDE_START_TIMEOUT ), NS_ERROR_FAILURE );
// Search for existing message window.
MessageWindow msgWindow;
if ( (HWND)msgWindow ) {
// We are a client process. Pass request to message window.
- LPTSTR cmd = ::GetCommandLine();
- rv = msgWindow.SendRequest( cmd );
+ rv = msgWindow.SendRequest();
} else {
// We will be server.
rv = msgWindow.Create();
if ( NS_SUCCEEDED( rv ) ) {
// Start up DDE server.
this->StartDDE();
// Tell caller to spin message loop.
*aResult = PR_TRUE;
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -358,16 +358,21 @@ ApplyUpdate(nsIFile *greDir, nsIFile *up
if (NS_FAILED(rv))
return;
nsCAutoString updaterPath;
rv = updater->GetNativePath(updaterPath);
if (NS_FAILED(rv))
return;
+ nsAutoString updaterPathW;
+ rv = updater->GetPath(updaterPathW);
+ if (NS_FAILED(rv))
+ return;
+
// Get the directory to which the update will be applied. On Mac OSX we need
// to apply the update to the Foo.app directory which is the parent of the
// parent of the appDir. On other platforms we will just apply to the appDir.
nsCAutoString applyToDir;
#if defined(XP_MACOSX)
{
nsCOMPtr<nsIFile> parentDir1, parentDir2;
rv = appDir->GetParent(getter_AddRefs(parentDir1));
@@ -430,17 +435,17 @@ ApplyUpdate(nsIFile *greDir, nsIFile *up
LOG(("spawning updater process [%s]\n", updaterPath.get()));
#if defined(USE_EXECV)
chdir(applyToDir.get());
execv(updaterPath.get(), argv);
#elif defined(XP_WIN)
_chdir(applyToDir.get());
- if (!WinLaunchChild(updaterPath.get(), appArgc + 4, argv, 1))
+ if (!WinLaunchChild(updaterPathW.get(), appArgc + 4, argv, 1))
return;
_exit(0);
#else
PRStatus status;
PRProcessAttr *attr;
attr = PR_NewProcessAttr();
if (!attr)
--- a/toolkit/xre/nsWindowsRestart.cpp
+++ b/toolkit/xre/nsWindowsRestart.cpp
@@ -39,16 +39,18 @@
// shared objects.
#ifdef nsWindowsRestart_cpp
#error "nsWindowsRestart.cpp is not a header file, and must only be included once."
#else
#define nsWindowsRestart_cpp
#endif
+#include "nsUTF8Utils.h"
+
#include <shellapi.h>
#ifndef ERROR_ELEVATION_REQUIRED
#define ERROR_ELEVATION_REQUIRED 740L
#endif
BOOL (WINAPI *pCreateProcessWithTokenW)(HANDLE,
DWORD,
@@ -60,37 +62,37 @@ BOOL (WINAPI *pCreateProcessWithTokenW)(
LPSTARTUPINFOW,
LPPROCESS_INFORMATION);
BOOL (WINAPI *pIsUserAnAdmin)(VOID);
/**
* Get the length that the string will take when it is quoted.
*/
-static int QuotedStrLen(const char *s)
+static int QuotedStrLen(const PRUnichar *s)
{
int i = 2; // initial and final quote
while (*s) {
if (*s == '"') {
++i;
}
- ++i; ++s;
+ ++i, ++s;
}
return i;
}
/**
* Copy string "s" to string "d", quoting and escaping all double quotes.
* The CRT parses this to retrieve the original argc/argv that we meant,
* see STDARGV.C in the MSVC6 CRT sources.
*
* @return the end of the string
*/
-static char* QuoteString(char *d, const char *s)
+static PRUnichar* QuoteString(PRUnichar *d, const PRUnichar *s)
{
*d = '"';
++d;
while (*s) {
*d = *s;
if (*s == '"') {
++d;
@@ -104,85 +106,70 @@ static char* QuoteString(char *d, const
++d;
return d;
}
/**
* Create a quoted command from a list of arguments. The returned string
* is allocated with "malloc" and should be "free"d.
+ *
+ * argv is UTF8
*/
-static char*
-MakeCommandLine(int argc, char **argv)
+static PRUnichar*
+MakeCommandLine(int argc, PRUnichar **argv)
{
int i;
int len = 1; // null-termination
for (i = 0; i < argc; ++i)
len += QuotedStrLen(argv[i]) + 1;
- char *s = (char*) malloc(len);
+ PRUnichar *s = (PRUnichar*) malloc(len * sizeof(PRUnichar));
if (!s)
return NULL;
- char *c = s;
+ PRUnichar *c = s;
for (i = 0; i < argc; ++i) {
c = QuoteString(c, argv[i]);
*c = ' ';
++c;
}
*c = '\0';
return s;
}
/**
- * alloc and convert multibyte char to unicode char
- */
-static PRUnichar *
-AllocConvertAToW(const char *buf)
-{
- PRUint32 inputLen = strlen(buf) + 1;
- int n = MultiByteToWideChar(CP_ACP, 0, buf, inputLen, NULL, 0);
- if (n <= 0)
- return NULL;
- PRUnichar *result = (PRUnichar *)malloc(n * sizeof(PRUnichar));
- if (!result)
- return NULL;
- MultiByteToWideChar(CP_ACP, 0, buf, inputLen, result, n);
- return result;
-}
-
-/**
* Launch a child process without elevated privilege.
*/
static BOOL
-LaunchAsNormalUser(const char *exePath, char *cl)
+LaunchAsNormalUser(const PRUnichar *exePath, PRUnichar *cl)
{
if (!pCreateProcessWithTokenW) {
// IsUserAnAdmin is not present on Win9x and not exported by name on Win2k
*(FARPROC *)&pIsUserAnAdmin =
- GetProcAddress(GetModuleHandle("shell32.dll"), "IsUserAnAdmin");
+ GetProcAddress(GetModuleHandleA("shell32.dll"), "IsUserAnAdmin");
// CreateProcessWithTokenW is not present on WinXP or earlier
*(FARPROC *)&pCreateProcessWithTokenW =
- GetProcAddress(GetModuleHandle("advapi32.dll"),
+ GetProcAddress(GetModuleHandleA("advapi32.dll"),
"CreateProcessWithTokenW");
if (!pCreateProcessWithTokenW)
return FALSE;
}
// do nothing here if we are not elevated or IsUserAnAdmin is not present.
if (!pIsUserAnAdmin || pIsUserAnAdmin && !pIsUserAnAdmin())
return FALSE;
// borrow the shell token to drop the privilege
- HWND hwndShell = FindWindow("Progman", NULL);
+ HWND hwndShell = FindWindowA("Progman", NULL);
DWORD dwProcessId;
GetWindowThreadProcessId(hwndShell, &dwProcessId);
HANDLE hProcessShell = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId);
if (!hProcessShell)
return FALSE;
HANDLE hTokenShell;
@@ -200,91 +187,147 @@ LaunchAsNormalUser(const char *exePath,
&hNewToken);
CloseHandle(hTokenShell);
if (!ok)
return FALSE;
STARTUPINFOW si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
- PRUnichar *exePathW = AllocConvertAToW(exePath);
- PRUnichar *clW = AllocConvertAToW(cl);
- ok = exePathW && clW;
- if (ok) {
- ok = pCreateProcessWithTokenW(hNewToken,
- 0, // profile is already loaded
- exePathW,
- clW,
- 0, // No special process creation flags
- NULL, // inherit my environment
- NULL, // use my current directory
- &si,
- &pi);
- }
- free(exePathW);
- free(clW);
+ // When launching with reduced privileges, environment inheritance
+ // (passing NULL as lpEnvironment) doesn't work correctly. Pass our
+ // current environment block explicitly
+ WCHAR* myenv = GetEnvironmentStringsW();
+
+ ok = pCreateProcessWithTokenW(hNewToken,
+ 0, // profile is already loaded
+ exePath,
+ cl,
+ CREATE_UNICODE_ENVIRONMENT,
+ myenv, // inherit my environment
+ NULL, // use my current directory
+ &si,
+ &pi);
+
+ if (myenv)
+ FreeEnvironmentStringsW(myenv);
+
CloseHandle(hNewToken);
if (!ok)
return FALSE;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
/**
+ * Convert UTF8 to UTF16 without using the normal XPCOM goop, which we
+ * can't link to updater.exe.
+ */
+static PRUnichar*
+AllocConvertUTF8toUTF16(const char *arg)
+{
+ // UTF16 can't be longer in units than UTF8
+ int len = strlen(arg);
+ PRUnichar *s = new PRUnichar[(len + 1) * sizeof(PRUnichar)];
+ if (!s)
+ return NULL;
+
+ ConvertUTF8toUTF16 convert(s);
+ len = convert.write(arg, len);
+ s[len] = '\0';
+ return s;
+}
+
+static void
+FreeAllocStrings(int argc, PRUnichar **argv)
+{
+ while (argc) {
+ --argc;
+ delete [] argv[argc];
+ }
+
+ delete [] argv;
+}
+
+/**
* Launch a child process with the specified arguments.
* @param needElevation 1:need elevation, -1:want to drop priv, 0:don't care
* @note argv[0] is ignored
+ * @note The form of this function that takes char **argv expects UTF-8
*/
+
+BOOL
+WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv, int needElevation);
+
BOOL
-WinLaunchChild(const char *exePath, int argc, char **argv, int needElevation)
+WinLaunchChild(const PRUnichar *exePath, int argc, char **argv, int needElevation)
{
- char *cl;
+ PRUnichar** argvConverted = new PRUnichar*[argc];
+ if (!argvConverted)
+ return FALSE;
+
+ for (int i = 0; i < argc; ++i) {
+ argvConverted[i] = AllocConvertUTF8toUTF16(argv[i]);
+ if (!argvConverted[i]) {
+ return FALSE;
+ }
+ }
+
+ BOOL ok = WinLaunchChild(exePath, argc, argvConverted, needElevation);
+ FreeAllocStrings(argc, argvConverted);
+ return ok;
+}
+
+BOOL
+WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv, int needElevation)
+{
+ PRUnichar *cl;
BOOL ok;
if (needElevation > 0) {
cl = MakeCommandLine(argc - 1, argv + 1);
if (!cl)
return FALSE;
- ok = ShellExecute(NULL, // no special UI window
- NULL, // use default verb
- exePath,
- cl,
- NULL, // use my current directory
- SW_SHOWDEFAULT) > (HINSTANCE)32;
+ ok = ShellExecuteW(NULL, // no special UI window
+ NULL, // use default verb
+ exePath,
+ cl,
+ NULL, // use my current directory
+ SW_SHOWDEFAULT) > (HINSTANCE)32;
free(cl);
return ok;
}
cl = MakeCommandLine(argc, argv);
if (!cl)
return FALSE;
if (needElevation < 0) {
// try to launch as a normal user first
ok = LaunchAsNormalUser(exePath, cl);
// if it fails, fallback to normal launching
if (!ok)
needElevation = 0;
}
if (needElevation == 0) {
- STARTUPINFO si = {sizeof(si), 0};
+ STARTUPINFOW si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
- ok = CreateProcess(exePath,
- cl,
- NULL, // no special security attributes
- NULL, // no special thread attributes
- FALSE, // don't inherit filehandles
- 0, // No special process creation flags
- NULL, // inherit my environment
- NULL, // use my current directory
- &si,
- &pi);
+ ok = CreateProcessW(exePath,
+ cl,
+ NULL, // no special security attributes
+ NULL, // no special thread attributes
+ FALSE, // don't inherit filehandles
+ 0, // No special process creation flags
+ NULL, // inherit my environment
+ NULL, // use my current directory
+ &si,
+ &pi);
if (ok) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
free(cl);
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/nsWindowsWMain.cpp
@@ -0,0 +1,58 @@
+// This file is a .cpp file meant to be included in nsBrowserApp.cpp and other
+// similar bootstrap code. It converts wide-character windows wmain into UTF-8
+// narrow-character strings.
+
+#ifndef XP_WIN
+#error This file only makes sense on Windows.
+#endif
+
+#include "nsUTF8Utils.h"
+
+#define main NS_internal_main
+
+int main(int argc, char **argv);
+
+static char*
+AllocConvertUTF16toUTF8(const WCHAR *arg)
+{
+ // be generous... UTF16 units can expand up to 3 UTF8 units
+ int len = wcslen(arg);
+ char *s = new char[len * 3 + 1];
+ if (!s)
+ return NULL;
+
+ ConvertUTF16toUTF8 convert(s);
+ len = convert.write(arg, len);
+ s[len] = '\0';
+ return s;
+}
+
+static void
+FreeAllocStrings(int argc, char **argv)
+{
+ while (argc) {
+ --argc;
+ delete [] argv[argc];
+ }
+
+ delete [] argv;
+}
+
+int wmain(int argc, WCHAR **argv)
+{
+ char **argvConverted = new char*[argc + 1];
+ if (!argvConverted)
+ return 127;
+
+ for (int i = 0; i < argc; ++i) {
+ argvConverted[i] = AllocConvertUTF16toUTF8(argv[i]);
+ if (!argvConverted[i]) {
+ return 127;
+ }
+ }
+ argvConverted[argc] = NULL;
+
+ int result = main(argc, argvConverted);
+ FreeAllocStrings(argc, argvConverted);
+ return result;
+}
--- a/toolkit/xre/nsXULAppAPI.h
+++ b/toolkit/xre/nsXULAppAPI.h
@@ -249,37 +249,36 @@ struct nsXREAppData
* the aAppDirProvider object passed to XRE_InitEmbedding.
*/
#define NS_APP_PROFILE_LOCAL_DIR_STARTUP "ProfLDS"
/**
* Begin an XUL application. Does not return until the user exits the
* application.
*
- * @param argc/argv Command-line parameters to pass to the application. These
- * are in the "native" character set.
+ * @param argc/argv Command-line parameters to pass to the application. On
+ * Windows, these should be in UTF8. On unix-like platforms
+ * these are in the "native" character set.
*
* @param aAppData Information about the application to be run.
*
* @return A native result code suitable for returning from main().
*
* @note If the binary is linked against the standalone XPCOM glue,
* XPCOMGlueStartup() should be called before this method.
*
- * @note XXXbsmedberg Nobody uses the glue yet, but there is a
- * potential problem: on windows, the standalone glue calls
- * SetCurrentDirectory, and relative paths on the command line
- * won't be correct.
*/
XRE_API(int,
XRE_main, (int argc, char* argv[], const nsXREAppData* sAppData))
/**
* Given a path relative to the current working directory (or an absolute
* path), return an appropriate nsILocalFile object.
+ *
+ * @note Pass UTF8 strings on Windows... native charset on other platforms.
*/
XRE_API(nsresult,
XRE_GetFileFromPath, (const char *aPath, nsILocalFile* *aResult))
/**
* Get the path of the running application binary and store it in aResult.
* @param argv0 The value passed as argv[0] of main(). This value is only
* used on *nix, and only when other methods of determining
--- a/uriloader/exthandler/win/nsMIMEInfoWin.cpp
+++ b/uriloader/exthandler/win/nsMIMEInfoWin.cpp
@@ -49,16 +49,17 @@
#include "nsAutoPtr.h"
#include "nsIMutableArray.h"
#include "nsTArray.h"
#include "shlobj.h"
#include "windows.h"
#include "nsIWindowsRegKey.h"
#include "nsIProcess.h"
#include "nsOSHelperAppService.h"
+#include "nsUnicharUtils.h"
NS_IMPL_ISUPPORTS_INHERITED1(nsMIMEInfoWin, nsMIMEInfoBase, nsIPropertyBag)
nsMIMEInfoWin::~nsMIMEInfoWin()
{
}
nsresult
@@ -536,25 +537,25 @@ PRBool nsMIMEInfoWin::GetProgIDVerbComma
return PR_TRUE;
}
return PR_FALSE;
}
// Helper routine used in tracking app lists. Converts path
// entries to lower case and stores them in the trackList array.
void nsMIMEInfoWin::ProcessPath(nsCOMPtr<nsIMutableArray>& appList,
- nsTArray<nsCAutoString>& trackList,
+ nsTArray<nsString>& trackList,
const nsAString& appFilesystemCommand)
{
- NS_ConvertUTF16toUTF8 lower(appFilesystemCommand);
+ nsAutoString lower(appFilesystemCommand);
ToLowerCase(lower);
// Don't include firefox.exe in the list
- char exe[MAX_PATH+1];
- PRUint32 len = GetModuleFileName(NULL, exe, MAX_PATH);
+ WCHAR exe[MAX_PATH+1];
+ PRUint32 len = GetModuleFileNameW(NULL, exe, MAX_PATH);
if (len < MAX_PATH && len != 0) {
PRUint32 index = lower.Find(exe);
if (index != -1)
return;
}
nsCOMPtr<nsILocalHandlerApp> aApp;
if (!GetLocalHandlerApp(appFilesystemCommand, aApp))
@@ -563,21 +564,21 @@ void nsMIMEInfoWin::ProcessPath(nsCOMPtr
// Save in our main tracking arrays
appList->AppendElement(aApp, PR_FALSE);
trackList.AppendElement(lower);
}
// Helper routine that handles a compare between a path
// and an array of paths.
static PRBool IsPathInList(nsAString& appPath,
- nsTArray<nsCAutoString>& trackList)
+ nsTArray<nsString>& trackList)
{
// trackList data is always lowercase, see ProcessPath
// above.
- NS_ConvertUTF16toUTF8 tmp(appPath);
+ nsAutoString tmp(appPath);
ToLowerCase(tmp);
for (PRUint32 i = 0; i < trackList.Length(); i++) {
if (tmp.Equals(trackList[i]))
return PR_TRUE;
}
return PR_FALSE;
}
@@ -599,17 +600,17 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(
*_retval = nsnull;
nsCOMPtr<nsIMutableArray> appList =
do_CreateInstance("@mozilla.org/array;1");
if (!appList)
return NS_ERROR_FAILURE;
- nsTArray<nsCAutoString> trackList;
+ nsTArray<nsString> trackList;
nsCAutoString fileExt;
GetPrimaryExtension(fileExt);
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1");
if (!regKey)
return NS_ERROR_FAILURE;
--- a/uriloader/exthandler/win/nsMIMEInfoWin.h
+++ b/uriloader/exthandler/win/nsMIMEInfoWin.h
@@ -89,14 +89,14 @@ class nsMIMEInfoWin : public nsMIMEInfoB
// Lookup a rundll command handler and return
// a populated command template for use with rundll32.exe.
PRBool GetDllLaunchInfo(nsIFile * aDll,
nsILocalFile * aFile,
nsAString& args, PRBool bEdit);
// Helper routine used in tracking app lists
void ProcessPath(nsCOMPtr<nsIMutableArray>& appList,
- nsTArray<nsCAutoString>& trackList,
+ nsTArray<nsString>& trackList,
const nsAString& appFilesystemCommand);
};
#endif
--- a/xpcom/string/public/nsCharTraits.h
+++ b/xpcom/string/public/nsCharTraits.h
@@ -57,20 +57,30 @@
#include <string.h>
// for |memcpy|, et al
#ifndef nscore_h___
#include "nscore.h"
// for |PRUnichar|
#endif
+// This file may be used (through nsUTF8Utils.h) from non-XPCOM code, in
+// particular the standalone software updater. In that case stub out
+// the macros provided by nsDebug.h which are only usable when linking XPCOM
+
+#ifdef NS_NO_XPCOM
+#define NS_WARNING(msg)
+#define NS_ASSERTION(cond, msg)
+#define NS_ERROR(msg)
+#else
#ifndef nsDebug_h__
#include "nsDebug.h"
// for NS_ASSERTION
#endif
+#endif
#ifdef HAVE_CPP_BOOL
typedef bool nsCharTraits_bool;
#else
typedef PRBool nsCharTraits_bool;
#endif
/*
--- a/xpcom/string/public/nsUTF8Utils.h
+++ b/xpcom/string/public/nsUTF8Utils.h
@@ -33,16 +33,22 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsUTF8Utils_h_
#define nsUTF8Utils_h_
+// This file may be used in two ways: if MOZILLA_INTERNAL_API is defined, this
+// file will provide signatures for the Mozilla abstract string types. It will
+// use XPCOM assertion/debugging macros, etc.
+
+#include "nscore.h"
+
#include "nsCharTraits.h"
class UTF8traits
{
public:
static PRBool isASCII(char c) { return (c & 0x80) == 0x00; }
static PRBool isInSeq(char c) { return (c & 0xC0) == 0x80; }
static PRBool is2byte(char c) { return (c & 0xE0) == 0xC0; }
@@ -131,16 +137,18 @@ public:
if (err)
*err = PR_FALSE;
if (overlong)
*overlong = ucs4 < minUcs4;
*buffer = p;
return ucs4;
}
+#ifdef MOZILLA_INTERNAL_API
+
static PRUint32 NextChar(nsACString::const_iterator& iter,
const nsACString::const_iterator& end,
PRBool *err = nsnull, PRBool *overlong = nsnull)
{
if ( iter == end )
{
NS_ERROR("No input to work with");
if (err)
@@ -194,16 +202,17 @@ public:
}
if (err)
*err = PR_FALSE;
if (overlong)
*overlong = ucs4 < minUcs4;
return ucs4;
}
+#endif // MOZILLA_INTERNAL_API
private:
static PRBool CalcState(char c, PRUint32& ucs4, PRUint32& minUcs4,
PRInt32& state)
{
if ( UTF8traits::is2byte(c) )
{
ucs4 = (PRUint32(c) << 6) & 0x000007C0L;
@@ -351,16 +360,18 @@ public:
return 0xFFFD;
}
if (err)
*err = PR_TRUE;
return 0;
}
+#ifdef MOZILLA_INTERNAL_API
+
static PRUint32 NextChar(nsAString::const_iterator& iter,
const nsAString::const_iterator& end,
PRBool *err = nsnull)
{
if (iter == end)
{
if (err)
*err = PR_TRUE;
@@ -432,28 +443,29 @@ public:
*err = PR_TRUE;
return 0xFFFD;
}
if (err)
*err = PR_TRUE;
return 0;
}
+#endif // MOZILLA_INTERNAL_API
};
/**
* A character sink (see |copy_string| in nsAlgorithm.h) for converting
* UTF-8 to UTF-16
*/
class ConvertUTF8toUTF16
{
public:
- typedef nsACString::char_type value_type;
- typedef nsAString::char_type buffer_type;
+ typedef char value_type;
+ typedef PRUnichar buffer_type;
ConvertUTF8toUTF16( buffer_type* aBuffer )
: mStart(aBuffer), mBuffer(aBuffer), mErrorEncountered(PR_FALSE) {}
size_t Length() const { return mBuffer - mStart; }
PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
{
@@ -528,17 +540,17 @@ class ConvertUTF8toUTF16
/**
* A character sink (see |copy_string| in nsAlgorithm.h) for computing
* the length of the UTF-16 string equivalent to a UTF-8 string.
*/
class CalculateUTF8Length
{
public:
- typedef nsACString::char_type value_type;
+ typedef char value_type;
CalculateUTF8Length() : mLength(0), mErrorEncountered(PR_FALSE) { }
size_t Length() const { return mLength; }
PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
{
// ignore any further requests
@@ -597,18 +609,18 @@ class CalculateUTF8Length
/**
* A character sink (see |copy_string| in nsAlgorithm.h) for
* converting UTF-16 to UTF-8. Treats invalid UTF-16 data as 0xFFFD
* (0xEFBFBD in UTF-8).
*/
class ConvertUTF16toUTF8
{
public:
- typedef nsAString::char_type value_type;
- typedef nsACString::char_type buffer_type;
+ typedef PRUnichar value_type;
+ typedef char buffer_type;
// The error handling here is more lenient than that in
// |ConvertUTF8toUTF16|, but it's that way for backwards
// compatibility.
ConvertUTF16toUTF8( buffer_type* aBuffer )
: mStart(aBuffer), mBuffer(aBuffer) {}
@@ -711,17 +723,17 @@ class ConvertUTF16toUTF8
/**
* A character sink (see |copy_string| in nsAlgorithm.h) for computing
* the number of bytes a UTF-16 would occupy in UTF-8. Treats invalid
* UTF-16 data as 0xFFFD (0xEFBFBD in UTF-8).
*/
class CalculateUTF8Size
{
public:
- typedef nsAString::char_type value_type;
+ typedef PRUnichar value_type;
CalculateUTF8Size()
: mSize(0) { }
size_t Size() const { return mSize; }
PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
{
@@ -775,16 +787,17 @@ class CalculateUTF8Size
return N;
}
private:
size_t mSize;
};
+#ifdef MOZILLA_INTERNAL_API
/**
* A character sink that performs a |reinterpret_cast| style conversion
* between character types.
*/
template <class FromCharT, class ToCharT>
class LossyConvertEncoding
{
public:
@@ -811,10 +824,11 @@ class LossyConvertEncoding
write_terminator()
{
*mDestination = output_type(0);
}
private:
output_type* mDestination;
};
+#endif // MOZILLA_INTERNAL_API
#endif /* !defined(nsUTF8Utils_h_) */
--- a/xulrunner/app/Makefile.in
+++ b/xulrunner/app/Makefile.in
@@ -128,16 +128,22 @@ MOZ_WINCONSOLE = 0
endif
endif
DEFINES += -DMOZ_WINCONSOLE=$(MOZ_WINCONSOLE)
NSDISTMODE = copy
include $(topsrcdir)/config/config.mk
+ifdef _MSC_VER
+# Always enter a Windows program through wmain, whether or not we're
+# a console application.
+WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
+endif
+
ifdef NS_TRACE_MALLOC
EXTRA_DSO_LIBS += tracemalloc
endif
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool)
RCINCLUDE = splash.rc
ifndef GNU_CC
--- a/xulrunner/app/nsXULRunnerApp.cpp
+++ b/xulrunner/app/nsXULRunnerApp.cpp
@@ -52,16 +52,20 @@
#include "nsCRTGlue.h"
#include "nsStringAPI.h"
#include "nsServiceManagerUtils.h"
#include "plstr.h"
#include "prprf.h"
#include "prenv.h"
#include "nsINIParser.h"
+#ifdef XP_WIN
+#include "nsWindowsWMain.cpp"
+#endif
+
/**
* Output a string to the user. This method is really only meant to be used to
* output last-ditch error messages designed for developers NOT END USERS.
*
* @param isError
* Pass true to indicate severe errors.
* @param fmt
* printf-style format string followed by arguments.
@@ -440,18 +444,8 @@ int main(int argc, char* argv[])
AutoAppData appData(appDataLF);
if (!appData) {
Output(PR_TRUE, "Error: couldn't parse application.ini.\n");
return 2;
}
return XRE_main(argc, argv, appData);
}
-
-#if defined( XP_WIN ) && defined( WIN32 ) && !defined(__GNUC__)
-// We need WinMain in order to not be a console app. This function is
-// unused if we are a console application.
-int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR args, int )
-{
- // Do the real work.
- return main( __argc, __argv );
-}
-#endif
--- a/xulrunner/stub/Makefile.in
+++ b/xulrunner/stub/Makefile.in
@@ -39,17 +39,17 @@ DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xulrunner
-REQUIRES = xpcom xulapp
+REQUIRES = xpcom string xulapp
CPPSRCS = nsXULStub.cpp
# Statically link the CRT when possible
USE_STATIC_LIBS = 1
# The value of XULRUNNER_STUB_NAME is generated by configure to allow XULRunner
# apps to override it using the --with-xulrunner-stub-name=<appname> argument.
@@ -79,13 +79,19 @@ endif
ifndef MOZ_WINCONSOLE
ifdef MOZ_DEBUG
MOZ_WINCONSOLE = 1
else
MOZ_WINCONSOLE = 0
endif
endif
+include $(topsrcdir)/config/config.mk
+
+ifdef _MSC_VER
+WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup
+endif
+
include $(topsrcdir)/config/rules.mk
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,shell32)
endif
--- a/xulrunner/stub/nsXULStub.cpp
+++ b/xulrunner/stub/nsXULStub.cpp
@@ -46,17 +46,16 @@
#include <stdarg.h>
#ifdef XP_WIN
#include <windows.h>
#include <io.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define PATH_SEPARATOR_CHAR '\\'
-#include "nsWindowsRestart.cpp"
#define R_OK 04
#elif defined(XP_MACOSX)
#include <CFBundle.h>
#define PATH_SEPARATOR_CHAR '/'
#elif defined (XP_OS2)
#define INCL_DOS
#define INCL_DOSMISC
#define INCL_DOSERRORS
@@ -67,16 +66,20 @@
#define PATH_SEPARATOR_CHAR '\\'
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define PATH_SEPARATOR_CHAR '/'
#endif
+#ifdef XP_WIN
+#include "nsWindowsWMain.cpp"
+#endif
+
#define VERSION_MAXLEN 128
static void Output(PRBool isError, const char *fmt, ... )
{
va_list ap;
va_start(ap, fmt);
#if defined(XP_WIN) && !MOZ_WINCONSOLE
@@ -346,18 +349,8 @@ main(int argc, char **argv)
}
NS_LogTerm();
XPCOMGlueShutdown();
return retval;
}
-
-#if defined( XP_WIN ) && defined( WIN32 ) && !defined(__GNUC__)
-// We need WinMain in order to not be a console app. This function is
-// unused if we are a console application.
-int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR args, int )
-{
- // Do the real work.
- return main( __argc, __argv );
-}
-#endif