Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
nsWindowsRestart.cpp File Reference
#include <shellapi.h>

Go to the source code of this file.

Defines

#define nsWindowsRestart_cpp
#define ERROR_ELEVATION_REQUIRED   740L

Functions

 BOOL (WINAPI *pCreateProcessWithTokenW)(HANDLE
static int QuotedStrLen (const char *s)
 Get the length that the string will take when it is quoted.
static char * QuoteString (char *d, const char *s)
 Copy string "s" to string "d", quoting and escaping all double quotes.
static char * MakeCommandLine (int argc, char **argv)
 Create a quoted command from a list of arguments.
static PRUnicharAllocConvertAToW (const char *buf)
 alloc and convert multibyte char to unicode char
static BOOL LaunchAsNormalUser (const char *exePath, char *cl)
 Launch a child process without elevated privilege.
BOOL WinLaunchChild (const char *exePath, int argc, char **argv, int needElevation)
 Launch a child process with the specified arguments.

Variables

 DWORD
 LPCWSTR
 LPWSTR
 LPVOID
 LPSTARTUPINFOW
 LPPROCESS_INFORMATION
 LPSECURITY_ATTRIBUTES
 SECURITY_IMPERSONATION_LEVEL
 TOKEN_TYPE
 PHANDLE

Define Documentation

Definition at line 50 of file nsWindowsRestart.cpp.

Definition at line 44 of file nsWindowsRestart.cpp.


Function Documentation

static PRUnichar* AllocConvertAToW ( const char *  buf) [static]

alloc and convert multibyte char to unicode char

Definition at line 149 of file nsWindowsRestart.cpp.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

BOOL ( WINAPI *  pCreateProcessWithTokenW)
static BOOL LaunchAsNormalUser ( const char *  exePath,
char *  cl 
) [static]

Launch a child process without elevated privilege.

Definition at line 166 of file nsWindowsRestart.cpp.

{
  if (!pCreateProcessWithTokenW) {
    // IsUserAnAdmin is not present on Win9x and not exported by name on Win2k
    *(FARPROC *)&pIsUserAnAdmin =
        GetProcAddress(GetModuleHandle("shell32.dll"), "IsUserAnAdmin");

    // CreateProcessWithTokenW is not present on WinXP or earlier
    *(FARPROC *)&pCreateProcessWithTokenW =
        GetProcAddress(GetModuleHandle("advapi32.dll"),
                       "CreateProcessWithTokenW");

    if (!pCreateProcessWithTokenW)
      return FALSE;

    // DuplicateTokenEx is not present on WinME and Win9x.
    *(FARPROC *)&pDuplicateTokenEx =
        GetProcAddress(GetModuleHandle("advapi32.dll"), "DuplicateTokenEx");

    if (!pDuplicateTokenEx)
      return FALSE;
  }

  // do nothing here if we are not elevated or IsUserAnAdmin is not present.
  if (!pIsUserAnAdmin || pIsUserAnAdmin && !pIsUserAnAdmin())
    return FALSE;

  // borrow the shell token to drop the privilege
  HWND hwndShell = FindWindow("Progman", NULL);
  DWORD dwProcessId;
  GetWindowThreadProcessId(hwndShell, &dwProcessId);

  HANDLE hProcessShell = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId);
  if (!hProcessShell)
    return FALSE;

  HANDLE hTokenShell;
  BOOL ok = OpenProcessToken(hProcessShell, MAXIMUM_ALLOWED, &hTokenShell);
  CloseHandle(hProcessShell);
  if (!ok)
    return FALSE;

  HANDLE hNewToken;
  ok = pDuplicateTokenEx(hTokenShell,
                         MAXIMUM_ALLOWED,
                         NULL,
                         SecurityDelegation,
                         TokenPrimary,
                         &hNewToken);
  CloseHandle(hTokenShell);
  if (!ok)
    return FALSE;

  STARTUPINFOW si = {sizeof(si), 0};
  PROCESS_INFORMATION pi = {0};

  PRUnichar *exePathW = AllocConvertAToW(exePath);
  PRUnichar *clW = AllocConvertAToW(cl);
  ok = exePathW && clW;
  if (ok) {
    ok = pCreateProcessWithTokenW(hNewToken,
                                  0,    // profile is already loaded
                                  exePathW,
                                  clW,
                                  0,    // No special process creation flags
                                  NULL, // inherit my environment
                                  NULL, // use my current directory
                                  &si,
                                  &pi);
  }
  free(exePathW);
  free(clW);
  CloseHandle(hNewToken);
  if (!ok)
    return FALSE;

  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* MakeCommandLine ( int  argc,
char **  argv 
) [static]

Create a quoted command from a list of arguments.

The returned string is allocated with "malloc" and should be "free"d.

Definition at line 121 of file nsWindowsRestart.cpp.

{
  int i;
  int len = 1; // null-termination

  for (i = 0; i < argc; ++i)
    len += QuotedStrLen(argv[i]) + 1;

  char *s = (char*) malloc(len);
  if (!s)
    return NULL;

  char *c = s;
  for (i = 0; i < argc; ++i) {
    c = QuoteString(c, argv[i]);
    *c = ' ';
    ++c;
  }

  *c = '\0';

  return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int QuotedStrLen ( const char *  s) [static]

Get the length that the string will take when it is quoted.

Definition at line 75 of file nsWindowsRestart.cpp.

{
  int i = 2; // initial and final quote
  while (*s) {
    if (*s == '"') {
      ++i;
    }

    ++i; ++s;
  }
  return i;
}

Here is the caller graph for this function:

static char* QuoteString ( char *  d,
const char *  s 
) [static]

Copy string "s" to string "d", quoting and escaping all double quotes.

The CRT parses this to retrieve the original argc/argv that we meant, see STDARGV.C in the MSVC6 CRT sources.

Returns:
the end of the string

Definition at line 95 of file nsWindowsRestart.cpp.

{
  *d = '"';
  ++d;

  while (*s) {
    *d = *s;
    if (*s == '"') {
      ++d;
      *d = '"';
    }

    ++d; ++s;
  }

  *d = '"';
  ++d;

  return d;
}

Here is the caller graph for this function:

BOOL WinLaunchChild ( const char *  exePath,
int  argc,
char **  argv,
int  needElevation 
)

Launch a child process with the specified arguments.

Parameters:
needElevation1:need elevation, -1:want to drop priv, 0:don't care
Note:
argv[0] is ignored

Definition at line 254 of file nsWindowsRestart.cpp.

{
  char *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;
    free(cl);
    return ok;
  }

  cl = MakeCommandLine(argc, argv);
  if (!cl)
    return FALSE;

  if (needElevation < 0) {
    // try to launch as a normal user first
    ok = LaunchAsNormalUser(exePath, cl);
    // if it fails, fallback to normal launching
    if (!ok)
      needElevation = 0;
  }
  if (needElevation == 0) {
    STARTUPINFO si = {sizeof(si), 0};
    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);

    if (ok) {
      CloseHandle(pi.hProcess);
      CloseHandle(pi.hThread);
    }
  }

  free(cl);

  return ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 54 of file nsWindowsRestart.cpp.

Definition at line 54 of file nsWindowsRestart.cpp.

Definition at line 54 of file nsWindowsRestart.cpp.

Definition at line 66 of file nsWindowsRestart.cpp.

Definition at line 54 of file nsWindowsRestart.cpp.

Definition at line 54 of file nsWindowsRestart.cpp.

Definition at line 54 of file nsWindowsRestart.cpp.

Definition at line 66 of file nsWindowsRestart.cpp.

Definition at line 66 of file nsWindowsRestart.cpp.

Definition at line 66 of file nsWindowsRestart.cpp.