toolkit/xre/nsWindowsRestart.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 // This file is not build directly. Instead, it is included in multiple
     6 // shared objects.
     8 #ifdef nsWindowsRestart_cpp
     9 #error "nsWindowsRestart.cpp is not a header file, and must only be included once."
    10 #else
    11 #define nsWindowsRestart_cpp
    12 #endif
    14 #include "nsUTF8Utils.h"
    16 #include <shellapi.h>
    18 // Needed for CreateEnvironmentBlock
    19 #include <userenv.h>
    20 #pragma comment(lib, "userenv.lib")
    22 /**
    23  * Get the length that the string will take and takes into account the
    24  * additional length if the string needs to be quoted and if characters need to
    25  * be escaped.
    26  */
    27 static int ArgStrLen(const wchar_t *s)
    28 {
    29   int backslashes = 0;
    30   int i = wcslen(s);
    31   BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
    32   // Only add doublequotes if the string contains a space or a tab
    33   BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
    35   if (addDoubleQuotes) {
    36     i += 2; // initial and final duoblequote
    37   }
    39   if (hasDoubleQuote) {
    40     while (*s) {
    41       if (*s == '\\') {
    42         ++backslashes;
    43       } else {
    44         if (*s == '"') {
    45           // Escape the doublequote and all backslashes preceding the doublequote
    46           i += backslashes + 1;
    47         }
    49         backslashes = 0;
    50       }
    52       ++s;
    53     }
    54   }
    56   return i;
    57 }
    59 /**
    60  * Copy string "s" to string "d", quoting the argument as appropriate and
    61  * escaping doublequotes along with any backslashes that immediately precede
    62  * doublequotes.
    63  * The CRT parses this to retrieve the original argc/argv that we meant,
    64  * see STDARGV.C in the MSVC CRT sources.
    65  *
    66  * @return the end of the string
    67  */
    68 static wchar_t* ArgToString(wchar_t *d, const wchar_t *s)
    69 {
    70   int backslashes = 0;
    71   BOOL hasDoubleQuote = wcschr(s, L'"') != nullptr;
    72   // Only add doublequotes if the string contains a space or a tab
    73   BOOL addDoubleQuotes = wcspbrk(s, L" \t") != nullptr;
    75   if (addDoubleQuotes) {
    76     *d = '"'; // initial doublequote
    77     ++d;
    78   }
    80   if (hasDoubleQuote) {
    81     int i;
    82     while (*s) {
    83       if (*s == '\\') {
    84         ++backslashes;
    85       } else {
    86         if (*s == '"') {
    87           // Escape the doublequote and all backslashes preceding the doublequote
    88           for (i = 0; i <= backslashes; ++i) {
    89             *d = '\\';
    90             ++d;
    91           }
    92         }
    94         backslashes = 0;
    95       }
    97       *d = *s;
    98       ++d; ++s;
    99     }
   100   } else {
   101     wcscpy(d, s);
   102     d += wcslen(s);
   103   }
   105   if (addDoubleQuotes) {
   106     *d = '"'; // final doublequote
   107     ++d;
   108   }
   110   return d;
   111 }
   113 /**
   114  * Creates a command line from a list of arguments. The returned
   115  * string is allocated with "malloc" and should be "free"d.
   116  *
   117  * argv is UTF8
   118  */
   119 wchar_t*
   120 MakeCommandLine(int argc, wchar_t **argv)
   121 {
   122   int i;
   123   int len = 0;
   125   // The + 1 of the last argument handles the allocation for null termination
   126   for (i = 0; i < argc; ++i)
   127     len += ArgStrLen(argv[i]) + 1;
   129   // Protect against callers that pass 0 arguments
   130   if (len == 0)
   131     len = 1;
   133   wchar_t *s = (wchar_t*) malloc(len * sizeof(wchar_t));
   134   if (!s)
   135     return nullptr;
   137   wchar_t *c = s;
   138   for (i = 0; i < argc; ++i) {
   139     c = ArgToString(c, argv[i]);
   140     if (i + 1 != argc) {
   141       *c = ' ';
   142       ++c;
   143     }
   144   }
   146   *c = '\0';
   148   return s;
   149 }
   151 /**
   152  * Convert UTF8 to UTF16 without using the normal XPCOM goop, which we
   153  * can't link to updater.exe.
   154  */
   155 static char16_t*
   156 AllocConvertUTF8toUTF16(const char *arg)
   157 {
   158   // UTF16 can't be longer in units than UTF8
   159   int len = strlen(arg);
   160   char16_t *s = new char16_t[(len + 1) * sizeof(char16_t)];
   161   if (!s)
   162     return nullptr;
   164   ConvertUTF8toUTF16 convert(s);
   165   convert.write(arg, len);
   166   convert.write_terminator();
   167   return s;
   168 }
   170 static void
   171 FreeAllocStrings(int argc, wchar_t **argv)
   172 {
   173   while (argc) {
   174     --argc;
   175     delete [] argv[argc];
   176   }
   178   delete [] argv;
   179 }
   183 /**
   184  * Launch a child process with the specified arguments.
   185  * @note argv[0] is ignored
   186  * @note The form of this function that takes char **argv expects UTF-8
   187  */
   189 BOOL
   190 WinLaunchChild(const wchar_t *exePath,
   191                int argc, wchar_t **argv,
   192                HANDLE userToken = nullptr,
   193                HANDLE *hProcess = nullptr);
   195 BOOL
   196 WinLaunchChild(const wchar_t *exePath,
   197                int argc, char **argv,
   198                HANDLE userToken,
   199                HANDLE *hProcess)
   200 {
   201   wchar_t** argvConverted = new wchar_t*[argc];
   202   if (!argvConverted)
   203     return FALSE;
   205   for (int i = 0; i < argc; ++i) {
   206       argvConverted[i] = reinterpret_cast<wchar_t*>(AllocConvertUTF8toUTF16(argv[i]));
   207     if (!argvConverted[i]) {
   208       FreeAllocStrings(i, argvConverted);
   209       return FALSE;
   210     }
   211   }
   213   BOOL ok = WinLaunchChild(exePath, argc, argvConverted, userToken, hProcess);
   214   FreeAllocStrings(argc, argvConverted);
   215   return ok;
   216 }
   218 BOOL
   219 WinLaunchChild(const wchar_t *exePath,
   220                int argc, 
   221                wchar_t **argv,
   222                HANDLE userToken,
   223                HANDLE *hProcess)
   224 {
   225   wchar_t *cl;
   226   BOOL ok;
   228   cl = MakeCommandLine(argc, argv);
   229   if (!cl) {
   230     return FALSE;
   231   }
   233   STARTUPINFOW si = {0};
   234   si.cb = sizeof(STARTUPINFOW);
   235   si.lpDesktop = L"winsta0\\Default";
   236   PROCESS_INFORMATION pi = {0};
   238   if (userToken == nullptr) {
   239     ok = CreateProcessW(exePath,
   240                         cl,
   241                         nullptr,  // no special security attributes
   242                         nullptr,  // no special thread attributes
   243                         FALSE, // don't inherit filehandles
   244                         0,     // creation flags
   245                         nullptr,  // inherit my environment
   246                         nullptr,  // use my current directory
   247                         &si,
   248                         &pi);
   249   } else {
   250     // Create an environment block for the process we're about to start using
   251     // the user's token.
   252     LPVOID environmentBlock = nullptr;
   253     if (!CreateEnvironmentBlock(&environmentBlock, userToken, TRUE)) {
   254       environmentBlock = nullptr;
   255     }
   257     ok = CreateProcessAsUserW(userToken, 
   258                               exePath,
   259                               cl,
   260                               nullptr,  // no special security attributes
   261                               nullptr,  // no special thread attributes
   262                               FALSE,    // don't inherit filehandles
   263                               0,        // creation flags
   264                               environmentBlock,
   265                               nullptr,  // use my current directory
   266                               &si,
   267                               &pi);
   269     if (environmentBlock) {
   270       DestroyEnvironmentBlock(environmentBlock);
   271     }
   272   }
   274   if (ok) {
   275     if (hProcess) {
   276       *hProcess = pi.hProcess; // the caller now owns the HANDLE
   277     } else {
   278       CloseHandle(pi.hProcess);
   279     }
   280     CloseHandle(pi.hThread);
   281   } else {
   282     LPVOID lpMsgBuf = nullptr;
   283     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
   284                   FORMAT_MESSAGE_FROM_SYSTEM |
   285                   FORMAT_MESSAGE_IGNORE_INSERTS,
   286                   nullptr,
   287                   GetLastError(),
   288                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
   289                   (LPTSTR) &lpMsgBuf,
   290                   0,
   291                   nullptr);
   292     wprintf(L"Error restarting: %s\n", lpMsgBuf ? lpMsgBuf : L"(null)");
   293     if (lpMsgBuf)
   294       LocalFree(lpMsgBuf);
   295   }
   297   free(cl);
   299   return ok;
   300 }

mercurial