зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1457999: Backed out changeset d838002f9a52 due to Linux preprocessor errors; r=backout CLOSED TREE
--HG-- extra : histedit_source : 0a31b8596f8525662a19f6221c605b19486baefc
This commit is contained in:
Родитель
700a2481d1
Коммит
2cd522a2f4
|
@ -1,385 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_CmdLineAndEnvUtils_h
|
||||
#define mozilla_CmdLineAndEnvUtils_h
|
||||
|
||||
// NB: This code may be used outside of xul and thus must not depend on XPCOM
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#include "prenv.h"
|
||||
#include <string.h>
|
||||
#elif defined(XP_WIN)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <wchar.h>
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum ArgResult {
|
||||
ARG_NONE = 0,
|
||||
ARG_FOUND = 1,
|
||||
ARG_BAD = 2 // you wanted a param, but there isn't one
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
inline void
|
||||
RemoveArg(int& argc, CharT **argv)
|
||||
{
|
||||
do {
|
||||
*argv = *(argv + 1);
|
||||
++argv;
|
||||
} while (*argv);
|
||||
|
||||
--argc;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename FuncT, typename CharT>
|
||||
inline bool
|
||||
strimatch(FuncT aToLowerFn, const CharT* lowerstr, const CharT* mixedstr)
|
||||
{
|
||||
while(*lowerstr) {
|
||||
if (!*mixedstr) return false; // mixedstr is shorter
|
||||
if (aToLowerFn(*mixedstr) != *lowerstr) return false; // no match
|
||||
|
||||
++lowerstr;
|
||||
++mixedstr;
|
||||
}
|
||||
|
||||
if (*mixedstr) return false; // lowerstr is shorter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
inline bool
|
||||
strimatch(const char* lowerstr, const char* mixedstr)
|
||||
{
|
||||
return internal::strimatch(&tolower, lowerstr, mixedstr);
|
||||
}
|
||||
|
||||
inline bool
|
||||
strimatch(const wchar_t* lowerstr, const wchar_t* mixedstr)
|
||||
{
|
||||
return internal::strimatch(&towlower, lowerstr, mixedstr);
|
||||
}
|
||||
|
||||
enum class FlagLiteral
|
||||
{
|
||||
osint,
|
||||
safemode
|
||||
};
|
||||
|
||||
template <typename CharT, FlagLiteral Literal>
|
||||
inline const CharT* GetLiteral();
|
||||
|
||||
#define DECLARE_FLAG_LITERAL(enum_name, literal) \
|
||||
template <> inline \
|
||||
const char* GetLiteral<char, FlagLiteral::##enum_name>() \
|
||||
{ \
|
||||
return literal; \
|
||||
} \
|
||||
\
|
||||
template <> inline \
|
||||
const wchar_t* GetLiteral<wchar_t, FlagLiteral::##enum_name>() \
|
||||
{ \
|
||||
return L##literal; \
|
||||
}
|
||||
|
||||
DECLARE_FLAG_LITERAL(osint, "osint")
|
||||
DECLARE_FLAG_LITERAL(safemode, "safe-mode")
|
||||
|
||||
enum class CheckArgFlag : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
CheckOSInt = (1 << 0), // Retrun ARG_BAD if osint arg is also present.
|
||||
RemoveArg = (1 << 1) // Remove the argument from the argv array.
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CheckArgFlag)
|
||||
|
||||
/**
|
||||
* Check for a commandline flag. If the flag takes a parameter, the
|
||||
* parameter is returned in aParam. Flags may be in the form -arg or
|
||||
* --arg (or /arg on win32).
|
||||
*
|
||||
* @param aArgc The argc value.
|
||||
* @param aArgv The original argv.
|
||||
* @param aArg the parameter to check. Must be lowercase.
|
||||
* @param aParam if non-null, the -arg <data> will be stored in this pointer.
|
||||
* This is *not* allocated, but rather a pointer to the argv data.
|
||||
* @param aFlags Flags @see CheckArgFlag
|
||||
*/
|
||||
template <typename CharT>
|
||||
inline ArgResult
|
||||
CheckArg(int& aArgc, CharT** aArgv, const CharT* aArg, const CharT **aParam,
|
||||
CheckArgFlag aFlags)
|
||||
{
|
||||
MOZ_ASSERT(aArgv && aArg);
|
||||
|
||||
CharT **curarg = aArgv + 1; // skip argv[0]
|
||||
ArgResult ar = ARG_NONE;
|
||||
|
||||
while (*curarg) {
|
||||
CharT *arg = curarg[0];
|
||||
|
||||
if (arg[0] == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| *arg == '/'
|
||||
#endif
|
||||
) {
|
||||
++arg;
|
||||
|
||||
if (*arg == '-') {
|
||||
++arg;
|
||||
}
|
||||
|
||||
if (strimatch(aArg, arg)) {
|
||||
if (aFlags & CheckArgFlag::RemoveArg) {
|
||||
RemoveArg(aArgc, curarg);
|
||||
} else {
|
||||
++curarg;
|
||||
}
|
||||
|
||||
if (!aParam) {
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*curarg) {
|
||||
if (**curarg == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| **curarg == '/'
|
||||
#endif
|
||||
) {
|
||||
return ARG_BAD;
|
||||
}
|
||||
|
||||
*aParam = *curarg;
|
||||
|
||||
if (aFlags & CheckArgFlag::RemoveArg) {
|
||||
RemoveArg(aArgc, curarg);
|
||||
}
|
||||
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
return ARG_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
++curarg;
|
||||
}
|
||||
|
||||
if ((aFlags & CheckArgFlag::CheckOSInt) && ar == ARG_FOUND) {
|
||||
ArgResult arOSInt = CheckArg(aArgc, aArgv,
|
||||
GetLiteral<CharT, FlagLiteral::osint>(),
|
||||
reinterpret_cast<const CharT**>(nullptr),
|
||||
CheckArgFlag::None);
|
||||
if (arOSInt == ARG_FOUND) {
|
||||
ar = ARG_BAD;
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
PR_fprintf(PR_STDERR, "Error: argument --osint is invalid\n");
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
}
|
||||
}
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**
|
||||
* Get the length that the string will take and takes into account the
|
||||
* additional length if the string needs to be quoted and if characters need to
|
||||
* be escaped.
|
||||
*/
|
||||
inline int
|
||||
ArgStrLen(const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
int i = wcslen(s);
|
||||
bool hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
bool addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
i += 2; // initial and final duoblequote
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
i += backslashes + 1;
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy string "s" to string "d", quoting the argument as appropriate and
|
||||
* escaping doublequotes along with any backslashes that immediately precede
|
||||
* doublequotes.
|
||||
* The CRT parses this to retrieve the original argc/argv that we meant,
|
||||
* see STDARGV.C in the MSVC CRT sources.
|
||||
*
|
||||
* @return the end of the string
|
||||
*/
|
||||
inline wchar_t*
|
||||
ArgToString(wchar_t *d, const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
bool hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
bool addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // initial doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
int i;
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
for (i = 0; i <= backslashes; ++i) {
|
||||
*d = '\\';
|
||||
++d;
|
||||
}
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
*d = *s;
|
||||
++d; ++s;
|
||||
}
|
||||
} else {
|
||||
wcscpy(d, s);
|
||||
d += wcslen(s);
|
||||
}
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // final doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* Creates a command line from a list of arguments.
|
||||
*/
|
||||
inline UniquePtr<wchar_t[]>
|
||||
MakeCommandLine(int argc, wchar_t **argv)
|
||||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
|
||||
// The + 1 of the last argument handles the allocation for null termination
|
||||
for (i = 0; i < argc; ++i) {
|
||||
len += internal::ArgStrLen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
// Protect against callers that pass 0 arguments
|
||||
if (len == 0) {
|
||||
len = 1;
|
||||
}
|
||||
|
||||
auto s = MakeUnique<wchar_t[]>(len);
|
||||
if (!s) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wchar_t *c = s.get();
|
||||
for (i = 0; i < argc; ++i) {
|
||||
c = internal::ArgToString(c, argv[i]);
|
||||
if (i + 1 != argc) {
|
||||
*c = ' ';
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
|
||||
return Move(s);
|
||||
}
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
// Save literal putenv string to environment variable.
|
||||
inline void
|
||||
SaveToEnv(const char *aEnvString)
|
||||
{
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
char *expr = strdup(aEnvString);
|
||||
if (expr) {
|
||||
PR_SetEnv(expr);
|
||||
}
|
||||
|
||||
// We intentionally leak |expr| here since it is required by PR_SetEnv.
|
||||
MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr);
|
||||
#elif defined(XP_WIN)
|
||||
// This is the same as the NSPR implementation
|
||||
// (Note that we don't need to do a strdup for this case; the CRT makes a copy)
|
||||
_putenv(aEnvString);
|
||||
#else
|
||||
#error "Not implemented for this configuration"
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
EnvHasValue(const char* aVarName)
|
||||
{
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
const char* val = PR_GetEnv(aVarName);
|
||||
return val && *val;
|
||||
#elif defined(XP_WIN)
|
||||
// This is the same as the NSPR implementation
|
||||
const char* val = getenv(aVarName);
|
||||
return val && *val;
|
||||
#else
|
||||
#error "Not implemented for this configuration"
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_CmdLineAndEnvUtils_h
|
|
@ -1,46 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_PolicyChecks_h
|
||||
#define mozilla_PolicyChecks_h
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// NB: This code must be able to run apart from XPCOM
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
inline bool
|
||||
PolicyHasRegValue(HKEY aKey, LPCWSTR aName, DWORD* aValue)
|
||||
{
|
||||
DWORD len = sizeof(DWORD);
|
||||
LONG ret = ::RegGetValueW(aKey, L"SOFTWARE\\Policies\\Mozilla\\Firefox", aName,
|
||||
RRF_RT_DWORD, nullptr, aValue, &len);
|
||||
return ret == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
inline bool
|
||||
PolicyCheckBoolean(LPCWSTR aPolicyName)
|
||||
{
|
||||
DWORD value;
|
||||
if (PolicyHasRegValue(HKEY_LOCAL_MACHINE, aPolicyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
|
||||
if (PolicyHasRegValue(HKEY_CURRENT_USER, aPolicyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#endif // mozilla_PolicyChecks_h
|
|
@ -1,90 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_SafeMode_h
|
||||
#define mozilla_SafeMode_h
|
||||
|
||||
// NB: This code must be able to run apart from XPCOM
|
||||
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "mozilla/PolicyChecks.h"
|
||||
#include <windows.h>
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum class SafeModeFlag : uint32_t
|
||||
{
|
||||
None = 0,
|
||||
Unset = (1 << 0)
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SafeModeFlag)
|
||||
|
||||
template <typename CharT>
|
||||
inline Maybe<bool>
|
||||
IsSafeModeRequested(int& aArgc, CharT* aArgv[],
|
||||
const SafeModeFlag aFlags = SafeModeFlag::Unset)
|
||||
{
|
||||
CheckArgFlag checkArgFlags = CheckArgFlag::CheckOSInt;
|
||||
if (aFlags & SafeModeFlag::Unset) {
|
||||
checkArgFlags |= CheckArgFlag::RemoveArg;
|
||||
}
|
||||
|
||||
ArgResult ar = CheckArg(aArgc, aArgv,
|
||||
GetLiteral<CharT, FlagLiteral::safemode>(),
|
||||
reinterpret_cast<const CharT**>(nullptr),
|
||||
checkArgFlags);
|
||||
if (ar == ARG_BAD) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
bool result = ar == ARG_FOUND;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// If the shift key is pressed and the ctrl and / or alt keys are not pressed
|
||||
// during startup, start in safe mode. GetKeyState returns a short and the high
|
||||
// order bit will be 1 if the key is pressed. By masking the returned short
|
||||
// with 0x8000 the result will be 0 if the key is not pressed and non-zero
|
||||
// otherwise.
|
||||
if ((GetKeyState(VK_SHIFT) & 0x8000) &&
|
||||
!(GetKeyState(VK_CONTROL) & 0x8000) &&
|
||||
!(GetKeyState(VK_MENU) & 0x8000) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (result && PolicyCheckBoolean(L"DisableSafeMode")) {
|
||||
result = false;
|
||||
}
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
if ((GetCurrentEventKeyModifiers() & optionKey) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
|
||||
result = true;
|
||||
}
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
// The Safe Mode Policy should not be enforced for the env var case
|
||||
// (used by updater and crash-recovery).
|
||||
if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
|
||||
result = true;
|
||||
if (aFlags & SafeModeFlag::Unset) {
|
||||
// unset the env variable
|
||||
SaveToEnv("MOZ_SAFE_MODE_RESTART=");
|
||||
}
|
||||
}
|
||||
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_SafeMode_h
|
|
@ -30,19 +30,13 @@ EXPORTS += [
|
|||
'nsIAppStartupNotifier.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'AutoSQLiteLifetime.h',
|
||||
'Bootstrap.h',
|
||||
'CmdLineAndEnvUtils.h',
|
||||
'SafeMode.h',
|
||||
]
|
||||
EXPORTS.mozilla += ['AutoSQLiteLifetime.h', 'Bootstrap.h']
|
||||
|
||||
if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
|
||||
EXPORTS += ['EventTracer.h']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
EXPORTS.mozilla += [
|
||||
'PolicyChecks.h',
|
||||
'WinDllServices.h',
|
||||
]
|
||||
SOURCES += [
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/IOInterposer.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryChecking.h"
|
||||
|
@ -233,7 +232,6 @@
|
|||
#endif
|
||||
|
||||
#include "mozilla/mozalloc_oom.h"
|
||||
#include "SafeMode.h"
|
||||
|
||||
extern uint32_t gRestartMode;
|
||||
extern void InstallSignalHandlers(const char *ProgramName);
|
||||
|
@ -308,6 +306,25 @@ using mozilla::dom::ContentParent;
|
|||
using mozilla::dom::ContentChild;
|
||||
using mozilla::intl::LocaleService;
|
||||
|
||||
// Save literal putenv string to environment variable.
|
||||
static void
|
||||
SaveToEnv(const char *putenv)
|
||||
{
|
||||
char *expr = strdup(putenv);
|
||||
if (expr)
|
||||
PR_SetEnv(expr);
|
||||
// We intentionally leak |expr| here since it is required by PR_SetEnv.
|
||||
MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(expr);
|
||||
}
|
||||
|
||||
// Tests that an environment variable exists and has a value
|
||||
static bool
|
||||
EnvHasValue(const char *name)
|
||||
{
|
||||
const char *val = PR_GetEnv(name);
|
||||
return (val && *val);
|
||||
}
|
||||
|
||||
// Save the given word to the specified environment variable.
|
||||
static void
|
||||
SaveWordToEnv(const char *name, const nsACString & word)
|
||||
|
@ -383,6 +400,22 @@ SaveFileToEnvIfUnset(const char *name, nsIFile *file)
|
|||
SaveFileToEnv(name, file);
|
||||
}
|
||||
|
||||
static bool
|
||||
strimatch(const char* lowerstr, const char* mixedstr)
|
||||
{
|
||||
while(*lowerstr) {
|
||||
if (!*mixedstr) return false; // mixedstr is shorter
|
||||
if (tolower(*mixedstr) != *lowerstr) return false; // no match
|
||||
|
||||
++lowerstr;
|
||||
++mixedstr;
|
||||
}
|
||||
|
||||
if (*mixedstr) return false; // lowerstr is shorter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool gIsExpectedExit = false;
|
||||
|
||||
void MozExpectedExit() {
|
||||
|
@ -449,22 +482,94 @@ enum RemoteResult {
|
|||
REMOTE_ARG_BAD = 2
|
||||
};
|
||||
|
||||
enum ArgResult {
|
||||
ARG_NONE = 0,
|
||||
ARG_FOUND = 1,
|
||||
ARG_BAD = 2 // you wanted a param, but there isn't one
|
||||
};
|
||||
|
||||
static void RemoveArg(char **argv)
|
||||
{
|
||||
do {
|
||||
*argv = *(argv + 1);
|
||||
++argv;
|
||||
} while (*argv);
|
||||
|
||||
--gArgc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a commandline flag. If the flag takes a parameter, the
|
||||
* parameter is returned in aParam. Flags may be in the form -arg or
|
||||
* --arg (or /arg on win32).
|
||||
*
|
||||
* @param aArg the parameter to check. Must be lowercase.
|
||||
* @param aCheckOSInt if true returns ARG_BAD if the osint argument is present
|
||||
* when aArg is also present.
|
||||
* @param aParam if non-null, the -arg <data> will be stored in this pointer.
|
||||
* This is *not* allocated, but rather a pointer to the argv data.
|
||||
* @param aFlags flags @see CheckArgFlag
|
||||
* @param aRemArg if true, the argument is removed from the gArgv array.
|
||||
*/
|
||||
static ArgResult
|
||||
CheckArg(const char* aArg, const char** aParam = nullptr,
|
||||
CheckArgFlag aFlags = CheckArgFlag::RemoveArg)
|
||||
CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullptr, bool aRemArg = true)
|
||||
{
|
||||
MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()");
|
||||
return CheckArg(gArgc, gArgv, aArg, aParam, aFlags);
|
||||
|
||||
char **curarg = gArgv + 1; // skip argv[0]
|
||||
ArgResult ar = ARG_NONE;
|
||||
|
||||
while (*curarg) {
|
||||
char *arg = curarg[0];
|
||||
|
||||
if (arg[0] == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| *arg == '/'
|
||||
#endif
|
||||
) {
|
||||
++arg;
|
||||
if (*arg == '-')
|
||||
++arg;
|
||||
|
||||
if (strimatch(aArg, arg)) {
|
||||
if (aRemArg)
|
||||
RemoveArg(curarg);
|
||||
else
|
||||
++curarg;
|
||||
if (!aParam) {
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*curarg) {
|
||||
if (**curarg == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| **curarg == '/'
|
||||
#endif
|
||||
)
|
||||
return ARG_BAD;
|
||||
|
||||
*aParam = *curarg;
|
||||
if (aRemArg)
|
||||
RemoveArg(curarg);
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
}
|
||||
return ARG_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
++curarg;
|
||||
}
|
||||
|
||||
if (aCheckOSInt && ar == ARG_FOUND) {
|
||||
ArgResult arOSInt = CheckArg("osint");
|
||||
if (arOSInt == ARG_FOUND) {
|
||||
ar = ARG_BAD;
|
||||
PR_fprintf(PR_STDERR, "Error: argument --osint is invalid\n");
|
||||
}
|
||||
}
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -477,7 +582,38 @@ CheckArg(const char* aArg, const char** aParam = nullptr,
|
|||
static ArgResult
|
||||
CheckArgExists(const char* aArg)
|
||||
{
|
||||
return CheckArg(aArg, nullptr, CheckArgFlag::None);
|
||||
char **curarg = gArgv + 1; // skip argv[0]
|
||||
while (*curarg) {
|
||||
char *arg = curarg[0];
|
||||
|
||||
if (arg[0] == '-'
|
||||
#if defined(XP_WIN)
|
||||
|| *arg == '/'
|
||||
#endif
|
||||
) {
|
||||
++arg;
|
||||
if (*arg == '-')
|
||||
++arg;
|
||||
|
||||
char delimiter = '=';
|
||||
#if defined(XP_WIN)
|
||||
delimiter = ':';
|
||||
#endif
|
||||
int i;
|
||||
for (i = 0; arg[i] && arg[i] != delimiter; i++) {}
|
||||
char tmp = arg[i];
|
||||
arg[i] = '\0';
|
||||
bool found = strimatch(aArg, arg);
|
||||
arg[i] = tmp;
|
||||
if (found) {
|
||||
return ARG_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
++curarg;
|
||||
}
|
||||
|
||||
return ARG_NONE;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
@ -1663,14 +1799,14 @@ ParseRemoteCommandLine(nsCString& program,
|
|||
{
|
||||
ArgResult ar;
|
||||
|
||||
ar = CheckArg("p", profile, CheckArgFlag::None);
|
||||
ar = CheckArg("p", false, profile, false);
|
||||
if (ar == ARG_BAD) {
|
||||
// Leave it to the normal command line handling to handle this situation.
|
||||
return REMOTE_NOT_FOUND;
|
||||
}
|
||||
|
||||
const char *temp = nullptr;
|
||||
ar = CheckArg("a", &temp, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("a", true, &temp);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -a requires an application name\n");
|
||||
return REMOTE_ARG_BAD;
|
||||
|
@ -1679,7 +1815,7 @@ ParseRemoteCommandLine(nsCString& program,
|
|||
program.Assign(temp);
|
||||
}
|
||||
|
||||
ar = CheckArg("u", username, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("u", true, username);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
|
||||
return REMOTE_ARG_BAD;
|
||||
|
@ -2186,7 +2322,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
*aResult = nullptr;
|
||||
*aStartOffline = false;
|
||||
|
||||
ar = CheckArg("offline", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("offline", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --offline is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2208,7 +2344,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
}
|
||||
|
||||
// reset-profile and migration args need to be checked before any profiles are chosen below.
|
||||
ar = CheckArg("reset-profile", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("reset-profile", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --reset-profile is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2217,7 +2353,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
gDoProfileReset = true;
|
||||
}
|
||||
|
||||
ar = CheckArg("migration", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("migration", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --migration is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2244,8 +2380,8 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
|
||||
// Clear out flags that we handled (or should have handled!) last startup.
|
||||
const char *dummy;
|
||||
CheckArg("p", &dummy);
|
||||
CheckArg("profile", &dummy);
|
||||
CheckArg("p", false, &dummy);
|
||||
CheckArg("profile", false, &dummy);
|
||||
CheckArg("profilemanager");
|
||||
|
||||
if (gDoProfileReset) {
|
||||
|
@ -2274,7 +2410,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
return NS_LockProfilePath(lf, localDir, nullptr, aResult);
|
||||
}
|
||||
|
||||
ar = CheckArg("profile", &arg, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("profile", true, &arg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --profile requires a path\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2308,7 +2444,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
return ProfileLockedDialog(lf, lf, unlocker, aNative, aResult);
|
||||
}
|
||||
|
||||
ar = CheckArg("createprofile", &arg, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("createprofile", true, &arg);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --createprofile requires a profile name\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2364,7 +2500,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
rv = aProfileSvc->GetProfileCount(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ar = CheckArg("p", &arg);
|
||||
ar = CheckArg("p", false, &arg);
|
||||
if (ar == ARG_BAD) {
|
||||
ar = CheckArg("osint");
|
||||
if (ar == ARG_FOUND) {
|
||||
|
@ -2429,7 +2565,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n
|
|||
}
|
||||
}
|
||||
|
||||
ar = CheckArg("profilemanager", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("profilemanager", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --profilemanager is invalid when argument --osint is specified\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -3025,6 +3161,33 @@ public:
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef XP_WIN
|
||||
namespace {
|
||||
|
||||
bool PolicyHasRegValue(HKEY aKey, LPCWSTR aName, DWORD* aValue)
|
||||
{
|
||||
DWORD len = sizeof(DWORD);
|
||||
LONG ret = ::RegGetValueW(aKey, L"SOFTWARE\\Policies\\Mozilla\\Firefox", aName,
|
||||
RRF_RT_DWORD, nullptr, aValue, &len);
|
||||
return ret == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
bool SafeModeBlockedByPolicy()
|
||||
{
|
||||
LPCTSTR policyName = L"DisableSafeMode";
|
||||
DWORD value;
|
||||
if (PolicyHasRegValue(HKEY_LOCAL_MACHINE, policyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
if (PolicyHasRegValue(HKEY_CURRENT_USER, policyName, &value)) {
|
||||
return value == 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
#endif // XP_WIN
|
||||
|
||||
#if defined(XP_UNIX) && !defined(ANDROID)
|
||||
static SmprintfPointer
|
||||
FormatUid(uid_t aId)
|
||||
|
@ -3203,7 +3366,7 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
|
||||
// Check for application.ini overrides
|
||||
const char* override = nullptr;
|
||||
ar = CheckArg("override", &override, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("override", true, &override);
|
||||
if (ar == ARG_BAD) {
|
||||
Output(true, "Incorrect number of arguments passed to --override");
|
||||
return 1;
|
||||
|
@ -3423,12 +3586,49 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
|
||||
gRestartArgv[gRestartArgc] = nullptr;
|
||||
|
||||
Maybe<bool> safeModeRequested = IsSafeModeRequested(gArgc, gArgv);
|
||||
if (!safeModeRequested) {
|
||||
|
||||
ar = CheckArg("safe-mode", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --safe-mode is invalid when argument --osint is specified\n");
|
||||
return 1;
|
||||
}
|
||||
if (ar == ARG_FOUND) {
|
||||
gSafeMode = true;
|
||||
}
|
||||
|
||||
gSafeMode = safeModeRequested.value();
|
||||
#ifdef XP_WIN
|
||||
// If the shift key is pressed and the ctrl and / or alt keys are not pressed
|
||||
// during startup start in safe mode. GetKeyState returns a short and the high
|
||||
// order bit will be 1 if the key is pressed. By masking the returned short
|
||||
// with 0x8000 the result will be 0 if the key is not pressed and non-zero
|
||||
// otherwise.
|
||||
if ((GetKeyState(VK_SHIFT) & 0x8000) &&
|
||||
!(GetKeyState(VK_CONTROL) & 0x8000) &&
|
||||
!(GetKeyState(VK_MENU) & 0x8000) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY")) {
|
||||
gSafeMode = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if ((GetCurrentEventKeyModifiers() & optionKey) &&
|
||||
!EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY"))
|
||||
gSafeMode = true;
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (gSafeMode && SafeModeBlockedByPolicy()) {
|
||||
gSafeMode = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// The Safe Mode Policy should not be enforced for the env var case
|
||||
// (used by updater and crash-recovery).
|
||||
if (EnvHasValue("MOZ_SAFE_MODE_RESTART")) {
|
||||
gSafeMode = true;
|
||||
// unset the env variable
|
||||
SaveToEnv("MOZ_SAFE_MODE_RESTART=");
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
{
|
||||
|
@ -3481,7 +3681,7 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
// Handle --no-remote and --new-instance command line arguments. Setup
|
||||
// the environment to better accommodate other components and various
|
||||
// restart scenarios.
|
||||
ar = CheckArg("no-remote", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("no-remote", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --no-remote is invalid when argument --osint is specified\n");
|
||||
return 1;
|
||||
|
@ -3490,7 +3690,7 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
SaveToEnv("MOZ_NO_REMOTE=1");
|
||||
}
|
||||
|
||||
ar = CheckArg("new-instance", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("new-instance", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --new-instance is invalid when argument --osint is specified\n");
|
||||
return 1;
|
||||
|
@ -3517,7 +3717,7 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
|||
NS_ENSURE_SUCCESS(rv, 1);
|
||||
|
||||
// Check for --register, which registers chrome and then exits immediately.
|
||||
ar = CheckArg("register", nullptr, CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
|
||||
ar = CheckArg("register", true);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --register is invalid when argument --osint is specified\n");
|
||||
return 1;
|
||||
|
@ -4053,7 +4253,7 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
|
|||
// to make sure that the maintenance service successfully launches the
|
||||
// callback application.
|
||||
const char *logFile = nullptr;
|
||||
if (ARG_FOUND == CheckArg("dump-args", &logFile)) {
|
||||
if (ARG_FOUND == CheckArg("dump-args", false, &logFile)) {
|
||||
FILE* logFP = fopen(logFile, "wb");
|
||||
if (logFP) {
|
||||
for (int i = 1; i < gRestartArgc; ++i) {
|
||||
|
@ -4908,7 +5108,7 @@ XRE_InitCommandLine(int aArgc, char* aArgv[])
|
|||
#endif
|
||||
|
||||
const char *path = nullptr;
|
||||
ArgResult ar = CheckArg("greomni", &path);
|
||||
ArgResult ar = CheckArg("greomni", false, &path);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --greomni requires a path argument\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -4924,7 +5124,7 @@ XRE_InitCommandLine(int aArgc, char* aArgv[])
|
|||
return rv;
|
||||
}
|
||||
|
||||
ar = CheckArg("appomni", &path);
|
||||
ar = CheckArg("appomni", false, &path);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument --appomni requires a path argument\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define nsWindowsRestart_cpp
|
||||
#endif
|
||||
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
#include <shellapi.h>
|
||||
|
@ -20,6 +19,135 @@
|
|||
#include <userenv.h>
|
||||
#pragma comment(lib, "userenv.lib")
|
||||
|
||||
/**
|
||||
* Get the length that the string will take and takes into account the
|
||||
* additional length if the string needs to be quoted and if characters need to
|
||||
* be escaped.
|
||||
*/
|
||||
static int ArgStrLen(const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
int i = wcslen(s);
|
||||
BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
i += 2; // initial and final duoblequote
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
i += backslashes + 1;
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy string "s" to string "d", quoting the argument as appropriate and
|
||||
* escaping doublequotes along with any backslashes that immediately precede
|
||||
* doublequotes.
|
||||
* The CRT parses this to retrieve the original argc/argv that we meant,
|
||||
* see STDARGV.C in the MSVC CRT sources.
|
||||
*
|
||||
* @return the end of the string
|
||||
*/
|
||||
static wchar_t* ArgToString(wchar_t *d, const wchar_t *s)
|
||||
{
|
||||
int backslashes = 0;
|
||||
BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
|
||||
// Only add doublequotes if the string contains a space or a tab
|
||||
BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // initial doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
if (hasDoubleQuote) {
|
||||
int i;
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
++backslashes;
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
// Escape the doublequote and all backslashes preceding the doublequote
|
||||
for (i = 0; i <= backslashes; ++i) {
|
||||
*d = '\\';
|
||||
++d;
|
||||
}
|
||||
}
|
||||
|
||||
backslashes = 0;
|
||||
}
|
||||
|
||||
*d = *s;
|
||||
++d; ++s;
|
||||
}
|
||||
} else {
|
||||
wcscpy(d, s);
|
||||
d += wcslen(s);
|
||||
}
|
||||
|
||||
if (addDoubleQuotes) {
|
||||
*d = '"'; // final doublequote
|
||||
++d;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a command line from a list of arguments. The returned
|
||||
* string is allocated with "malloc" and should be "free"d.
|
||||
*
|
||||
* argv is UTF8
|
||||
*/
|
||||
wchar_t*
|
||||
MakeCommandLine(int argc, wchar_t **argv)
|
||||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
|
||||
// The + 1 of the last argument handles the allocation for null termination
|
||||
for (i = 0; i < argc; ++i)
|
||||
len += ArgStrLen(argv[i]) + 1;
|
||||
|
||||
// Protect against callers that pass 0 arguments
|
||||
if (len == 0)
|
||||
len = 1;
|
||||
|
||||
wchar_t *s = (wchar_t*) malloc(len * sizeof(wchar_t));
|
||||
if (!s)
|
||||
return nullptr;
|
||||
|
||||
wchar_t *c = s;
|
||||
for (i = 0; i < argc; ++i) {
|
||||
c = ArgToString(c, argv[i]);
|
||||
if (i + 1 != argc) {
|
||||
*c = ' ';
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UTF8 to UTF16 without using the normal XPCOM goop, which we
|
||||
* can't link to updater.exe.
|
||||
|
@ -94,9 +222,10 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
HANDLE userToken,
|
||||
HANDLE *hProcess)
|
||||
{
|
||||
wchar_t *cl;
|
||||
BOOL ok;
|
||||
|
||||
mozilla::UniquePtr<wchar_t[]> cl(mozilla::MakeCommandLine(argc, argv));
|
||||
cl = MakeCommandLine(argc, argv);
|
||||
if (!cl) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -108,7 +237,7 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
|
||||
if (userToken == nullptr) {
|
||||
ok = CreateProcessW(exePath,
|
||||
cl.get(),
|
||||
cl,
|
||||
nullptr, // no special security attributes
|
||||
nullptr, // no special thread attributes
|
||||
FALSE, // don't inherit filehandles
|
||||
|
@ -127,7 +256,7 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
|
||||
ok = CreateProcessAsUserW(userToken,
|
||||
exePath,
|
||||
cl.get(),
|
||||
cl,
|
||||
nullptr, // no special security attributes
|
||||
nullptr, // no special thread attributes
|
||||
FALSE, // don't inherit filehandles
|
||||
|
@ -165,5 +294,7 @@ WinLaunchChild(const wchar_t *exePath,
|
|||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
free(cl);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -69,10 +69,10 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
wcscat(inCmdLineNew, inCmdLine);
|
||||
LPWSTR *inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc);
|
||||
|
||||
auto outCmdLine = mozilla::MakeCommandLine(inArgc - 1, inArgv + 1);
|
||||
wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine.get()) + 1) * sizeof(wchar_t));
|
||||
wchar_t *outCmdLine = MakeCommandLine(inArgc - 1, inArgv + 1);
|
||||
wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine) + 1) * sizeof(wchar_t));
|
||||
wcscpy(outCmdLineNew, DUMMY_ARG1);
|
||||
wcscat(outCmdLineNew, outCmdLine.get());
|
||||
wcscat(outCmdLineNew, outCmdLine);
|
||||
LPWSTR *outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc);
|
||||
|
||||
if (VERBOSE) {
|
||||
|
@ -80,7 +80,7 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
wprintf(L"Verbose Output\n");
|
||||
wprintf(L"--------------\n");
|
||||
wprintf(L"Input command line : >%s<\n", inCmdLine);
|
||||
wprintf(L"MakeComandLine output: >%s<\n", outCmdLine.get());
|
||||
wprintf(L"MakeComandLine output: >%s<\n", outCmdLine);
|
||||
wprintf(L"Expected command line: >%s<\n", compareCmdLine);
|
||||
|
||||
wprintf(L"input argc : %d\n", inArgc - 1);
|
||||
|
@ -107,6 +107,7 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -122,11 +123,12 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
isEqual = (wcscmp(outCmdLine.get(), compareCmdLine) == 0);
|
||||
isEqual = (wcscmp(outCmdLine, compareCmdLine) == 0);
|
||||
if (!isEqual) {
|
||||
wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n",
|
||||
passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum);
|
||||
|
@ -137,6 +139,7 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -153,6 +156,7 @@ verifyCmdLineCreation(wchar_t *inCmdLine,
|
|||
LocalFree(outArgv);
|
||||
free(inCmdLineNew);
|
||||
free(outCmdLineNew);
|
||||
free(outCmdLine);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче