process-win.cpp revision 9c0e21f5aec1d320af6cb8baa5f17a528cb7ee62
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/* $Id$ */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** @file
c11f819521ac699ff05361aa39f2a6e7342aacaevboxsync * IPRT - Process, Windows.
c11f819521ac699ff05361aa39f2a6e7342aacaevboxsync */
c11f819521ac699ff05361aa39f2a6e7342aacaevboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Copyright (C) 2006-2010 Oracle Corporation
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
ef0576b151f3ad77ecefe5f4641d5d7f0caedafcvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * available from http://www.virtualbox.org. This file is free software;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * General Public License (GPL) as published by the Free Software
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The contents of this file may alternatively be used under the terms
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * of the Common Development and Distribution License Version 1.0
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution, in which case the provisions of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * CDDL are applicable instead of those of the GPL.
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync *
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync * You may elect to license modified versions of this file under the
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync * terms and conditions of either the GPL or the CDDL or both.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync/*******************************************************************************
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync* Header Files *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync#define LOG_GROUP RTLOGGROUP_PROCESS
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <iprt/asm.h> /* hack */
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <Userenv.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <Windows.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <tlhelp32.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <process.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <errno.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <Strsafe.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <iprt/process.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include "internal/iprt.h"
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync#include <iprt/assert.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/critsect.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/file.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/err.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/env.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/getopt.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/initterm.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/ldr.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/mem.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/once.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/pipe.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/string.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/socket.h>
9ee86050975427444ed8f68e502d2aa9ddcbff1cvboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
c0fa6fe4a52eff9785fdf7a79cf3bc149eecd937vboxsync/*******************************************************************************
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync* Structures and Typedefs *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsynctypedef WINADVAPI BOOL WINAPI FNCREATEPROCESSWITHLOGON(LPCWSTR,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPCWSTR,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPCWSTR,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync DWORD,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPCWSTR,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPWSTR,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync DWORD,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPVOID,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPCWSTR,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPSTARTUPINFOW,
25866675a2cd68211a7a90bc0abd32c40235d07dvboxsync LPPROCESS_INFORMATION);
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsynctypedef FNCREATEPROCESSWITHLOGON *PFNCREATEPROCESSWITHLOGON;
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsynctypedef DWORD WINAPI FNWTSGETACTIVECONSOLESESSIONID();
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsynctypedef FNWTSGETACTIVECONSOLESESSIONID *PFNWTSGETACTIVECONSOLESESSIONID;
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsynctypedef HANDLE WINAPI FNCREATETOOLHELP32SNAPSHOT(DWORD, DWORD);
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsynctypedef FNCREATETOOLHELP32SNAPSHOT *PFNCREATETOOLHELP32SNAPSHOT;
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsynctypedef BOOL WINAPI FNPROCESS32FIRST(HANDLE, LPPROCESSENTRY32);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef FNPROCESS32FIRST *PFNPROCESS32FIRST;
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync
1c14b7525891c8c3bbc9767497792894596a00f7vboxsynctypedef BOOL WINAPI FNPROCESS32NEXT(HANDLE, LPPROCESSENTRY32);
1c14b7525891c8c3bbc9767497792894596a00f7vboxsynctypedef FNPROCESS32NEXT *PFNPROCESS32NEXT;
1c14b7525891c8c3bbc9767497792894596a00f7vboxsync
152d786a21a506f9e2a2e16ba8efdc2bcae133abvboxsynctypedef BOOL WINAPI FNENUMPROCESSES(DWORD*, DWORD, DWORD*);
152d786a21a506f9e2a2e16ba8efdc2bcae133abvboxsynctypedef FNENUMPROCESSES *PFNENUMPROCESSES;
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsynctypedef DWORD FNGETMODULEBASENAME(HANDLE, HMODULE, LPTSTR, DWORD);
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsynctypedef FNGETMODULEBASENAME *PFNGETMODULEBASENAME;
1c14b7525891c8c3bbc9767497792894596a00f7vboxsync
1c14b7525891c8c3bbc9767497792894596a00f7vboxsynctypedef BOOL WINAPI FNCREATEENVIRONMENTBLOCK(LPVOID *, HANDLE, BOOL);
1c14b7525891c8c3bbc9767497792894596a00f7vboxsynctypedef FNCREATEENVIRONMENTBLOCK *PFNCREATEENVIRONMENTBLOCK;
1c14b7525891c8c3bbc9767497792894596a00f7vboxsync
f11eaffbbd9153a62d2c6eb3ec1810947c956802vboxsynctypedef BOOL WINAPI FNPFNDESTROYENVIRONMENTBLOCK(LPVOID);
f11eaffbbd9153a62d2c6eb3ec1810947c956802vboxsynctypedef FNPFNDESTROYENVIRONMENTBLOCK *PFNPFNDESTROYENVIRONMENTBLOCK;
9ee86050975427444ed8f68e502d2aa9ddcbff1cvboxsync
f11eaffbbd9153a62d2c6eb3ec1810947c956802vboxsynctypedef BOOL WINAPI FNLOADUSERPROFILEW(HANDLE, LPPROFILEINFOW);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef FNLOADUSERPROFILEW *PFNLOADUSERPROFILEW;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef BOOL WINAPI FNUNLOADUSERPROFILE(HANDLE, HANDLE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsynctypedef FNUNLOADUSERPROFILE *PFNUNLOADUSERPROFILE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*******************************************************************************
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync* Global Variables *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync*******************************************************************************/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Init once structure. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic RTONCE g_rtProcWinInitOnce = RTONCE_INITIALIZER;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Critical section protecting the process array. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic RTCRITSECT g_CritSect;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** The number of processes in the array. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic uint32_t g_cProcesses;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** The current allocation size. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic uint32_t g_cProcessesAlloc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Array containing the live or non-reaped child processes. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic struct RTPROCWINENTRY
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The process ID. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ULONG_PTR pid;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** The process handle. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hProcess;
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync} *g_paProcesses;
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync/**
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync * Clean up the globals.
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param enmReason Ignored.
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync * @param iStatus Ignored.
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync * @param pvUser Ignored.
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync */
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsyncstatic DECLCALLBACK(void) rtProcWinTerm(RTTERMREASON enmReason, int32_t iStatus, void *pvUser)
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync{
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync NOREF(pvUser); NOREF(iStatus); NOREF(enmReason);
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync
152d786a21a506f9e2a2e16ba8efdc2bcae133abvboxsync RTCritSectDelete(&g_CritSect);
152d786a21a506f9e2a2e16ba8efdc2bcae133abvboxsync
152d786a21a506f9e2a2e16ba8efdc2bcae133abvboxsync size_t i = g_cProcesses;
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync while (i-- > 0)
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync {
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync CloseHandle(g_paProcesses[i].hProcess);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync g_paProcesses[i].hProcess = NULL;
6308f6770d7f8fb842b437338e31554e913e6773vboxsync }
6308f6770d7f8fb842b437338e31554e913e6773vboxsync RTMemFree(g_paProcesses);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_paProcesses = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_cProcesses = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_cProcessesAlloc = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Initialize the globals.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns IPRT status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pvUser1 Ignored.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pvUser2 Ignored.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
6308f6770d7f8fb842b437338e31554e913e6773vboxsyncstatic DECLCALLBACK(int32_t) rtProcWinInitOnce(void *pvUser1, void *pvUser2)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NOREF(pvUser1); NOREF(pvUser2);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_cProcesses = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_cProcessesAlloc = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_paProcesses = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTCritSectInit(&g_CritSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo init once, terminate once - this is a generic thing which should
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * have some kind of static and simpler setup! */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTTermRegisterCallback(rtProcWinTerm, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectDelete(&g_CritSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Gets the process handle for a process from g_paProcesses.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns Process handle if found, NULL if not.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pid The process to remove (pid).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic HANDLE rtProcWinFindPid(RTPROCESS pid)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hProcess = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectEnter(&g_CritSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t i = g_cProcesses;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (i-- > 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_paProcesses[i].pid == pid)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync hProcess = g_paProcesses[i].hProcess;
267957dcacbf753410d79dc1ef9fc0834131ddcdvboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectLeave(&g_CritSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return hProcess;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Removes a process from g_paProcesses and closes the process handle.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pid The process to remove (pid).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void rtProcWinRemovePid(RTPROCESS pid)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectEnter(&g_CritSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t i = g_cProcesses;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (i-- > 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_paProcesses[i].pid == pid)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hProcess = g_paProcesses[i].hProcess;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_cProcesses--;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t cToMove = g_cProcesses - i;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (cToMove)
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync memmove(&g_paProcesses[i], &g_paProcesses[i + 1], cToMove * sizeof(g_paProcesses[0]));
6308f6770d7f8fb842b437338e31554e913e6773vboxsync
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync RTCritSectLeave(&g_CritSect);
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync CloseHandle(hProcess);
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync return;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync }
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync RTCritSectLeave(&g_CritSect);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync}
6308f6770d7f8fb842b437338e31554e913e6773vboxsync
6308f6770d7f8fb842b437338e31554e913e6773vboxsync
6308f6770d7f8fb842b437338e31554e913e6773vboxsync/**
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync * Adds a process to g_paProcesses.
6308f6770d7f8fb842b437338e31554e913e6773vboxsync *
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync * @returns IPRT status code.
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync * @param pid The process id.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param hProcess The process handle.
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync */
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsyncstatic int rtProcWinAddPid(RTPROCESS pid, HANDLE hProcess)
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync{
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync RTCritSectEnter(&g_CritSect);
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync uint32_t i = g_cProcesses;
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync if (i >= g_cProcessesAlloc)
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync {
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync void *pvNew = RTMemRealloc(g_paProcesses, (i + 16) * sizeof(g_paProcesses[0]));
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync if (RT_UNLIKELY(!pvNew))
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync {
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync RTCritSectLeave(&g_CritSect);
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync return VERR_NO_MEMORY;
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync }
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync g_paProcesses = (struct RTPROCWINENTRY *)pvNew;
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync g_cProcessesAlloc = i + 16;
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync }
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync g_paProcesses[i].pid = pid;
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync g_paProcesses[i].hProcess = hProcess;
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync g_cProcesses = i + 1;
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync RTCritSectLeave(&g_CritSect);
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync return VINF_SUCCESS;
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync}
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsyncRTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync{
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync return RTProcCreateEx(pszExec, papszArgs, Env, fFlags,
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync NULL, NULL, NULL, /* standard handles */
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync NULL /*pszAsUser*/, NULL /* pszPassword*/,
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync pProcess);
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync}
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync
6308f6770d7f8fb842b437338e31554e913e6773vboxsync/**
b32cbfd89d5d933a6c86fc4d24ffae4d27976af3vboxsync * Map some important or much used Windows error codes
267957dcacbf753410d79dc1ef9fc0834131ddcdvboxsync * to our error codes.
267957dcacbf753410d79dc1ef9fc0834131ddcdvboxsync *
b32cbfd89d5d933a6c86fc4d24ffae4d27976af3vboxsync * @return Mapped IPRT status code.
b32cbfd89d5d933a6c86fc4d24ffae4d27976af3vboxsync * @param dwError Windows error code to map to IPRT code.
b32cbfd89d5d933a6c86fc4d24ffae4d27976af3vboxsync */
b32cbfd89d5d933a6c86fc4d24ffae4d27976af3vboxsyncstatic int rtProcMapErrorCodes(DWORD dwError)
b32cbfd89d5d933a6c86fc4d24ffae4d27976af3vboxsync{
6308f6770d7f8fb842b437338e31554e913e6773vboxsync int rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync switch (dwError)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case ERROR_NOACCESS:
6308f6770d7f8fb842b437338e31554e913e6773vboxsync case ERROR_PRIVILEGE_NOT_HELD:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_PERMISSION_DENIED;
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync break;
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync
3b5486d99a3b391015873e5524bb1974d6dd3935vboxsync case ERROR_PASSWORD_EXPIRED:
3b5486d99a3b391015873e5524bb1974d6dd3935vboxsync case ERROR_ACCOUNT_RESTRICTION: /* See: http://support.microsoft.com/kb/303846/ */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case ERROR_PASSWORD_RESTRICTION:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_AUTHENTICATION_FAILURE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync default:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Could trigger a debug assertion! */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync rc = RTErrConvertFromWin32(dwError);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync }
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
6308f6770d7f8fb842b437338e31554e913e6773vboxsync
6308f6770d7f8fb842b437338e31554e913e6773vboxsync/**
6308f6770d7f8fb842b437338e31554e913e6773vboxsync * Get the process token (not the process handle like the name might indicate)
6308f6770d7f8fb842b437338e31554e913e6773vboxsync * of the process indicated by @a dwPID if the @a pSID matches.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
824104c3b60b9c8d5c03c40658e33ecd6c4fa9e8vboxsync * @returns IPRT status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param dwPID The process identifier.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pSID The secure identifier of the user.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param phToken Where to return the token handle - duplicate,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * caller closes it on success.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int rtProcGetProcessHandle(DWORD dwPID, PSID pSID, PHANDLE phToken)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
6308f6770d7f8fb842b437338e31554e913e6773vboxsync AssertPtr(pSID);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync AssertPtr(phToken);
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync DWORD dwErr;
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync BOOL fRc;
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync bool fFound = false;
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync HANDLE hProc = OpenProcess(MAXIMUM_ALLOWED, TRUE, dwPID);
a5d319fc6b17a28a8d6738e6f872d66244601cebvboxsync if (hProc != NULL)
6308f6770d7f8fb842b437338e31554e913e6773vboxsync {
6308f6770d7f8fb842b437338e31554e913e6773vboxsync HANDLE hTokenProc;
6308f6770d7f8fb842b437338e31554e913e6773vboxsync fRc = OpenProcessToken(hProc,
6308f6770d7f8fb842b437338e31554e913e6773vboxsync TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE
6308f6770d7f8fb842b437338e31554e913e6773vboxsync | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
6308f6770d7f8fb842b437338e31554e913e6773vboxsync &hTokenProc);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync if (fRc)
6308f6770d7f8fb842b437338e31554e913e6773vboxsync {
6308f6770d7f8fb842b437338e31554e913e6773vboxsync DWORD dwSize = 0;
6308f6770d7f8fb842b437338e31554e913e6773vboxsync fRc = GetTokenInformation(hTokenProc, TokenUser, NULL, 0, &dwSize);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync if (!fRc)
6308f6770d7f8fb842b437338e31554e913e6773vboxsync dwErr = GetLastError();
6308f6770d7f8fb842b437338e31554e913e6773vboxsync if ( !fRc
6308f6770d7f8fb842b437338e31554e913e6773vboxsync && dwErr == ERROR_INSUFFICIENT_BUFFER
6308f6770d7f8fb842b437338e31554e913e6773vboxsync && dwSize > 0)
6308f6770d7f8fb842b437338e31554e913e6773vboxsync {
6308f6770d7f8fb842b437338e31554e913e6773vboxsync PTOKEN_USER pTokenUser = (PTOKEN_USER)RTMemAlloc(dwSize);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync AssertPtrReturn(pTokenUser, VERR_NO_MEMORY);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync RT_ZERO(*pTokenUser);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync if ( GetTokenInformation(hTokenProc,
6308f6770d7f8fb842b437338e31554e913e6773vboxsync TokenUser,
6308f6770d7f8fb842b437338e31554e913e6773vboxsync (LPVOID)pTokenUser,
6308f6770d7f8fb842b437338e31554e913e6773vboxsync dwSize,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &dwSize))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( IsValidSid(pTokenUser->User.Sid)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && EqualSid(pTokenUser->User.Sid, pSID))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (DuplicateTokenEx(hTokenProc, MAXIMUM_ALLOWED,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, SecurityIdentification, TokenPrimary, phToken))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * So we found the process instance which belongs to the user we want to
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * to run our new process under. This duplicated token will be used for
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * the actual CreateProcessAsUserW() call then.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync fFound = true;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync }
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync else
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync dwErr = GetLastError();
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync }
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemFree(pTokenUser);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync CloseHandle(hTokenProc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync CloseHandle(hProc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (fFound)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (dwErr != NO_ERROR)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return RTErrConvertFromWin32(dwErr);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VERR_NOT_FOUND; /* No error occurred, but we didn't find the right process. */
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Finds a one of the processes in @a papszNames running with user @a pSID and
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * returns a duplicate handle to its token.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @returns Success indicator.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param papszNames The process candidates, in prioritized order.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pSID The secure identifier of the user.
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync * @param phToken Where to return the token handle - duplicate,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * caller closes it on success.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic bool rtProcFindProcessByName(const char * const *papszNames, PSID pSID, PHANDLE phToken)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(papszNames);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(pSID);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtr(phToken);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD dwErr = NO_ERROR;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool fFound = false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * On modern systems (W2K+) try the Toolhelp32 API first; this is more stable
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * and reliable. Fallback to EnumProcess on NT4.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync RTLDRMOD hKernel32;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTLdrLoad("Kernel32.dll", &hKernel32);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PFNCREATETOOLHELP32SNAPSHOT pfnCreateToolhelp32Snapshot;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrGetSymbol(hKernel32, "CreateToolhelp32Snapshot", (void**)&pfnCreateToolhelp32Snapshot);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PFNPROCESS32FIRST pfnProcess32First;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrGetSymbol(hKernel32, "Process32First", (void**)&pfnProcess32First);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync PFNPROCESS32NEXT pfnProcess32Next;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync rc = RTLdrGetSymbol(hKernel32, "Process32Next", (void**)&pfnProcess32Next);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hSnap = pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hSnap != INVALID_HANDLE_VALUE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (size_t i = 0; papszNames[i] && !fFound; i++)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
4ae37290cb50a39ea45112540ac89f0b12b172b8vboxsync PROCESSENTRY32 procEntry;
4ae37290cb50a39ea45112540ac89f0b12b172b8vboxsync procEntry.dwSize = sizeof(PROCESSENTRY32);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pfnProcess32First(hSnap, &procEntry))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync do
46a78ba0ce1d037aaed54f3df16ebd9c0b70ed39vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if ( _stricmp(procEntry.szExeFile, papszNames[i]) == 0
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync && RT_SUCCESS(rtProcGetProcessHandle(procEntry.th32ProcessID, pSID, phToken)))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync fFound = true;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync break;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync } while (pfnProcess32Next(hSnap, &procEntry));
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync else /* Process32First */
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync dwErr = GetLastError();
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync if (FAILED(dwErr))
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync break;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync CloseHandle(hSnap);
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync else /* hSnap == INVALID_HANDLE_VALUE */
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync dwErr = GetLastError();
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync else /* CreateToolhelp32Snapshot / Toolhelp32 API not available. */
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync /*
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync * NT4 needs a copy of "PSAPI.dll" (redistributed by Microsoft and not
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync * part of the OS) in order to get a lookup. If we don't have this DLL
b6a171211dc56d6a805da5f43dcb6b3eb73c7e8avboxsync * we are not able to get a token and therefore no UI will be visible.
b6a171211dc56d6a805da5f43dcb6b3eb73c7e8avboxsync */
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync RTLDRMOD hPSAPI;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync int rc = RTLdrLoad("PSAPI.dll", &hPSAPI);
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if (RT_SUCCESS(rc))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync PFNENUMPROCESSES pfnEnumProcesses;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync rc = RTLdrGetSymbol(hPSAPI, "EnumProcesses", (void**)&pfnEnumProcesses);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync PFNGETMODULEBASENAME pfnGetModuleBaseName;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync rc = RTLdrGetSymbol(hPSAPI, "GetModuleBaseName", (void**)&pfnGetModuleBaseName);
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if (RT_SUCCESS(rc))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync /** @todo Retry if pBytesReturned equals cbBytes! */
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync DWORD adwPIDs[4096]; /* Should be sufficient for now. */
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync DWORD cbBytes = 0;
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync if (pfnEnumProcesses(adwPIDs, sizeof(adwPIDs), &cbBytes))
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync {
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync for (size_t i = 0; papszNames[i] && !fFound; i++)
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync {
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync for (DWORD dwIdx = 0; dwIdx < cbBytes/sizeof(DWORD) && !fFound; dwIdx++)
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync {
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync FALSE, adwPIDs[dwIdx]);
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if (hProc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync char *pszProcName = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD dwSize = 128;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync do
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemRealloc(pszProcName, dwSize);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pfnGetModuleBaseName(hProc, 0, pszProcName, dwSize) == dwSize)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwSize += 128;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (dwSize > _4K) /* Play safe. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pszProcName)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( _stricmp(pszProcName, papszNames[i]) == 0
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && RT_SUCCESS(rtProcGetProcessHandle(adwPIDs[dwIdx], pSID, phToken)))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync fFound = true;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pszProcName)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTStrFree(pszProcName);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync CloseHandle(hProc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync else
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
6308f6770d7f8fb842b437338e31554e913e6773vboxsync RTLdrClose(hKernel32);
6da7ae3144a7be1443dd37052b24370bf210fda1vboxsync }
6308f6770d7f8fb842b437338e31554e913e6773vboxsync Assert(dwErr == NO_ERROR);
c0fa6fe4a52eff9785fdf7a79cf3bc149eecd937vboxsync return fFound;
c0fa6fe4a52eff9785fdf7a79cf3bc149eecd937vboxsync}
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync/**
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync * Logs on a specified user and returns its primary token.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @return int
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pwszUser User name.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pwszPassword Password.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pwszDomain Domain (not used at the moment).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param phToken Pointer to store the logon token.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int rtProcUserLogon(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain, HANDLE *phToken)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo Add domain support! */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync BOOL fRc = LogonUserW(pwszUser,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Because we have to deal with http://support.microsoft.com/kb/245683
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * for NULL domain names when running on NT4 here, pass an empty string if so.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * However, passing FQDNs should work!
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ((DWORD)(LOBYTE(LOWORD(GetVersion()))) < 5) /* < Windows 2000. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ? L"" /* NT4 and older. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync : NULL, /* Windows 2000 and up. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszPassword,
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync LOGON32_LOGON_INTERACTIVE,
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync LOGON32_PROVIDER_DEFAULT,
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync phToken);
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync if (!fRc)
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync return rtProcMapErrorCodes(GetLastError());
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync return VINF_SUCCESS;
8f8c8ff0bfe182cff047f8c028b2546b25087d44vboxsync}
8f8c8ff0bfe182cff047f8c028b2546b25087d44vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync/**
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * Logs off a user, specified by the given token.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync *
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @param hToken The token (=user) to log off.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncstatic void rtProcUserLogoff(HANDLE hToken)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync CloseHandle(hToken);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Creates an environment block out of a handed in Unicode and RTENV block.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The RTENV block can overwrite entries already present in the Unicode block.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @return IPRT status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pvBlock Unicode block (array) of environment entries; name=value
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param hEnv Handle of an existing RTENV block to use.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param ppwszBlock Pointer to the final output.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int rtProcEnvironmentCreateInternal(VOID *pvBlock, RTENV hEnv, PRTUTF16 *ppwszBlock)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTENV hEnvTemp;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync rc = RTEnvClone(&hEnvTemp, hEnv);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PRTUTF16 pBlock = (PRTUTF16)pvBlock;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync while ( pBlock
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && pBlock != '\0'
55d7f78467f8aefc7dff60f188bdf0f80523862cvboxsync && RT_SUCCESS(rc))
55d7f78467f8aefc7dff60f188bdf0f80523862cvboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync char *pszEntry;
d5d8a18c82ced223ee7d069cdb1ba074c80449d8vboxsync rc = RTUtf16ToUtf8(pBlock, &pszEntry);
d5d8a18c82ced223ee7d069cdb1ba074c80449d8vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Don't overwrite values which we already have set to a custom value
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * specified in hEnv ... */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!RTEnvExistEx(hEnv, pszEntry))
3e4bc3e32bc6ac59335fae7115d09f7a2ca9dc4bvboxsync rc = RTEnvPutEx(hEnvTemp, pszEntry);
3e4bc3e32bc6ac59335fae7115d09f7a2ca9dc4bvboxsync RTStrFree(pszEntry);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync size_t l;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* 32k should be the maximum the environment block can have on Windows. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (FAILED(StringCbLengthW((LPCWSTR)pBlock, _32K * sizeof(RTUTF16), &l)))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBlock += l / sizeof(RTUTF16);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pBlock[1] == '\0') /* Did we reach the double zero termination (\0\0)? */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pBlock++; /* Skip zero termination of current string and advance to next string ... */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTEnvQueryUtf16Block(hEnvTemp, ppwszBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTEnvDestroy(hEnvTemp);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
3e4bc3e32bc6ac59335fae7115d09f7a2ca9dc4bvboxsync
3e4bc3e32bc6ac59335fae7115d09f7a2ca9dc4bvboxsync
3e4bc3e32bc6ac59335fae7115d09f7a2ca9dc4bvboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Builds up the environment block for a specified user (identified by a token),
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * whereas hEnv is an additional set of environment variables which overwrite existing
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * values of the user profile. ppwszBlock needs to be destroyed after usage
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * calling rtProcEnvironmentDestroy().
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @return IPRT status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param hToken Token of the user to use.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param hEnv Own environment block to extend/overwrite the profile's data with.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param ppwszBlock Pointer to a pointer of the final UTF16 environment block.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int rtProcEnvironmentCreateFromToken(HANDLE hToken, RTENV hEnv, PRTUTF16 *ppwszBlock)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTLDRMOD hUserenv;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTLdrLoad("Userenv.dll", &hUserenv);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PFNCREATEENVIRONMENTBLOCK pfnCreateEnvironmentBlock;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrGetSymbol(hUserenv, "CreateEnvironmentBlock", (void**)&pfnCreateEnvironmentBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PFNPFNDESTROYENVIRONMENTBLOCK pfnDestroyEnvironmentBlock;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrGetSymbol(hUserenv, "DestroyEnvironmentBlock", (void**)&pfnDestroyEnvironmentBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LPVOID pEnvBlockProfile = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pfnCreateEnvironmentBlock(&pEnvBlockProfile, hToken, FALSE /* Don't inherit from parent. */))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = rtProcEnvironmentCreateInternal(pEnvBlockProfile, hEnv, ppwszBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pfnDestroyEnvironmentBlock(pEnvBlockProfile);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTErrConvertFromWin32(GetLastError());
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTLdrClose(hUserenv);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* If we don't have the Userenv-API for whatever reason or something with the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * native environment block failed, try to return at least our own environment block. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTEnvQueryUtf16Block(hEnv, ppwszBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
8b82f5ce032cb07de31804c998483b0988530aebvboxsync
8b82f5ce032cb07de31804c998483b0988530aebvboxsync/**
8b82f5ce032cb07de31804c998483b0988530aebvboxsync * Builds up the environment block for a specified user (identified by user name, password
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * and domain), whereas hEnv is an additional set of environment variables which overwrite
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync * existing values of the user profile. ppwszBlock needs to be destroyed after usage
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * calling rtProcEnvironmentDestroy().
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @return IPRT status code.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pwszUser User name.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pwszPassword Password.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param pwszDomain Domain.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param hEnv Own environment block to extend/overwrite the profile's data with.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @param ppwszBlock Pointer to a pointer of the final UTF16 environment block.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9083f76e8c5709604766d0215a380de516e781eevboxsyncstatic int rtProcEnvironmentCreateFromAccount(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain,
9083f76e8c5709604766d0215a380de516e781eevboxsync RTENV hEnv, PRTUTF16 *ppwszBlock)
ad8fb8c920c36650d5ead020ef8e05b681dd4375vboxsync{
6a0b15b171dc10f072ec82f498d7b20d7c0eec6cvboxsync HANDLE hToken;
6a0b15b171dc10f072ec82f498d7b20d7c0eec6cvboxsync int rc = rtProcUserLogon(pwszUser, pwszPassword, pwszDomain, &hToken);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = rtProcEnvironmentCreateFromToken(hToken, hEnv, ppwszBlock);
3649373f921ada8549bf86c6edb03b340f2d214avboxsync rtProcUserLogoff(hToken);
3649373f921ada8549bf86c6edb03b340f2d214avboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync/**
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync * Destroys an environment block formerly created by rtProcEnvironmentCreateInternal(),
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * rtProcEnvironmentCreateFromToken() or rtProcEnvironmentCreateFromAccount().
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync *
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * @param ppwszBlock Environment block to destroy.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncstatic void rtProcEnvironmentDestroy(PRTUTF16 ppwszBlock)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync{
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync RTEnvFreeUtf16Block(ppwszBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTENV hEnv, DWORD dwCreationFlags,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo, uint32_t fFlags)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync BOOL fRc = FALSE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD dwErr = NO_ERROR;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * If we run as a service CreateProcessWithLogon will fail,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * so don't even try it (because of Local System context).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!(fFlags & RTPROC_FLAGS_SERVICE))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTLDRMOD hAdvAPI32;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrLoad("Advapi32.dll", &hAdvAPI32);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This may fail on too old (NT4) platforms or if the calling process
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * is running on a SYSTEM account (like a service, ERROR_ACCESS_DENIED) on newer
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * platforms (however, this works on W2K!).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PFNCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrGetSymbol(hAdvAPI32, "CreateProcessWithLogonW", (void**)&pfnCreateProcessWithLogonW);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PRTUTF16 pwszzBlock;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = rtProcEnvironmentCreateFromAccount(pwszUser, pwszPassword, NULL /* Domain */,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync hEnv, &pwszzBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync fRc = pfnCreateProcessWithLogonW(pwszUser,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, /* lpDomain*/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszPassword,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync 1 /*LOGON_WITH_PROFILE*/, /* dwLogonFlags */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszExec,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszCmdLine,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwCreationFlags,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszzBlock,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, /* pCurrentDirectory */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pStartupInfo,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pProcInfo);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!fRc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rtProcEnvironmentDestroy(pwszzBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTLdrClose(hAdvAPI32);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Did the API call above fail because we're running on a too old OS (NT4) or
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * we're running as a Windows service?
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( RT_FAILURE(rc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync || (fFlags & RTPROC_FLAGS_SERVICE))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * So if we want to start a process from a service (RTPROC_FLAGS_SERVICE),
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * we have to do the following:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - Check the credentials supplied and get the user SID.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - If valid get the correct Explorer/VBoxTray instance corresponding to that
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * user. This of course is only possible if that user is logged in (over
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * physical console or terminal services).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - If we found the user's Explorer/VBoxTray app, use and modify the token to
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * use it in order to allow the newly started process to access the user's
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * desktop. If there's no Explorer/VBoxTray app we cannot display the started
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * process (but run it without UI).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The following restrictions apply:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - A process only can show its UI when the user the process should run
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * under is logged in (has a desktop).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - We do not want to display a process of user A run on the desktop
b8d7fd85fc9270b7ad49b0e1af2cafec0b9ec818vboxsync * of user B on multi session systems.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The following rights are needed in order to use LogonUserW and
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * CreateProcessAsUserW, so the local policy has to be modified to:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - SE_TCB_NAME = Act as part of the operating system
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * - SE_INCREASE_QUOTA_NAME
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * We may fail here with ERROR_PRIVILEGE_NOT_HELD.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PHANDLE phToken = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hTokenLogon = INVALID_HANDLE_VALUE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = rtProcUserLogon(pwszUser, pwszPassword, NULL /* Domain */, &hTokenLogon);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool fFound = false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hTokenUserDesktop = INVALID_HANDLE_VALUE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (fFlags & RTPROC_FLAGS_SERVICE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD cbName = 0; /* Must be zero to query size! */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD cbDomain = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync SID_NAME_USE sidNameUse = SidTypeUser;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync fRc = LookupAccountNameW(NULL,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszUser,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &cbName,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &cbDomain,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &sidNameUse);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!fRc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( !fRc
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && dwErr == ERROR_INSUFFICIENT_BUFFER
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && cbName > 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = NO_ERROR;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PSID pSID = (PSID)RTMemAlloc(cbName * sizeof(wchar_t));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pSID, VERR_NO_MEMORY);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo No way to allocate a PRTUTF16 directly? */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PRTUTF16 pwszDomain = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (cbDomain > 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszDomain = (PRTUTF16)RTMemAlloc(cbDomain * sizeof(RTUTF16));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pwszDomain, VERR_NO_MEMORY);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Note: Also supports FQDNs! */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( LookupAccountNameW(NULL, /* lpSystemName */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszUser,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pSID,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &cbName,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszDomain,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &cbDomain,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &sidNameUse)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && IsValidSid(pSID))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Array of process names we want to look for. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync static const char * const s_papszProcNames[] =
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#ifdef VBOX /* The explorer entry is a fallback in case GA aren't installed. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync { "VBoxTray.exe" },
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync { "explorer.exe" },
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync };
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync fFound = rtProcFindProcessByName(s_papszProcNames, pSID, &hTokenUserDesktop);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError(); /* LookupAccountNameW() failed. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTMemFree(pSID);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pwszDomain != NULL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTUtf16Free(pwszDomain);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else /* !RTPROC_FLAGS_SERVICE */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Nothing to do here right now. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo Hmm, this function already is too big! We need to split
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * it up into several small parts. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* If we got an error due to account lookup/loading above, don't
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * continue here. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (dwErr == NO_ERROR)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * If we didn't find a matching VBoxTray, just use the token we got
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * above from LogonUserW(). This enables us to at least run processes with
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * desktop interaction without UI.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync phToken = fFound ? &hTokenUserDesktop : &hTokenLogon;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTLDRMOD hUserenv;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTLdrLoad("Userenv.dll", &hUserenv);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PFNLOADUSERPROFILEW pfnLoadUserProfileW;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrGetSymbol(hUserenv, "LoadUserProfileW", (void**)&pfnLoadUserProfileW);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PFNUNLOADUSERPROFILE pfnUnloadUserProfile;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLdrGetSymbol(hUserenv, "UnloadUserProfile", (void**)&pfnUnloadUserProfile);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PROFILEINFOW profileInfo;
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync if (!(fFlags & RTPROC_FLAGS_NO_PROFILE))
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync {
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync ZeroMemory(&profileInfo, sizeof(profileInfo));
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync profileInfo.dwSize = sizeof(profileInfo);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync profileInfo.lpUserName = pwszUser;
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync profileInfo.dwFlags = PI_NOUI; /* Prevents the display of profile error messages. */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pfnLoadUserProfileW(*phToken, &profileInfo))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (dwErr == NO_ERROR)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PRTUTF16 pwszzBlock;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = rtProcEnvironmentCreateFromToken(*phToken, hEnv, &pwszzBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Useful KB articles:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * http://support.microsoft.com/kb/165194/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * http://support.microsoft.com/kb/184802/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * http://support.microsoft.com/kb/327618/
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync fRc = CreateProcessAsUserW(*phToken,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszExec,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszCmdLine,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, /* pProcessAttributes */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, /* pThreadAttributes */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync TRUE, /* fInheritHandles */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwCreationFlags,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszzBlock,
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync NULL, /* pCurrentDirectory */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pStartupInfo,
6308f6770d7f8fb842b437338e31554e913e6773vboxsync pProcInfo);
6308f6770d7f8fb842b437338e31554e913e6773vboxsync if (fRc)
6308f6770d7f8fb842b437338e31554e913e6773vboxsync dwErr = NO_ERROR;
6308f6770d7f8fb842b437338e31554e913e6773vboxsync else
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync dwErr = GetLastError(); /* CreateProcessAsUserW() failed. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rtProcEnvironmentDestroy(pwszzBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwErr = rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!(fFlags & RTPROC_FLAGS_NO_PROFILE))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pfnUnloadUserProfile(*phToken, profileInfo.hProfile);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTLdrClose(hUserenv);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync } /* Userenv.dll found/loaded? */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync } /* Account lookup succeeded? */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hTokenUserDesktop != INVALID_HANDLE_VALUE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync CloseHandle(hTokenUserDesktop);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rtProcUserLogoff(hTokenLogon);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( RT_SUCCESS(rc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && dwErr != NO_ERROR)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = rtProcMapErrorCodes(dwErr);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncRTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync const char *pszPassword, PRTPROCESS phProcess)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Input validation
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(!(fFlags & ~(RTPROC_FLAGS_DETACHED | RTPROC_FLAGS_HIDDEN | RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_SAME_CONTRACT | RTPROC_FLAGS_NO_PROFILE)), VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(!(fFlags & RTPROC_FLAGS_DETACHED) || !phProcess, VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrNullReturn(pszAsUser, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo search the PATH (add flag for this). */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Initialize the globals.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertRCReturn(rc, rc);
5e403442588989687ee8fb66dd921dd08199bfd0vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Get the file descriptors for the handles we've been passed.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * It seems there is no point in trying to convince a child process's CRT
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * that any of the standard file handles is non-TEXT. So, we don't...
b4dc9a151c850935f866da241db86e6ae33c45a2vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync STARTUPINFOW StartupInfo;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RT_ZERO(StartupInfo);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.cb = sizeof(StartupInfo);
b4dc9a151c850935f866da241db86e6ae33c45a2vboxsync StartupInfo.dwFlags = STARTF_USESTDHANDLES;
b4dc9a151c850935f866da241db86e6ae33c45a2vboxsync#if 1 /* The CRT should keep the standard handles up to date. */
b4dc9a151c850935f866da241db86e6ae33c45a2vboxsync StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.hStdInput = _get_osfhandle(0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.hStdOutput = _get_osfhandle(1);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.hStdError = _get_osfhandle(2);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* If we want to have a hidden process (e.g. not visible to
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * to the user) use the STARTUPINFO flags. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (fFlags & RTPROC_FLAGS_HIDDEN)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync StartupInfo.wShowWindow = SW_HIDE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PCRTHANDLE paHandles[3] = { phStdIn, phStdOut, phStdErr };
5e403442588989687ee8fb66dd921dd08199bfd0vboxsync HANDLE *aphStds[3] = { &StartupInfo.hStdInput, &StartupInfo.hStdOutput, &StartupInfo.hStdError };
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD afInhStds[3] = { 0xffffffff, 0xffffffff, 0xffffffff };
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (int i = 0; i < 3; i++)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (paHandles[i])
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertPtrReturn(paHandles[i], VERR_INVALID_POINTER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync switch (paHandles[i]->enmType)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case RTHANDLETYPE_FILE:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *aphStds[i] = paHandles[i]->u.hFile != NIL_RTFILE
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ? (HANDLE)RTFileToNative(paHandles[i]->u.hFile)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync : INVALID_HANDLE_VALUE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
5e403442588989687ee8fb66dd921dd08199bfd0vboxsync case RTHANDLETYPE_PIPE:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *aphStds[i] = paHandles[i]->u.hPipe != NIL_RTPIPE
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ? (HANDLE)RTPipeToNative(paHandles[i]->u.hPipe)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync : INVALID_HANDLE_VALUE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
b4dc9a151c850935f866da241db86e6ae33c45a2vboxsync case RTHANDLETYPE_SOCKET:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *aphStds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync ? (HANDLE)RTSocketToNative(paHandles[i]->u.hSocket)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync : INVALID_HANDLE_VALUE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync default:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailedReturn(("%d: %d\n", i, paHandles[i]->enmType), VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Get the inheritability of the handle. */
fe869d55b000b5b3445dcf7077ac443434ff3ec3vboxsync if (*aphStds[i] != INVALID_HANDLE_VALUE)
fe869d55b000b5b3445dcf7077ac443434ff3ec3vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!GetHandleInformation(*aphStds[i], &afInhStds[i]))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTErrConvertFromWin32(GetLastError());
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailedReturn(("%Rrc %p\n", rc, *aphStds[i]), rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Set the inheritability any handles we're handing the child.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VINF_SUCCESS;
2d04e048765b5cde38cc383c9c872b475224aa0bvboxsync for (int i = 0; i < 3; i++)
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if ( (afInhStds[i] != 0xffffffff)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && !(afInhStds[i] & HANDLE_FLAG_INHERIT))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if (!SetHandleInformation(*aphStds[i], HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync rc = RTErrConvertFromWin32(GetLastError());
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync AssertMsgFailedBreak(("%Rrc %p\n", rc, *aphStds[i]));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync /*
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync * Create the environment block, command line and convert the executable
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync * name.
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync */
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync PRTUTF16 pwszzBlock;
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if (RT_SUCCESS(rc))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync rc = RTEnvQueryUtf16Block(hEnv, &pwszzBlock);
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync if (RT_SUCCESS(rc))
f4f1486a0ea478a9cf75ad985f1d25915fa1f3a4vboxsync {
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync PRTUTF16 pwszCmdLine;
979511e3a45b65c9f38881ca2e9de4dfbad2e0c4vboxsync rc = RTGetOptArgvToUtf16String(&pwszCmdLine, papszArgs, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync if (RT_SUCCESS(rc))
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync {
d6ec942234269e5c8ddc45e26473fd575ade6fbcvboxsync PRTUTF16 pwszExec;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTStrToUtf16(pszExec, &pwszExec);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Get going...
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PROCESS_INFORMATION ProcInfo;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RT_ZERO(ProcInfo);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (fFlags & RTPROC_FLAGS_DETACHED)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwCreationFlags |= DETACHED_PROCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Only use the normal CreateProcess stuff if we have no user name
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * and we are not running from a (Windows) service. Otherwise use
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * the more advanced version in rtProcCreateAsUserHlp().
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if ( pszAsUser == NULL
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && !(fFlags & RTPROC_FLAGS_SERVICE))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (CreateProcessW(pwszExec,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszCmdLine,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, /* pProcessAttributes */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, /* pThreadAttributes */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync TRUE, /* fInheritHandles */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync dwCreationFlags,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pwszzBlock,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync NULL, /* pCurrentDirectory */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &StartupInfo,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync &ProcInfo))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTErrConvertFromWin32(GetLastError());
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Convert the additional parameters and use a helper
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * function to do the actual work.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PRTUTF16 pwszUser;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTStrToUtf16(pszAsUser, &pwszUser);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PRTUTF16 pwszPassword;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTStrToUtf16(pszPassword ? pszPassword : "", &pwszPassword);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = rtProcCreateAsUserHlp(pwszUser, pwszPassword,
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync pwszExec, pwszCmdLine, hEnv, dwCreationFlags,
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync &StartupInfo, &ProcInfo, fFlags);
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTUtf16Free(pwszPassword);
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTUtf16Free(pwszUser);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync if (RT_SUCCESS(rc))
16e6bb956968b3b7caee5a07dc98ad0e4aa60d36vboxsync {
16e6bb956968b3b7caee5a07dc98ad0e4aa60d36vboxsync CloseHandle(ProcInfo.hThread);
16e6bb956968b3b7caee5a07dc98ad0e4aa60d36vboxsync if (phProcess)
16e6bb956968b3b7caee5a07dc98ad0e4aa60d36vboxsync {
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync /*
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync * Add the process to the child process list so
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * RTProcWait can reuse and close the process handle.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rtProcWinAddPid(ProcInfo.dwProcessId, ProcInfo.hProcess);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *phProcess = ProcInfo.dwProcessId;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync CloseHandle(ProcInfo.hProcess);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTUtf16Free(pwszExec);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTUtf16Free(pwszCmdLine);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTEnvFreeUtf16Block(pwszzBlock);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync /* Undo any handle inherit changes. */
648b0a0e189323afe4d836f1848f82c7dded0e58vboxsync for (int i = 0; i < 3; i++)
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync if ( (afInhStds[i] != 0xffffffff)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync && !(afInhStds[i] & HANDLE_FLAG_INHERIT))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync if (!SetHandleInformation(*aphStds[i], HANDLE_FLAG_INHERIT, 0))
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync AssertMsgFailed(("%Rrc %p\n", RTErrConvertFromWin32(GetLastError()), *aphStds[i]));
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync }
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync return rc;
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync}
56bef151ea50f63620466fce377458ce5fd0967avboxsync
eab76ae67801d10882ae1fbdb90351044a2a3a54vboxsync
56bef151ea50f63620466fce377458ce5fd0967avboxsync
56bef151ea50f63620466fce377458ce5fd0967avboxsyncRTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertReturn(!(fFlags & ~(RTPROCWAIT_FLAGS_BLOCK | RTPROCWAIT_FLAGS_NOBLOCK)), VERR_INVALID_PARAMETER);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertRCReturn(rc, rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Try find the process among the ones we've spawned, otherwise, attempt
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * opening the specified process.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hOpenedProc = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hProcess = rtProcWinFindPid(Process);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hProcess == NULL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync hProcess = hOpenedProc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, Process);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hProcess == NULL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (dwErr == ERROR_INVALID_PARAMETER)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VERR_PROCESS_NOT_FOUND;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return RTErrConvertFromWin32(dwErr);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Wait for it to terminate.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD Millies = fFlags == RTPROCWAIT_FLAGS_BLOCK ? INFINITE : 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (WaitRc == WAIT_IO_COMPLETION)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync switch (WaitRc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * It has terminated.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case WAIT_OBJECT_0:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD dwExitCode;
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync if (GetExitCodeProcess(hProcess, &dwExitCode))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo the exit code can be special statuses. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pProcStatus)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pProcStatus->iStatus = (int)dwExitCode;
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hOpenedProc == NULL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rtProcWinRemovePid(Process);
fe869d55b000b5b3445dcf7077ac443434ff3ec3vboxsync rc = VINF_SUCCESS;
fe869d55b000b5b3445dcf7077ac443434ff3ec3vboxsync }
fe869d55b000b5b3445dcf7077ac443434ff3ec3vboxsync else
fe869d55b000b5b3445dcf7077ac443434ff3ec3vboxsync rc = RTErrConvertFromWin32(GetLastError());
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * It hasn't terminated just yet.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case WAIT_TIMEOUT:
0a3599702f0cfe19a23070ff9eddbcec0ae71298vboxsync rc = VERR_PROCESS_RUNNING;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Something went wrong...
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case WAIT_FAILED:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTErrConvertFromWin32(GetLastError());
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync case WAIT_ABANDONED:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertFailed();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_GENERAL_FAILURE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync default:
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertMsgFailed(("WaitRc=%RU32\n", WaitRc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_GENERAL_FAILURE;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hOpenedProc != NULL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync CloseHandle(hOpenedProc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncRTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo this isn't quite right. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return RTProcWait(Process, fFlags, pProcStatus);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncRTR3DECL(int) RTProcTerminate(RTPROCESS Process)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertRCReturn(rc, rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Try find the process among the ones we've spawned, otherwise, attempt
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * opening the specified process.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync HANDLE hProcess = rtProcWinFindPid(Process);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hProcess != NULL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!TerminateProcess(hProcess, 127))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTErrConvertFromWin32(GetLastError());
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, Process);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hProcess != NULL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync BOOL fRc = TerminateProcess(hProcess, 127);
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync DWORD dwErr = GetLastError();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync CloseHandle(hProcess);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!fRc)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTErrConvertFromWin32(dwErr);
543fd530ce618a1b55531ea76a785c7add7d072cvboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncRTR3DECL(uint64_t) RTProcGetAffinityMask(void)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD_PTR dwProcessAffinityMask = 0xffffffff;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync DWORD_PTR dwSystemAffinityMask;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync BOOL fRc = GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Assert(fRc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return dwProcessAffinityMask;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync