process-win.cpp revision c77f724884bdfe5a7376dc72de92dfae3476f5e3
dccbafa70b5a9a6f933c5566e4542caf9f379b97vboxsync/* $Id$ */
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync/** @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Process, Windows.
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync */
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync/*
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync *
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * available from http://www.virtualbox.org. This file is free software;
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * you can redistribute it and/or modify it under the terms of the GNU
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * General Public License (GPL) as published by the Free Software
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync *
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * The contents of this file may alternatively be used under the terms
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * of the Common Development and Distribution License Version 1.0
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * VirtualBox OSE distribution, in which case the provisions of the
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * CDDL are applicable instead of those of the GPL.
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync *
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * You may elect to license modified versions of this file under the
bd8e360cd1db83dcb2694ea9122ce3bc5bae678avboxsync * terms and conditions of either the GPL or the CDDL or both.
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync *
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync * additional information or have any questions.
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync/*******************************************************************************
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync* Header Files *
dccbafa70b5a9a6f933c5566e4542caf9f379b97vboxsync*******************************************************************************/
d618bed3882cd227cf8f5d0d2824f8db42fad415vboxsync#define LOG_GROUP RTLOGGROUP_PROCESS
03c2683d4e59cc500217b1d5d76fdf9b8cdfefa5vboxsync
03c2683d4e59cc500217b1d5d76fdf9b8cdfefa5vboxsync#include <Userenv.h>
03c2683d4e59cc500217b1d5d76fdf9b8cdfefa5vboxsync#include <Windows.h>
5ef92c0006229b3fc7bc7eb4ad80ed65fb0dd98bvboxsync#include <process.h>
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync#include <errno.h>
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/process.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include "internal/iprt.h"
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/assert.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/critsect.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/file.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/err.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/env.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/getopt.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/initterm.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/ldr.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/mem.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/once.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/pipe.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/string.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync#include <iprt/socket.h>
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
dccbafa70b5a9a6f933c5566e4542caf9f379b97vboxsync/*******************************************************************************
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync* Structures and Typedefs *
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync*******************************************************************************/
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsynctypedef WINADVAPI BOOL WINAPI FNCREATEPROCESSWITHLOGON(LPCWSTR,
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync LPCWSTR,
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync LPCWSTR,
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync DWORD,
81587231c9c584851518872e197f6f02dffe68cavboxsync LPCWSTR,
81587231c9c584851518872e197f6f02dffe68cavboxsync LPWSTR,
81587231c9c584851518872e197f6f02dffe68cavboxsync DWORD,
81587231c9c584851518872e197f6f02dffe68cavboxsync LPVOID,
81587231c9c584851518872e197f6f02dffe68cavboxsync LPCWSTR,
81587231c9c584851518872e197f6f02dffe68cavboxsync LPSTARTUPINFOW,
7be2140da7230ed5736528554a4dc34b2ac482acvboxsync LPPROCESS_INFORMATION);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsynctypedef FNCREATEPROCESSWITHLOGON *PFNCREATEPROCESSWITHLOGON;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync/*******************************************************************************
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync* Global Variables *
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync*******************************************************************************/
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync/** Init once structure. */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsyncstatic RTONCE g_rtProcWinInitOnce = RTONCE_INITIALIZER;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync/** Critical section protecting the process array. */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsyncstatic RTCRITSECT g_CritSect;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync/** The number of processes in the array. */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsyncstatic uint32_t g_cProcesses;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync/** The current allocation size. */
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsyncstatic uint32_t g_cProcessesAlloc;
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync/** Array containing the live or non-reaped child processes. */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncstatic struct RTPROCWINENTRY
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync{
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync /** The process ID. */
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync ULONG_PTR pid;
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync /** The process handle. */
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync HANDLE hProcess;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync} *g_paProcesses;
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync/**
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * Clean up the globals.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync *
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * @param enmReason Ignored.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * @param iStatus Ignored.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * @param pvUser Ignored.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync */
c882ddf98a60a4aab1218108b334083f98b7d66avboxsyncstatic DECLCALLBACK(void) rtProcWinTerm(RTTERMREASON enmReason, int32_t iStatus, void *pvUser)
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync{
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync NOREF(pvUser); NOREF(iStatus); NOREF(enmReason);
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync RTCritSectDelete(&g_CritSect);
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync size_t i = g_cProcesses;
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync while (i-- > 0)
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync {
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync CloseHandle(g_paProcesses[i].hProcess);
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync g_paProcesses[i].hProcess = NULL;
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync }
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync RTMemFree(g_paProcesses);
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync g_paProcesses = NULL;
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync g_cProcesses = 0;
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync g_cProcessesAlloc = 0;
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync}
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync/**
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * Initialize the globals.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync *
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * @returns IPRT status code.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * @param pvUser1 Ignored.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync * @param pvUser2 Ignored.
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync */
c882ddf98a60a4aab1218108b334083f98b7d66avboxsyncstatic DECLCALLBACK(int32_t) rtProcWinInitOnce(void *pvUser1, void *pvUser2)
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync{
c882ddf98a60a4aab1218108b334083f98b7d66avboxsync NOREF(pvUser1); NOREF(pvUser2);
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync g_cProcesses = 0;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync g_cProcessesAlloc = 0;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync g_paProcesses = NULL;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync int rc = RTCritSectInit(&g_CritSect);
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync if (RT_SUCCESS(rc))
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync {
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync /** @todo init once, terminate once - this is a generic thing which should
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync * have some kind of static and simpler setup! */
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync rc = RTTermRegisterCallback(rtProcWinTerm, NULL);
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync if (RT_SUCCESS(rc))
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync return rc;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync RTCritSectDelete(&g_CritSect);
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync }
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync return rc;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync}
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync/**
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync * Gets the process handle for a process from g_paProcesses.
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync *
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync * @returns Process handle if found, NULL if not.
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync * @param pid The process to remove (pid).
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync */
b6097213cd07c5383c49168bfb61f915dbd4587avboxsyncstatic HANDLE rtProcWinFindPid(RTPROCESS pid)
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync{
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync HANDLE hProcess = NULL;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync RTCritSectEnter(&g_CritSect);
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync uint32_t i = g_cProcesses;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync while (i-- > 0)
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync if (g_paProcesses[i].pid == pid)
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync {
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync hProcess = g_paProcesses[i].hProcess;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync break;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync }
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync RTCritSectLeave(&g_CritSect);
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync return hProcess;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync}
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync/**
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync * Removes a process from g_paProcesses.
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync *
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync * @param pid The process to remove (pid).
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync */
b6097213cd07c5383c49168bfb61f915dbd4587avboxsyncstatic void rtProcWinRemovePid(RTPROCESS pid)
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync{
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync RTCritSectEnter(&g_CritSect);
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync uint32_t i = g_cProcesses;
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync while (i-- > 0)
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync if (g_paProcesses[i].pid == pid)
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync {
b6097213cd07c5383c49168bfb61f915dbd4587avboxsync g_cProcesses--;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync uint32_t cToMove = g_cProcesses - i;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync if (cToMove)
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync memmove(&g_paProcesses[i], &g_paProcesses[i + 1], cToMove * sizeof(g_paProcesses[0]));
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync break;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync }
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync RTCritSectLeave(&g_CritSect);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync}
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync/**
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync * Adds a process to g_paProcesses.
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync *
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync * @returns IPRT status code.
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync * @param pid The process id.
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync * @param hProcess The process handle.
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsyncstatic int rtProcWinAddPid(RTPROCESS pid, HANDLE hProcess)
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync{
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync RTCritSectEnter(&g_CritSect);
7868f7238f92c22fcfede63182607629da7a8eadvboxsync
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync uint32_t i = g_cProcesses;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync if (i >= g_cProcessesAlloc)
fd546afe09073de92e5422c1334f1c27b4108687vboxsync {
fd546afe09073de92e5422c1334f1c27b4108687vboxsync void *pvNew = RTMemRealloc(g_paProcesses, (i + 16) * sizeof(g_paProcesses[0]));
fd546afe09073de92e5422c1334f1c27b4108687vboxsync if (RT_UNLIKELY(!pvNew))
fd546afe09073de92e5422c1334f1c27b4108687vboxsync {
fd546afe09073de92e5422c1334f1c27b4108687vboxsync RTCritSectLeave(&g_CritSect);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync return VERR_NO_MEMORY;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync }
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync g_paProcesses = (struct RTPROCWINENTRY *)pvNew;
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync g_cProcessesAlloc = i + 16;
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync }
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsync g_paProcesses[i].pid = pid;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync g_paProcesses[i].hProcess = hProcess;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync g_cProcesses = i + 1;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync RTCritSectLeave(&g_CritSect);
fd546afe09073de92e5422c1334f1c27b4108687vboxsync return VINF_SUCCESS;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync}
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsyncRTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
fd546afe09073de92e5422c1334f1c27b4108687vboxsync{
fd546afe09073de92e5422c1334f1c27b4108687vboxsync return RTProcCreateEx(pszExec, papszArgs, Env, fFlags,
fd546afe09073de92e5422c1334f1c27b4108687vboxsync NULL, NULL, NULL, /* standard handles */
fd546afe09073de92e5422c1334f1c27b4108687vboxsync NULL /*pszAsUser*/, NULL /* pszPassword*/,
fd546afe09073de92e5422c1334f1c27b4108687vboxsync pProcess);
fd546afe09073de92e5422c1334f1c27b4108687vboxsync}
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsyncstatic int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine,
fd546afe09073de92e5422c1334f1c27b4108687vboxsync PRTUTF16 pwszzBlock, STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo)
fd546afe09073de92e5422c1334f1c27b4108687vboxsync{
fd546afe09073de92e5422c1334f1c27b4108687vboxsync /** @todo On NT4 we need to enable the SeTcbPrivilege to act as part of the operating system. Otherwise
fd546afe09073de92e5422c1334f1c27b4108687vboxsync * we will get error 1314 (priviledge not held) as a response. */
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsync /*
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync * The following rights are needed in order to use LogonUserW and
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync * CreateProcessAsUserW, so the local policy has to be modified to:
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync * - SE_TCB_NAME = Act as part of the operating system
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync * - SE_INCREASE_QUOTA_NAME
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync *
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync * We may fail here with ERROR_PRIVILEGE_NOT_HELD.
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync int rc;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync DWORD dwErr = NO_ERROR;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync HANDLE hToken = INVALID_HANDLE_VALUE;
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync BOOL fRc = LogonUserW(pwszUser,
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync NULL, /* lpDomain */
8e3f7f941e446e203bd8f3d0782d761aeb5af6c9vboxsync pwszPassword,
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync LOGON32_LOGON_INTERACTIVE,
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync LOGON32_PROVIDER_DEFAULT,
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync &hToken);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync if (fRc)
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync {
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync fRc = CreateProcessAsUserW(hToken,
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync pwszExec,
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync pwszCmdLine,
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync NULL, /* pProcessAttributes */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync NULL, /* pThreadAttributes */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync TRUE, /* fInheritHandles */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync pwszzBlock,
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync NULL, /* pCurrentDirectory */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync pStartupInfo,
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync pProcInfo);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync if (!fRc)
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync dwErr = GetLastError();
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync CloseHandle(hToken);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync }
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync else
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync dwErr = GetLastError();
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync /*
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * If we don't hold enough priviledges to spawn a new process with
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * different credentials we have to use CreateProcessWithLogonW here. This
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * API is W2K+ and uses a system service for spawning the process.
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /** @todo Use fFlags to either use this feature or just fail. */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (dwErr == ERROR_PRIVILEGE_NOT_HELD)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync RTLDRMOD hAdvAPI32;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync rc = RTLdrLoad("Advapi32.dll", &hAdvAPI32);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync if (RT_SUCCESS(rc))
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync {
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync /* This may fail on too old (NT4) platforms. */
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync PFNCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW;
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync rc = RTLdrGetSymbol(hAdvAPI32, "CreateProcessWithLogonW", (void**)&pfnCreateProcessWithLogonW);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (RT_SUCCESS(rc))
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync {
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync fRc = pfnCreateProcessWithLogonW(pwszUser,
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync NULL, /* lpDomain*/
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync pwszPassword,
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync 1 /*LOGON_WITH_PROFILE*/, /* dwLogonFlags */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync pwszExec,
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync pwszCmdLine,
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync pwszzBlock,
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync NULL, /* pCurrentDirectory */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync pStartupInfo,
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync pProcInfo);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (fRc)
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync dwErr = NO_ERROR;
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync else
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync dwErr = GetLastError();
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync RTLdrClose(hAdvAPI32);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync#endif
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (dwErr != NO_ERROR)
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync rc = RTErrConvertFromWin32(dwErr);
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync else
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync rc = VINF_SUCCESS;
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync return rc;
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync}
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsyncRTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync const char *pszPassword, PRTPROCESS phProcess)
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync{
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync /*
4fa08e9052161e65bfe8d2e3bb38fa227af628c0vboxsync * Input validation
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertReturn(!(fFlags & ~RTPROC_FLAGS_DAEMONIZE), VERR_INVALID_PARAMETER);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync /** @todo search the PATH (add flag for this). */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync /*
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync * Initialize the globals.
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertRCReturn(rc, rc);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync /*
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync * Get the file descriptors for the handles we've been passed.
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync *
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync * It seems there is no point in trying to convince a child process's CRT
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync * that any of the standard file handles is non-TEXT. So, we don't...
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync STARTUPINFOW StartupInfo;
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync RT_ZERO(StartupInfo);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync StartupInfo.cb = sizeof(StartupInfo);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync StartupInfo.dwFlags = STARTF_USESTDHANDLES;
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync#if 1 /* The CRT should keep the standard handles up to date. */
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync#else
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync StartupInfo.hStdInput = _get_osfhandle(0);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync StartupInfo.hStdOutput = _get_osfhandle(1);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync StartupInfo.hStdError = _get_osfhandle(2);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync#endif
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync PCRTHANDLE paHandles[3] = { phStdIn, phStdOut, phStdErr };
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync HANDLE *aphStds[3] = { &StartupInfo.hStdInput, &StartupInfo.hStdOutput, &StartupInfo.hStdError };
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync DWORD afInhStds[3] = { 0xffffffff, 0xffffffff, 0xffffffff };
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync for (int i = 0; i < 3; i++)
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync {
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync if (paHandles[i])
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync {
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync AssertPtrReturn(paHandles[i], VERR_INVALID_POINTER);
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync switch (paHandles[i]->enmType)
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync {
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync case RTHANDLETYPE_FILE:
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync *aphStds[i] = paHandles[i]->u.hFile != NIL_RTFILE
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync ? (HANDLE)RTFileToNative(paHandles[i]->u.hFile)
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync : INVALID_HANDLE_VALUE;
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync break;
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync case RTHANDLETYPE_PIPE:
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync *aphStds[i] = paHandles[i]->u.hPipe != NIL_RTPIPE
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync ? (HANDLE)RTPipeToNative(paHandles[i]->u.hPipe)
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync : INVALID_HANDLE_VALUE;
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync break;
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync case RTHANDLETYPE_SOCKET:
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync *aphStds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET
1a05eb58618c8f646bd1304d10c73792e0034f20vboxsync ? (HANDLE)RTSocketToNative(paHandles[i]->u.hSocket)
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync : INVALID_HANDLE_VALUE;
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync break;
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync default:
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertMsgFailedReturn(("%d: %d\n", i, paHandles[i]->enmType), VERR_INVALID_PARAMETER);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync /* Get the inheritability of the handle. */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (*aphStds[i] != INVALID_HANDLE_VALUE)
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync {
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (!GetHandleInformation(*aphStds[i], &afInhStds[i]))
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync {
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync rc = RTErrConvertFromWin32(GetLastError());
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertMsgFailedReturn(("%Rrc %p\n", rc, *aphStds[i]), rc);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync /*
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync * Set the inheritability any handles we're handing the child.
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync rc = VINF_SUCCESS;
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync for (int i = 0; i < 3; i++)
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if ( (afInhStds[i] != 0xffffffff)
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync && !(afInhStds[i] & HANDLE_FLAG_INHERIT))
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync {
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (!SetHandleInformation(*aphStds[i], HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync {
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync rc = RTErrConvertFromWin32(GetLastError());
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync AssertMsgFailedBreak(("%Rrc %p\n", rc, *aphStds[i]));
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync }
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync /*
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync * Create the environment block, command line and convert the executable
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync * name.
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync */
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync PRTUTF16 pwszzBlock;
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (RT_SUCCESS(rc))
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync rc = RTEnvQueryUtf16Block(hEnv, &pwszzBlock);
f6f8bfbbbc6a59ba94b01886ed5a8d6e5813073bvboxsync if (RT_SUCCESS(rc))
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync PRTUTF16 pwszCmdLine;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync rc = RTGetOptArgvToUtf16String(&pwszCmdLine, papszArgs, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (RT_SUCCESS(rc))
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync PRTUTF16 pwszExec;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync rc = RTStrToUtf16(pszExec, &pwszExec);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (RT_SUCCESS(rc))
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /*
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * Get going...
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync PROCESS_INFORMATION ProcInfo;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync RT_ZERO(ProcInfo);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (pszAsUser == NULL)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (CreateProcessW(pwszExec,
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync pwszCmdLine,
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync NULL, /* pProcessAttributes */
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync NULL, /* pThreadAttributes */
fd546afe09073de92e5422c1334f1c27b4108687vboxsync TRUE, /* fInheritHandles */
fd546afe09073de92e5422c1334f1c27b4108687vboxsync CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
fd546afe09073de92e5422c1334f1c27b4108687vboxsync pwszzBlock,
7be2140da7230ed5736528554a4dc34b2ac482acvboxsync NULL, /* pCurrentDirectory */
7e0c3d180b978b8f4b5b33f8e924520248ee3ab3vboxsync &StartupInfo,
fd546afe09073de92e5422c1334f1c27b4108687vboxsync &ProcInfo))
81587231c9c584851518872e197f6f02dffe68cavboxsync rc = VINF_SUCCESS;
81587231c9c584851518872e197f6f02dffe68cavboxsync else
81587231c9c584851518872e197f6f02dffe68cavboxsync rc = RTErrConvertFromWin32(GetLastError());
dc88ff18a0306635c385b14211765e618351b253vboxsync }
dccbafa70b5a9a6f933c5566e4542caf9f379b97vboxsync else
dccbafa70b5a9a6f933c5566e4542caf9f379b97vboxsync {
81587231c9c584851518872e197f6f02dffe68cavboxsync /*
81587231c9c584851518872e197f6f02dffe68cavboxsync * Convert the additional parameters and use a helper
81587231c9c584851518872e197f6f02dffe68cavboxsync * function to do the actual work.
81587231c9c584851518872e197f6f02dffe68cavboxsync */
81587231c9c584851518872e197f6f02dffe68cavboxsync PRTUTF16 pwszUser;
81587231c9c584851518872e197f6f02dffe68cavboxsync rc = RTStrToUtf16(pszAsUser, &pwszUser);
81587231c9c584851518872e197f6f02dffe68cavboxsync if (RT_SUCCESS(rc))
81587231c9c584851518872e197f6f02dffe68cavboxsync {
81587231c9c584851518872e197f6f02dffe68cavboxsync PRTUTF16 pwszPassword;
81587231c9c584851518872e197f6f02dffe68cavboxsync rc = RTStrToUtf16(pszPassword ? pszPassword : "", &pwszPassword);
81587231c9c584851518872e197f6f02dffe68cavboxsync if (RT_SUCCESS(rc))
81587231c9c584851518872e197f6f02dffe68cavboxsync {
81587231c9c584851518872e197f6f02dffe68cavboxsync rc = rtProcCreateAsUserHlp(pwszUser, pwszPassword,
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync pwszExec, pwszCmdLine, pwszzBlock,
81587231c9c584851518872e197f6f02dffe68cavboxsync &StartupInfo, &ProcInfo);
81587231c9c584851518872e197f6f02dffe68cavboxsync
81587231c9c584851518872e197f6f02dffe68cavboxsync RTUtf16Free(pwszPassword);
81587231c9c584851518872e197f6f02dffe68cavboxsync }
81587231c9c584851518872e197f6f02dffe68cavboxsync RTUtf16Free(pwszUser);
81587231c9c584851518872e197f6f02dffe68cavboxsync }
81587231c9c584851518872e197f6f02dffe68cavboxsync }
81587231c9c584851518872e197f6f02dffe68cavboxsync if (RT_SUCCESS(rc))
81587231c9c584851518872e197f6f02dffe68cavboxsync {
81587231c9c584851518872e197f6f02dffe68cavboxsync CloseHandle(ProcInfo.hThread);
81587231c9c584851518872e197f6f02dffe68cavboxsync if (phProcess)
81587231c9c584851518872e197f6f02dffe68cavboxsync {
81587231c9c584851518872e197f6f02dffe68cavboxsync /*
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * Add the process to the child process list so
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * RTProcWait can reuse and close the process handle.
81587231c9c584851518872e197f6f02dffe68cavboxsync */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync rtProcWinAddPid(ProcInfo.dwProcessId, ProcInfo.hProcess);
81587231c9c584851518872e197f6f02dffe68cavboxsync *phProcess = ProcInfo.dwProcessId;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync else
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync CloseHandle(ProcInfo.hProcess);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync rc = VINF_SUCCESS;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync RTUtf16Free(pwszExec);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync RTUtf16Free(pwszCmdLine);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync RTEnvFreeUtf16Block(pwszzBlock);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /* Undo any handle inherit changes. */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync for (int i = 0; i < 3; i++)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if ( (afInhStds[i] != 0xffffffff)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync && !(afInhStds[i] & HANDLE_FLAG_INHERIT))
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (!SetHandleInformation(*aphStds[i], HANDLE_FLAG_INHERIT, 0))
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync AssertMsgFailed(("%Rrc %p\n", RTErrConvertFromWin32(GetLastError()), *aphStds[i]));
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync return rc;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync}
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsyncRTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync{
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync AssertReturn(!(fFlags & ~(RTPROCWAIT_FLAGS_BLOCK | RTPROCWAIT_FLAGS_NOBLOCK)), VERR_INVALID_PARAMETER);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync AssertRCReturn(rc, rc);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /*
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * Try find the process among the ones we've spawned, otherwise, attempt
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * opening the specified process.
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync HANDLE hProcess = rtProcWinFindPid(Process);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (hProcess == NULL)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, Process);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (hProcess != NULL)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /*
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * Wait for it to terminate.
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync DWORD Millies = fFlags == RTPROCWAIT_FLAGS_BLOCK ? INFINITE : 0;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync DWORD WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync while (WaitRc == WAIT_IO_COMPLETION)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync switch (WaitRc)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /*
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync * It has terminated.
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync case WAIT_OBJECT_0:
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync DWORD dwExitCode;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (GetExitCodeProcess(hProcess, &dwExitCode))
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /** @todo the exit code can be special statuses. */
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync if (pProcStatus)
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync {
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync pProcStatus->iStatus = (int)dwExitCode;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync rtProcWinRemovePid(Process);
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync return VINF_SUCCESS;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync break;
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync }
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync /*
81587231c9c584851518872e197f6f02dffe68cavboxsync * It hasn't terminated just yet.
81587231c9c584851518872e197f6f02dffe68cavboxsync */
81587231c9c584851518872e197f6f02dffe68cavboxsync case WAIT_TIMEOUT:
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync return VERR_PROCESS_RUNNING;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync /*
dccbafa70b5a9a6f933c5566e4542caf9f379b97vboxsync * Something went wrong...
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync */
da97b7ac000d0f02e86c31a4f2767a00d83c6167vboxsync case WAIT_FAILED:
da97b7ac000d0f02e86c31a4f2767a00d83c6167vboxsync break;
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync case WAIT_ABANDONED:
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync AssertFailed();
7868f7238f92c22fcfede63182607629da7a8eadvboxsync return VERR_GENERAL_FAILURE;
14e0667f834cd0e2a8c365084cd2ad0a893109e8vboxsync default:
7868f7238f92c22fcfede63182607629da7a8eadvboxsync AssertMsgFailed(("WaitRc=%RU32\n", WaitRc));
14e0667f834cd0e2a8c365084cd2ad0a893109e8vboxsync return VERR_GENERAL_FAILURE;
14e0667f834cd0e2a8c365084cd2ad0a893109e8vboxsync }
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync }
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync DWORD dwErr = GetLastError();
d618bed3882cd227cf8f5d0d2824f8db42fad415vboxsync if (dwErr == ERROR_INVALID_PARAMETER)
7868f7238f92c22fcfede63182607629da7a8eadvboxsync return VERR_PROCESS_NOT_FOUND;
da97b7ac000d0f02e86c31a4f2767a00d83c6167vboxsync return RTErrConvertFromWin32(dwErr);
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync}
da97b7ac000d0f02e86c31a4f2767a00d83c6167vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsync
b1cf57acefb5d1ce6ae2466f43e225a81083ff34vboxsyncRTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
ea6c70405e39fa563a55780ef25e0933d8c73a1avboxsync{
da97b7ac000d0f02e86c31a4f2767a00d83c6167vboxsync /** @todo this isn't quite right. */
da97b7ac000d0f02e86c31a4f2767a00d83c6167vboxsync return RTProcWait(Process, fFlags, pProcStatus);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync}
81587231c9c584851518872e197f6f02dffe68cavboxsync
81587231c9c584851518872e197f6f02dffe68cavboxsync
81587231c9c584851518872e197f6f02dffe68cavboxsyncRTR3DECL(int) RTProcTerminate(RTPROCESS Process)
81587231c9c584851518872e197f6f02dffe68cavboxsync{
81587231c9c584851518872e197f6f02dffe68cavboxsync HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, Process);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync if (hProcess != NULL)
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync {
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync BOOL fRc = TerminateProcess(hProcess, 127);
45e9c1c72518aeba6673332bdd4d70b59e1c11a4vboxsync CloseHandle(hProcess);
fd546afe09073de92e5422c1334f1c27b4108687vboxsync if (fRc)
4d6dcfe00aab559241d9ed05b89f803ab5ddf611vboxsync return VINF_SUCCESS;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync }
fd546afe09073de92e5422c1334f1c27b4108687vboxsync DWORD dwErr = GetLastError();
fd546afe09073de92e5422c1334f1c27b4108687vboxsync return RTErrConvertFromWin32(dwErr);
fd546afe09073de92e5422c1334f1c27b4108687vboxsync}
7e0c3d180b978b8f4b5b33f8e924520248ee3ab3vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
7e0c3d180b978b8f4b5b33f8e924520248ee3ab3vboxsyncRTR3DECL(uint64_t) RTProcGetAffinityMask(void)
fd546afe09073de92e5422c1334f1c27b4108687vboxsync{
fd546afe09073de92e5422c1334f1c27b4108687vboxsync DWORD_PTR dwProcessAffinityMask = 0xffffffff;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync DWORD_PTR dwSystemAffinityMask;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsync BOOL fRc = GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
fd546afe09073de92e5422c1334f1c27b4108687vboxsync Assert(fRc);
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsync return dwProcessAffinityMask;
fd546afe09073de92e5422c1334f1c27b4108687vboxsync}
fd546afe09073de92e5422c1334f1c27b4108687vboxsync
fd546afe09073de92e5422c1334f1c27b4108687vboxsync