Bug 396052 - Firefox fails to start when run from a directory with non-native characters, r=luser sr=neil
This commit is contained in:
Родитель
76576ca87c
Коммит
81cceca417
|
@ -151,6 +151,13 @@ 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
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
#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;
|
||||
|
@ -156,13 +161,3 @@ int main(int argc, char* argv[])
|
|||
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
|
||||
|
|
|
@ -59,6 +59,8 @@ interface nsICommandLineRunner : nsICommandLine
|
|||
* 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.
|
||||
*/
|
||||
|
|
|
@ -384,20 +384,17 @@ nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult)
|
|||
// 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);
|
||||
|
@ -471,7 +468,11 @@ nsCommandLine::appendArg(const char* arg)
|
|||
#endif
|
||||
|
||||
nsAutoString warg;
|
||||
#ifdef XP_WIN
|
||||
CopyUTF8toUTF16(nsDependentCString(arg), warg);
|
||||
#else
|
||||
NS_CopyNativeToUnicode(nsDependentCString(arg), warg);
|
||||
#endif
|
||||
|
||||
mArgs.AppendString(warg);
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ CPPSRCS = \
|
|||
|
||||
PROGRAM = updater$(BIN_SUFFIX)
|
||||
|
||||
REQUIRES = libmar libbz2
|
||||
REQUIRES = libmar libbz2 string
|
||||
|
||||
LIBS += \
|
||||
$(DEPTH)/modules/libmar/src/$(LIB_PREFIX)mar.$(LIB_SUFFIX) \
|
||||
|
@ -65,6 +65,7 @@ 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
|
||||
|
@ -104,6 +105,12 @@ 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
|
||||
|
|
|
@ -95,6 +95,16 @@ ArchiveReader::ExtractFile(const char *name, const char *dest)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
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);
|
||||
|
|
|
@ -39,8 +39,16 @@
|
|||
#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();
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <process.h>
|
||||
#include <io.h>
|
||||
#include "resource.h"
|
||||
#include "progressui.h"
|
||||
|
||||
#define TIMER_ID 1
|
||||
#define TIMER_INTERVAL 100
|
||||
|
@ -72,16 +73,16 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -95,7 +96,7 @@ UpdateDialog(HWND hDlg)
|
|||
static void
|
||||
ResizeDialogToFit(HWND hDlg)
|
||||
{
|
||||
char text[MAX_INFO_LENGTH];
|
||||
WCHAR text[MAX_INFO_LENGTH];
|
||||
RECT infoSize, textSize;
|
||||
HFONT hInfoFont, hOldFont;
|
||||
|
||||
|
@ -173,23 +174,23 @@ CenterDialog(HWND hDlg)
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -250,7 +251,7 @@ DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
|
||||
int
|
||||
InitProgressUI(int *argc, char ***argv)
|
||||
InitProgressUI(int *argc, NS_tchar ***argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -267,10 +268,10 @@ ShowProgressUI()
|
|||
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 = {
|
||||
|
|
|
@ -47,6 +47,41 @@
|
|||
* 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"
|
||||
|
@ -64,24 +99,6 @@
|
|||
#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);
|
||||
|
@ -261,7 +278,7 @@ private:
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static char* gSourcePath;
|
||||
static NS_tchar* gSourcePath;
|
||||
static ArchiveReader gArchiveReader;
|
||||
#ifdef XP_WIN
|
||||
static bool gSucceeded = FALSE;
|
||||
|
@ -281,10 +298,10 @@ 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()
|
||||
|
@ -359,7 +376,7 @@ mstrtok(const char *delims, char **str)
|
|||
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)) {
|
||||
|
@ -741,9 +758,11 @@ PatchFile::~PatchFile()
|
|||
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);
|
||||
}
|
||||
|
@ -818,12 +837,18 @@ PatchFile::Prepare()
|
|||
// 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);
|
||||
|
||||
ensure_remove(spath);
|
||||
NS_tremove(spath);
|
||||
|
||||
int rv = gArchiveReader.ExtractFile(mPatchFile, spath);
|
||||
FILE *fp = NS_tfopen(spath, NS_T("wb"));
|
||||
if (!fp)
|
||||
return WRITE_ERROR;
|
||||
|
||||
int rv = gArchiveReader.ExtractFileToStream(mPatchFile, fp);
|
||||
fclose(fp);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
|
@ -831,7 +856,7 @@ PatchFile::Prepare()
|
|||
// 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;
|
||||
|
||||
|
@ -1011,55 +1036,66 @@ PatchIfFile::Finish(int status)
|
|||
#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);
|
||||
|
@ -1067,13 +1103,13 @@ LaunchWinPostProcess(const char *appExe)
|
|||
#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);
|
||||
|
@ -1134,7 +1170,7 @@ UpdateThreadFunc(void *param)
|
|||
QuitProgressUI();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int NS_main(int argc, NS_tchar **argv)
|
||||
{
|
||||
InitProgressUI(&argc, &argv);
|
||||
|
||||
|
@ -1150,7 +1186,7 @@ int main(int argc, char **argv)
|
|||
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);
|
||||
|
@ -1306,15 +1342,20 @@ ActionList::Finish(int status)
|
|||
|
||||
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;
|
||||
|
||||
|
@ -1394,13 +1435,3 @@ int DoUpdate()
|
|||
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
|
||||
|
|
|
@ -929,13 +929,13 @@ XRE_GetFileFromPath(const char *aPath, nsILocalFile* *aResult)
|
|||
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;
|
||||
|
|
|
@ -291,9 +291,46 @@ SaveWordToEnv(const char *name, const nsACString & word)
|
|||
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
|
||||
|
@ -691,8 +728,8 @@ nsXULAppInfo::LaunchAppHelperWithArgs(int aArgc, char **aArgv)
|
|||
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))
|
||||
|
@ -1325,13 +1362,13 @@ XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult)
|
|||
// nsGREDirServiceProvider.cpp
|
||||
|
||||
#ifdef XP_WIN
|
||||
char exePath[MAXPATHLEN];
|
||||
PRUnichar exePath[MAXPATHLEN];
|
||||
|
||||
if (!::GetModuleFileName(0, 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;
|
||||
|
||||
|
@ -1579,15 +1616,22 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative,
|
|||
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;
|
||||
|
@ -1612,8 +1656,9 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative,
|
|||
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;
|
||||
}
|
||||
|
@ -1855,20 +1900,11 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
|||
*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;
|
||||
}
|
||||
|
||||
|
@ -1876,7 +1912,6 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
|||
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);
|
||||
|
|
|
@ -133,7 +133,7 @@ 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"
|
||||
|
|
|
@ -563,29 +563,29 @@ struct MessageWindow {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -615,9 +615,9 @@ struct MessageWindow {
|
|||
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);
|
||||
|
||||
|
@ -701,8 +701,7 @@ nsNativeAppSupportWin::Start( PRBool *aResult ) {
|
|||
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();
|
||||
|
|
|
@ -363,6 +363,11 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile,
|
|||
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.
|
||||
|
@ -435,7 +440,7 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile,
|
|||
#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
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#define nsWindowsRestart_cpp
|
||||
#endif
|
||||
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
#include <shellapi.h>
|
||||
|
||||
#ifndef ERROR_ELEVATION_REQUIRED
|
||||
|
@ -65,7 +67,7 @@ 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) {
|
||||
|
@ -73,7 +75,7 @@ static int QuotedStrLen(const char *s)
|
|||
++i;
|
||||
}
|
||||
|
||||
++i; ++s;
|
||||
++i, ++s;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
@ -85,7 +87,7 @@ static int QuotedStrLen(const char *s)
|
|||
*
|
||||
* @return the end of the string
|
||||
*/
|
||||
static char* QuoteString(char *d, const char *s)
|
||||
static PRUnichar* QuoteString(PRUnichar *d, const PRUnichar *s)
|
||||
{
|
||||
*d = '"';
|
||||
++d;
|
||||
|
@ -109,9 +111,11 @@ static char* QuoteString(char *d, const char *s)
|
|||
/**
|
||||
* 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
|
||||
|
@ -119,11 +123,11 @@ MakeCommandLine(int argc, char **argv)
|
|||
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 = ' ';
|
||||
|
@ -135,37 +139,20 @@ MakeCommandLine(int argc, char **argv)
|
|||
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)
|
||||
|
@ -177,7 +164,7 @@ LaunchAsNormalUser(const char *exePath, char *cl)
|
|||
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);
|
||||
|
||||
|
@ -205,22 +192,24 @@ LaunchAsNormalUser(const char *exePath, char *cl)
|
|||
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;
|
||||
|
@ -231,26 +220,80 @@ LaunchAsNormalUser(const char *exePath, char *cl)
|
|||
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 char *exePath, int argc, char **argv, int needElevation)
|
||||
WinLaunchChild(const PRUnichar *exePath, int argc, PRUnichar **argv, int needElevation);
|
||||
|
||||
BOOL
|
||||
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;
|
||||
}
|
||||
|
@ -267,19 +310,19 @@ WinLaunchChild(const char *exePath, int argc, char **argv, int needElevation)
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -254,8 +254,9 @@ struct nsXREAppData
|
|||
* 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.
|
||||
*
|
||||
|
@ -264,10 +265,6 @@ struct nsXREAppData
|
|||
* @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))
|
||||
|
@ -275,6 +272,8 @@ XRE_API(int,
|
|||
/**
|
||||
* 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))
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "nsIWindowsRegKey.h"
|
||||
#include "nsIProcess.h"
|
||||
#include "nsOSHelperAppService.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsMIMEInfoWin, nsMIMEInfoBase, nsIPropertyBag)
|
||||
|
||||
|
@ -541,15 +542,15 @@ PRBool nsMIMEInfoWin::GetProgIDVerbCommandHandler(const nsAString& appProgIDName
|
|||
// 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)
|
||||
|
@ -568,11 +569,11 @@ void nsMIMEInfoWin::ProcessPath(nsCOMPtr<nsIMutableArray>& appList,
|
|||
// 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++) {
|
||||
|
@ -604,7 +605,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray **_retval)
|
|||
if (!appList)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsTArray<nsCAutoString> trackList;
|
||||
nsTArray<nsString> trackList;
|
||||
|
||||
nsCAutoString fileExt;
|
||||
GetPrimaryExtension(fileExt);
|
||||
|
|
|
@ -94,7 +94,7 @@ class nsMIMEInfoWin : public nsMIMEInfoBase, public nsIPropertyBag {
|
|||
|
||||
// Helper routine used in tracking app lists
|
||||
void ProcessPath(nsCOMPtr<nsIMutableArray>& appList,
|
||||
nsTArray<nsCAutoString>& trackList,
|
||||
nsTArray<nsString>& trackList,
|
||||
const nsAString& appFilesystemCommand);
|
||||
|
||||
};
|
||||
|
|
|
@ -62,10 +62,20 @@
|
|||
// 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;
|
||||
|
|
|
@ -38,6 +38,12 @@
|
|||
#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
|
||||
|
@ -136,6 +142,8 @@ public:
|
|||
return ucs4;
|
||||
}
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
|
||||
static PRUint32 NextChar(nsACString::const_iterator& iter,
|
||||
const nsACString::const_iterator& end,
|
||||
PRBool *err = nsnull, PRBool *overlong = nsnull)
|
||||
|
@ -199,6 +207,7 @@ public:
|
|||
*overlong = ucs4 < minUcs4;
|
||||
return ucs4;
|
||||
}
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
private:
|
||||
static PRBool CalcState(char c, PRUint32& ucs4, PRUint32& minUcs4,
|
||||
|
@ -356,6 +365,8 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
|
||||
static PRUint32 NextChar(nsAString::const_iterator& iter,
|
||||
const nsAString::const_iterator& end,
|
||||
PRBool *err = nsnull)
|
||||
|
@ -437,6 +448,7 @@ public:
|
|||
*err = PR_TRUE;
|
||||
return 0;
|
||||
}
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
};
|
||||
|
||||
|
||||
|
@ -447,8 +459,8 @@ public:
|
|||
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) {}
|
||||
|
@ -533,7 +545,7 @@ class ConvertUTF8toUTF16
|
|||
class CalculateUTF8Length
|
||||
{
|
||||
public:
|
||||
typedef nsACString::char_type value_type;
|
||||
typedef char value_type;
|
||||
|
||||
CalculateUTF8Length() : mLength(0), mErrorEncountered(PR_FALSE) { }
|
||||
|
||||
|
@ -602,8 +614,8 @@ class CalculateUTF8Length
|
|||
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
|
||||
|
@ -716,7 +728,7 @@ class ConvertUTF16toUTF8
|
|||
class CalculateUTF8Size
|
||||
{
|
||||
public:
|
||||
typedef nsAString::char_type value_type;
|
||||
typedef PRUnichar value_type;
|
||||
|
||||
CalculateUTF8Size()
|
||||
: mSize(0) { }
|
||||
|
@ -780,6 +792,7 @@ class CalculateUTF8Size
|
|||
size_t mSize;
|
||||
};
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
/**
|
||||
* A character sink that performs a |reinterpret_cast| style conversion
|
||||
* between character types.
|
||||
|
@ -816,5 +829,6 @@ class LossyConvertEncoding
|
|||
private:
|
||||
output_type* mDestination;
|
||||
};
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
#endif /* !defined(nsUTF8Utils_h_) */
|
||||
|
|
|
@ -133,6 +133,12 @@ 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
|
||||
|
|
|
@ -57,6 +57,10 @@
|
|||
#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.
|
||||
|
@ -445,13 +449,3 @@ int main(int argc, char* argv[])
|
|||
|
||||
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
|
||||
|
|
|
@ -44,7 +44,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
MODULE = xulrunner
|
||||
|
||||
REQUIRES = xpcom xulapp
|
||||
REQUIRES = xpcom string xulapp
|
||||
|
||||
CPPSRCS = nsXULStub.cpp
|
||||
|
||||
|
@ -84,6 +84,12 @@ 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)
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define PATH_SEPARATOR_CHAR '\\'
|
||||
#include "nsWindowsRestart.cpp"
|
||||
#define R_OK 04
|
||||
#elif defined(XP_MACOSX)
|
||||
#include <CFBundle.h>
|
||||
|
@ -72,6 +71,10 @@
|
|||
#define PATH_SEPARATOR_CHAR '/'
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "nsWindowsWMain.cpp"
|
||||
#endif
|
||||
|
||||
#define VERSION_MAXLEN 128
|
||||
|
||||
static void Output(PRBool isError, const char *fmt, ... )
|
||||
|
@ -351,13 +354,3 @@ main(int argc, char **argv)
|
|||
|
||||
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче