VirtualBox

Changeset 80569 in vbox


Ignore:
Timestamp:
Sep 3, 2019 2:34:21 PM (5 years ago)
Author:
vboxsync
Message:

Main: bugref:9341: Added VM autostart during boot support for windows host

Location:
trunk
Files:
4 added
35 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/VBox-CodingGuidelines.cpp

    r79974 r80569  
    629629 *                                      NULL,           // pszAsUser
    630630 *                                      NULL,           // pszPassword
     631 *                                      NULL,           // pExtraData
    631632 *                                      &hProcess);
    632633 *        @endcode
  • trunk/doc/manual/en_US/user_AdvancedTopics.xml

    r78532 r80569  
    58755875        <ulink
    58765876      url="http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/BPSystemStartup.html">http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/BPSystemStartup.html</ulink>.
     5877      </para>
     5878
     5879    </sect2>
     5880
     5881    <sect2 id="autostart-windows">
     5882
     5883      <title>Windows: Starting the Autostart Service With windows service</title>
     5884
     5885      <para>
     5886        On Windows, the autostarting is implemented as Windows service.
     5887        The service is installed for every user with her/his own credentials.
     5888        Before installing any autostart services on a system you have to define
     5889        the <computeroutput>VBOXAUTOSTART_CONFIG</computeroutput> environment
     5890        variable in the system variables with the path to the config file.
     5891        The config file has the same format as on Linux,
     5892        see <xref linkend="autostart-linux" />, except the user name
     5893        can be specified using following formats: "user", "domain\user",
     5894        ".\user" and "user@domain".
     5895      </para>
     5896
     5897      <para>
     5898        To activate the autostart ability for particular user a member of
     5899        administrators group must run the following command:
     5900      </para>
     5901
     5902      <screen>VBoxAutostartSvc install --user=&lt;user&gt; [--password-file=&lt;password_file&gt;]</screen>
     5903
     5904      <para>
     5905        The password file should contain the password followed by a line break.
     5906        The rest of the file is ignored. The user will be asked for a password
     5907        if the password file is not specified.
     5908      </para>
     5909
     5910      <para>
     5911        To remove the autostart ability for particular user a member of
     5912        administrators group must run the following command:
     5913      </para>
     5914
     5915      <screen>VBoxAutostartSvc delete --user=&lt;user&gt;</screen>
     5916
     5917      <para>
     5918        The user can be specified for both commands using following formats:
     5919        "user", "domain\user", ".\user" and "user@domain"
     5920      </para>
     5921
     5922      <para>
     5923        Note:
     5924      </para>
     5925
     5926      <para>
     5927        If user has changed his password a member of administrators group
     5928        must either reinstall the service or change the service credentials
     5929        using windows service manager. The autostart service can not be
     5930        installed for users with empty passwords due to Windows security policies.
    58775931      </para>
    58785932
  • trunk/include/iprt/process.h

    r80481 r80569  
    168168 *                      NULL wif pszAsUser is NULL.  Whether this is actually
    169169 *                      used or not depends on the platform.
     170 * @param   pvExtraData Points to additional data as per @a fFlags:
     171 *                          - RTPROC_FLAGS_DESIRED_SESSION_ID: Pointing to a
     172 *                            uint32_t variable with the desired session ID.
    170173 * @param   phProcess   Where to store the process handle on successful return.
    171174 *                      The content is not changed on failure.  NULL is allowed.
     
    180183RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
    181184                               PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
    182                                const char *pszPassword, PRTPROCESS phProcess);
     185                               const char *pszPassword, void *pvExtraData, PRTPROCESS phProcess);
    183186
    184187/** @name RTProcCreate and RTProcCreateEx flags
     
    228231/** Hint that we don't expect to ever want to wait on the process. */
    229232#define RTPROC_FLAGS_NO_WAIT                RT_BIT(10)
     233/** For use with RTPROC_FLAGS_SERVICE to specify a desired session ID
     234 * (Windows only, ignored elsewhere).  The @a pvExtraData argument points to
     235 * a uint32_t containing the session ID, UINT32_MAX means any session. */
     236#define RTPROC_FLAGS_DESIRED_SESSION_ID     RT_BIT(11)
    230237/** Valid flag mask. */
    231 #define RTPROC_FLAGS_VALID_MASK             UINT32_C(0x7ff)
     238#define RTPROC_FLAGS_VALID_MASK             UINT32_C(0xfff)
    232239/** @}  */
    233240
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp

    r76553 r80569  
    12981298                rc = RTProcCreateEx(szSysprepCmd, papszArgsExp, hEnv, 0 /* fFlags */,
    12991299                                    phStdIn, phStdOut, phStdErr, NULL /* pszAsUser */,
    1300                                     NULL /* pszPassword */, phProcess);
     1300                                    NULL /* pszPassword */, NULL, phProcess);
    13011301                vgsvcGstCtrlProcessFreeArgv(papszArgsExp);
    13021302            }
     
    13901390                                pszUser,
    13911391                                pszPassword && *pszPassword ? pszPassword : NULL,
     1392                                NULL /*pvExtraData*/,
    13921393                                phProcess);
    13931394#ifdef RT_OS_WINDOWS
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r79326 r80569  
    22512251                                    !fAnonymous ? pszUser : NULL,
    22522252                                    !fAnonymous ? pSessionThread->StartupInfo.szPassword : NULL,
     2253                                    NULL /*pvExtraData*/,
    22532254                                    &pSessionThread->hProcess);
    22542255            }
  • trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk

    r76553 r80569  
    2222 PROGRAMS += VBoxAutostartSvc
    2323 VBoxAutostartSvc_TEMPLATE   = VBOXMAINCLIENTEXE
     24 VBoxAutostartSvc_INCS       = ../Common
    2425 VBoxAutostartSvc_SOURCES    = \
    2526        VBoxAutostartCfg.cpp \
     
    2728        VBoxAutostartStop.cpp \
    2829        VBoxAutostartUtils.cpp \
    29         VBoxAutostart-win.cpp
     30        VBoxAutostart-win.cpp \
     31        ../Common/PasswordInput.cpp
     32 VBoxAutostartSvc_LIBS.win += Secur32.lib       
    3033else
    3134 PROGRAMS += VBoxAutostart
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp

    r76553 r80569  
    2323#include <tchar.h>
    2424
     25#define SECURITY_WIN32
     26#include <Security.h>
     27
     28#include <VBox/com/array.h>
    2529#include <VBox/com/com.h>
    26 #include <VBox/com/string.h>
    27 #include <VBox/com/Guid.h>
    28 #include <VBox/com/array.h>
    2930#include <VBox/com/ErrorInfo.h>
    3031#include <VBox/com/errorprint.h>
    31 
     32#include <VBox/com/Guid.h>
     33#include <VBox/com/listeners.h>
    3234#include <VBox/com/NativeEventQueue.h>
    33 #include <VBox/com/listeners.h>
     35#include <VBox/com/string.h>
    3436#include <VBox/com/VirtualBox.h>
    3537
    3638#include <VBox/log.h>
    3739#include <VBox/version.h>
     40
     41#include <iprt/env.h>
    3842#include <iprt/errcore.h>
     43#include <iprt/getopt.h>
    3944#include <iprt/initterm.h>
    4045#include <iprt/mem.h>
    41 #include <iprt/getopt.h>
     46#include <iprt/process.h>
     47#include <iprt/path.h>
    4248#include <iprt/semaphore.h>
    4349#include <iprt/stream.h>
     
    4652
    4753#include "VBoxAutostart.h"
     54#include "PasswordInput.h"
    4855
    4956
     
    7178/** The semaphore the main service thread is waiting on in autostartSvcWinServiceMain. */
    7279static RTSEMEVENTMULTI g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI;
     80/** The service name is used for send to service main. */
     81static com::Bstr g_bstrServiceName;
    7382
    7483
     
    7786*********************************************************************************************************************************/
    7887static SC_HANDLE autostartSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess);
     88
     89static int autostartGetProcessDomainUser(com::Utf8Str &aUser)
     90{
     91    int rc = VERR_NOT_SUPPORTED;
     92
     93    RTUTF16 wszUsername[1024] = { 0 };
     94    ULONG   cwcUsername = RT_ELEMENTS(wszUsername);
     95    char *pszUser = NULL;
     96    if (!GetUserNameExW(NameSamCompatible, &wszUsername[0], &cwcUsername))
     97        return RTErrConvertFromWin32(GetLastError());
     98    rc = RTUtf16ToUtf8(wszUsername, &pszUser);
     99    aUser = pszUser;
     100    RTStrFree(pszUser);
     101    return rc;
     102}
     103
     104static int autostartGetLocalDomain(com::Utf8Str &aDomain)
     105{
     106    RTUTF16 pwszDomain[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
     107    uint32_t cwcDomainSize =  MAX_COMPUTERNAME_LENGTH + 1;
     108    if (!GetComputerNameW(pwszDomain, (LPDWORD)&cwcDomainSize))
     109        return RTErrConvertFromWin32(GetLastError());
     110    char *pszDomain = NULL;
     111    int rc = RTUtf16ToUtf8(pwszDomain, &pszDomain);
     112    aDomain = pszDomain;
     113    RTStrFree(pszDomain);
     114    return rc;
     115}
     116
     117static int autostartGetDomainAndUser(const com::Utf8Str &aDomainAndUser, com::Utf8Str &aDomain, com::Utf8Str &aUser)
     118{
     119    size_t offDelim = aDomainAndUser.find("\\");
     120    if (offDelim != aDomainAndUser.npos)
     121    {
     122        // if only domain is specified
     123        if (aDomainAndUser.length() - offDelim == 1)
     124            return VERR_INVALID_PARAMETER;
     125
     126        if (offDelim == 1 && aDomainAndUser[0] == '.')
     127        {
     128            int rc = autostartGetLocalDomain(aDomain);
     129            aUser = aDomainAndUser.substr(offDelim + 1);
     130            return rc;
     131        }
     132        aDomain = aDomainAndUser.substr(0, offDelim);
     133        aUser   = aDomainAndUser.substr(offDelim + 1);
     134        return VINF_SUCCESS;
     135    }
     136
     137    offDelim = aDomainAndUser.find("@");
     138    if (offDelim != aDomainAndUser.npos)
     139    {
     140        // if only domain is specified
     141        if (offDelim == 0)
     142            return VERR_INVALID_PARAMETER;
     143
     144        // with '@' but without domain
     145        if (aDomainAndUser.length() - offDelim == 1)
     146        {
     147            int rc = autostartGetLocalDomain(aDomain);
     148            aUser = aDomainAndUser.substr(0, offDelim);
     149            return rc;
     150        }
     151        aDomain = aDomainAndUser.substr(offDelim + 1);
     152        aUser   = aDomainAndUser.substr(0, offDelim);
     153        return VINF_SUCCESS;
     154    }
     155
     156    // only user is specified
     157    int rc = autostartGetLocalDomain(aDomain);
     158    aUser = aDomainAndUser;
     159    return rc;
     160}
     161
     162/** Common helper for formatting the service name. */
     163static void autostartFormatServiceName(const com::Utf8Str &aDomain, const com::Utf8Str &aUser, com::Utf8Str &aServiceName)
     164{
     165    aServiceName.printf("%s%s%s", AUTOSTART_SERVICE_NAME, aDomain.c_str(), aUser.c_str());
     166}
     167
     168/** Used by the delete service operation. */
     169static int autostartGetServiceName(const com::Utf8Str &aDomainAndUser, com::Utf8Str &aServiceName)
     170{
     171    com::Utf8Str sDomain;
     172    com::Utf8Str sUser;
     173    int rc = autostartGetDomainAndUser(aDomainAndUser, sDomain, sUser);
     174    if (RT_FAILURE(rc))
     175        return rc;
     176    autostartFormatServiceName(sDomain, sUser, aServiceName);
     177    return VINF_SUCCESS;
     178}
    79179
    80180/**
     
    228328 * @param   ...                 Errors codes that should not cause a message to be displayed.
    229329 */
    230 static SC_HANDLE autostartSvcWinOpenService(const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
     330static SC_HANDLE autostartSvcWinOpenService(const PRTUTF16 pwszServiceName, const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
    231331                                            unsigned cIgnoredErrors, ...)
    232332{
     
    235335        return NULL;
    236336
    237     SC_HANDLE hSvc = OpenServiceA(hSCM, AUTOSTART_SERVICE_NAME, dwSVCAccess);
     337    SC_HANDLE hSvc = OpenServiceW(hSCM, pwszServiceName, dwSVCAccess);
    238338    if (hSvc)
    239339    {
     
    258358                    break;
    259359                case ERROR_SERVICE_DOES_NOT_EXIST:
    260                     autostartSvcDisplayError("%s - OpenService failure: The service does not exist. Reinstall it.\n", pszAction);
     360                    autostartSvcDisplayError("%s - OpenService failure: The service %ls does not exist. Reinstall it.\n",
     361                                             pszAction, pwszServiceName);
    261362                    break;
    262363                default:
     
    356457     */
    357458    bool fVerbose = false;
     459    const char *pszUser = NULL;
    358460    static const RTGETOPTDEF s_aOptions[] =
    359461    {
    360         { "--verbose", 'v', RTGETOPT_REQ_NOTHING }
     462        { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
     463        { "--user",    'u', RTGETOPT_REQ_STRING  },
    361464    };
    362465    int ch;
    363     unsigned iArg = 0;
    364466    RTGETOPTUNION Value;
    365467    RTGETOPTSTATE GetState;
     
    372474                fVerbose = true;
    373475                break;
    374             case VINF_GETOPT_NOT_OPTION:
    375                 return autostartSvcDisplayTooManyArgsError("delete", argc, argv, iArg);
     476            case 'u':
     477                pszUser = Value.psz;
     478                break;
    376479            default:
    377                 return autostartSvcDisplayGetOptError("delete", ch, argc, argv, iArg, &Value);
    378         }
    379 
    380         iArg++;
    381     }
    382 
     480                return autostartSvcDisplayGetOptError("delete", ch, &Value);
     481        }
     482    }
     483
     484    if (!pszUser)
     485        return autostartSvcDisplayError("delete - DeleteService failed, user name required.\n");
     486
     487    com::Utf8Str sServiceName;
     488    int vrc = autostartGetServiceName(pszUser, sServiceName);
     489    if (!RT_FAILURE(vrc))
     490        return autostartSvcDisplayError("delete - DeleteService failed, service name for user %s can not be constructed.\n",
     491                                        pszUser);
    383492    /*
    384493     * Create the service.
    385494     */
    386     int rc = RTEXITCODE_FAILURE;
    387     SC_HANDLE hSvc = autostartSvcWinOpenService("delete", SERVICE_CHANGE_CONFIG, DELETE,
     495    RTEXITCODE rc = RTEXITCODE_FAILURE;
     496    SC_HANDLE hSvc = autostartSvcWinOpenService(com::Bstr(sServiceName).raw(), "delete", SERVICE_CHANGE_CONFIG, DELETE,
    388497                                                1, ERROR_SERVICE_DOES_NOT_EXIST);
    389498    if (hSvc)
     
    391500        if (DeleteService(hSvc))
    392501        {
    393             RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
     502            RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str());
    394503            rc = RTEXITCODE_SUCCESS;
    395504        }
     
    402511
    403512        if (fVerbose)
    404             RTPrintf("The service %s was not installed, nothing to be done.", AUTOSTART_SERVICE_NAME);
     513            RTPrintf("The service %s was not installed, nothing to be done.", sServiceName.c_str());
    405514        else
    406             RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
     515            RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str());
    407516        rc = RTEXITCODE_SUCCESS;
    408517    }
     
    425534    bool fVerbose = false;
    426535    const char *pszUser = NULL;
    427     const char *pszPwd = NULL;
     536    com::Utf8Str strPwd;
     537    const char *pszPwdFile = NULL;
    428538    static const RTGETOPTDEF s_aOptions[] =
    429539    {
    430         { "--verbose",  'v', RTGETOPT_REQ_NOTHING },
    431         { "--user",     'u', RTGETOPT_REQ_STRING  },
    432         { "--password", 'p', RTGETOPT_REQ_STRING  }
     540        { "--verbose",       'v', RTGETOPT_REQ_NOTHING },
     541        { "--user",          'u', RTGETOPT_REQ_STRING  },
     542        { "--password-file", 'p', RTGETOPT_REQ_STRING  }
    433543    };
    434     int iArg = 0;
    435544    int ch;
    436545    RTGETOPTUNION Value;
     
    448557                break;
    449558            case 'p':
    450                 pszPwd = Value.psz;
     559                pszPwdFile = Value.psz;
    451560                break;
    452561            default:
    453                 return autostartSvcDisplayGetOptError("create", ch, argc, argv, iArg, &Value);
    454         }
    455         iArg++;
    456     }
    457     if (iArg != argc)
    458         return autostartSvcDisplayTooManyArgsError("create", argc, argv, iArg);
     562                return autostartSvcDisplayGetOptError("create", ch, &Value);
     563        }
     564    }
     565
     566    if (!pszUser)
     567        return autostartSvcDisplayError("Username is missing");
     568
     569    if (pszPwdFile)
     570    {
     571        /* Get password from file. */
     572        RTEXITCODE rcExit = readPasswordFile(pszPwdFile, &strPwd);
     573        if (rcExit == RTEXITCODE_FAILURE)
     574            return rcExit;
     575    }
     576    else
     577    {
     578        /* Get password from console. */
     579        RTEXITCODE rcExit = readPasswordFromConsole(&strPwd, "Enter password:");
     580        if (rcExit == RTEXITCODE_FAILURE)
     581            return rcExit;
     582    }
     583
     584    if (strPwd.isEmpty())
     585        return autostartSvcDisplayError("Password is missing");
     586
     587    com::Utf8Str sDomain;
     588    com::Utf8Str sUserTmp;
     589    int vrc = autostartGetDomainAndUser(pszUser, sDomain, sUserTmp);
     590    if (RT_FAILURE(vrc))
     591        return autostartSvcDisplayError("create - CreateService failed, failed to get domain and user from string %s (%d).\n",
     592                                        pszUser, vrc);
     593    com::Utf8StrFmt sUserFullName("%s\\%s", sDomain.c_str(), sUserTmp.c_str());
     594    com::Utf8StrFmt sDisplayName("%s %s@%s", AUTOSTART_SERVICE_DISPLAY_NAME, sUserTmp.c_str(), sDomain.c_str());
     595    com::Utf8Str    sServiceName;
     596    autostartFormatServiceName(sDomain, sUserTmp, sServiceName);
    459597
    460598    /*
     
    465603    if (hSCM)
    466604    {
    467         char szExecPath[MAX_PATH];
    468         if (GetModuleFileNameA(NULL /* the executable */, szExecPath, sizeof(szExecPath)))
     605        char szExecPath[RTPATH_MAX];
     606        if (RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))
    469607        {
    470608            if (fVerbose)
    471609                RTPrintf("Creating the %s service, binary \"%s\"...\n",
    472                          AUTOSTART_SERVICE_NAME, szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */
    473 
    474             SC_HANDLE hSvc = CreateServiceA(hSCM,                            /* hSCManager */
    475                                             AUTOSTART_SERVICE_NAME,          /* lpServiceName */
    476                                             AUTOSTART_SERVICE_DISPLAY_NAME,  /* lpDisplayName */
     610                         sServiceName.c_str(), szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */
     611
     612            /*
     613             * Add service name as command line parameter for the service
     614             */
     615            com::Utf8StrFmt sCmdLine("\"%s\" --service=%s", szExecPath, sServiceName.c_str());
     616            SC_HANDLE hSvc = CreateServiceW(hSCM,                            /* hSCManager */
     617                                            com::Bstr(sServiceName).raw(),   /* lpServiceName */
     618                                            com::Bstr(sDisplayName).raw(),   /* lpDisplayName */
    477619                                            SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */
    478620                                            SERVICE_WIN32_OWN_PROCESS,       /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */
    479621                                            SERVICE_AUTO_START,              /* dwStartType */
    480622                                            SERVICE_ERROR_NORMAL,            /* dwErrorControl */
    481                                             szExecPath,                      /* lpBinaryPathName */
     623                                            com::Bstr(sCmdLine).raw(),       /* lpBinaryPathName */
    482624                                            NULL,                            /* lpLoadOrderGroup */
    483625                                            NULL,                            /* lpdwTagId */
    484626                                            NULL,                            /* lpDependencies */
    485                                             pszUser,                         /* lpServiceStartName (NULL => LocalSystem) */
    486                                             pszPwd);                         /* lpPassword */
     627                                            com::Bstr(sUserFullName).raw(),  /* lpServiceStartName (NULL => LocalSystem) */
     628                                            com::Bstr(strPwd).raw());        /* lpPassword */
    487629            if (hSvc)
    488630            {
    489                 RTPrintf("Successfully created the %s service.\n", AUTOSTART_SERVICE_NAME);
     631                RTPrintf("Successfully created the %s service.\n", sServiceName.c_str());
    490632                /** @todo Set the service description or it'll look weird in the vista service manager.
    491633                 *  Anything else that should be configured? Start access or something? */
     
    631773}
    632774
    633 static DECLCALLBACK(int) autostartWorkerThread(RTTHREAD hThreadSelf, void *pvUser)
    634 {
    635     RT_NOREF(hThreadSelf, pvUser);
     775static int autostartStartVMs()
     776{
    636777    int rc = autostartSetup();
    637778
    638     /** @todo Implement config options. */
    639     rc = autostartStartMain(NULL);
     779    const char *pszConfigFile = RTEnvGet("VBOXAUTOSTART_CONFIG");
     780    if (!pszConfigFile)
     781        return autostartSvcLogError("Starting VMs failed. VBOXAUTOSTART_CONFIG environment variable is not defined.\n");
     782    bool fAllow = false;
     783
     784    PCFGAST pCfgAst = NULL;
     785    rc = autostartParseConfig(pszConfigFile, &pCfgAst);
    640786    if (RT_FAILURE(rc))
    641         autostartSvcLogError("Starting VMs failed, rc=%Rrc", rc);
     787        return autostartSvcLogError("Starting VMs failed. Failed to parse the config file. Check the access permissions and file structure.\n");
     788
     789    PCFGAST pCfgAstPolicy = autostartConfigAstGetByName(pCfgAst, "default_policy");
     790    /* Check default policy. */
     791    if (pCfgAstPolicy)
     792    {
     793        if (   pCfgAstPolicy->enmType == CFGASTNODETYPE_KEYVALUE
     794            && (   !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "allow")
     795                || !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "deny")))
     796        {
     797            if (!RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "allow"))
     798                fAllow = true;
     799        }
     800        else
     801        {
     802            autostartConfigAstDestroy(pCfgAst);
     803            return autostartSvcLogError("'default_policy' must be either 'allow' or 'deny'.\n");
     804        }
     805    }
     806
     807    com::Utf8Str sUser;
     808    rc = autostartGetProcessDomainUser(sUser);
     809    if (RT_FAILURE(rc))
     810    {
     811        autostartConfigAstDestroy(pCfgAst);
     812        return autostartSvcLogError("Failed to query username of the process (%Rrc).\n", rc);
     813    }
     814
     815    PCFGAST pCfgAstUser = NULL;
     816    for (unsigned i = 0; i < pCfgAst->u.Compound.cAstNodes; i++)
     817    {
     818        PCFGAST pNode = pCfgAst->u.Compound.apAstNodes[i];
     819        com::Utf8Str sDomain;
     820        com::Utf8Str sUserTmp;
     821        int rc = autostartGetDomainAndUser(pNode->pszKey, sDomain, sUserTmp);
     822        if (RT_FAILURE(rc))
     823            continue;
     824        com::Utf8StrFmt sDomainUser("%s\\%s", sDomain.c_str(), sUserTmp.c_str());
     825        if (sDomainUser == sUser)
     826        {
     827            pCfgAstUser = pNode;
     828            break;
     829        }
     830    }
     831
     832    if (   pCfgAstUser
     833        && pCfgAstUser->enmType == CFGASTNODETYPE_COMPOUND)
     834    {
     835        pCfgAstPolicy = autostartConfigAstGetByName(pCfgAstUser, "allow");
     836        if (pCfgAstPolicy)
     837        {
     838            if (   pCfgAstPolicy->enmType == CFGASTNODETYPE_KEYVALUE
     839                && (   !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "true")
     840                    || !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "false")))
     841                fAllow = RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "true") == 0;
     842            else
     843            {
     844                autostartConfigAstDestroy(pCfgAst);
     845                return autostartSvcLogError("'allow' must be either 'true' or 'false'.\n");
     846            }
     847        }
     848    }
     849    else if (pCfgAstUser)
     850    {
     851        autostartConfigAstDestroy(pCfgAst);
     852        return autostartSvcLogError("Invalid config, user is not a compound node.\n");
     853    }
     854
     855    if (!fAllow)
     856    {
     857        autostartConfigAstDestroy(pCfgAst);
     858        return autostartSvcLogError("User is not allowed to autostart VMs.\n");
     859    }
     860
     861    rc = autostartStartMain(pCfgAstUser);
     862    autostartConfigAstDestroy(pCfgAst);
     863    if (RT_FAILURE(rc))
     864        autostartSvcLogError("Starting VMs failed, rc=%Rrc\n", rc);
    642865
    643866    return rc;
     
    651874 *
    652875 * @param   cArgs           Argument count.
    653  * @param   papszArgs       Argument vector.
    654  */
    655 static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPTSTR *papszArgs)
    656 {
    657     RT_NOREF(papszArgs);
     876 * @param   papwszArgs      Argument vector.
     877 */
     878static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPWSTR *papwszArgs)
     879{
     880    RT_NOREF(papwszArgs);
    658881    LogFlowFuncEnter();
    659882
     
    662885     */
    663886    Assert(g_u32SupSvcWinStatus == SERVICE_STOPPED);
    664     g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExA(AUTOSTART_SERVICE_NAME, autostartSvcWinServiceCtrlHandlerEx, NULL);
     887    g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExW(g_bstrServiceName.raw(), autostartSvcWinServiceCtrlHandlerEx, NULL);
    665888    if (g_hSupSvcWinCtrlHandler)
    666889    {
     
    682905                    if (autostartSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0))
    683906                    {
    684                         LogFlow(("autostartSvcWinServiceMain: calling RTSemEventMultiWait\n"));
    685                         RTTHREAD hWorker;
    686                         RTThreadCreate(&hWorker, autostartWorkerThread, NULL, 0, RTTHREADTYPE_DEFAULT, 0, "WorkerThread");
    687 
    688                         LogFlow(("autostartSvcWinServiceMain: woke up\n"));
    689                         err = NO_ERROR;
    690                         rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
     907                        LogFlow(("autostartSvcWinServiceMain: calling autostartStartVMs\n"));
     908                        rc = autostartStartVMs();
    691909                        if (RT_SUCCESS(rc))
    692910                        {
    693                             LogFlow(("autostartSvcWinServiceMain: woke up\n"));
    694                             /** @todo Autostop part. */
     911                            LogFlow(("autostartSvcWinServiceMain: done string VMs\n"));
    695912                            err = NO_ERROR;
     913                            rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
     914                            if (RT_SUCCESS(rc))
     915                            {
     916                                LogFlow(("autostartSvcWinServiceMain: woke up\n"));
     917                                /** @todo Autostop part. */
     918                                err = NO_ERROR;
     919                            }
     920                            else
     921                                autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
    696922                        }
    697                         else
    698                             autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
    699923
    700924                        autostartShutdown();
     
    703927                    {
    704928                        err = GetLastError();
    705                         autostartSvcLogError("SetServiceStatus failed, err=%d", err);
     929                        autostartSvcLogError("SetServiceStatus failed, err=%u", err);
    706930                    }
    707931
     
    718942        {
    719943            err = GetLastError();
    720             autostartSvcLogError("SetServiceStatus failed, err=%d", err);
     944            autostartSvcLogError("SetServiceStatus failed, err=%u", err);
    721945        }
    722946        autostartSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err);
    723947    }
    724948    else
    725         autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%d", GetLastError());
     949        autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%u", GetLastError());
    726950
    727951    LogFlowFuncLeave();
     
    750974    static const RTGETOPTDEF s_aOptions[] =
    751975    {
    752         { "--dummy", 'd', RTGETOPT_REQ_NOTHING }
     976        { "--service", 's', RTGETOPT_REQ_STRING },
    753977    };
    754     int iArg = 0;
     978
     979    const char *pszServiceName = NULL;
     980    int ch;
     981    RTGETOPTUNION Value;
     982    RTGETOPTSTATE GetState;
     983    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
     984    while ((ch = RTGetOpt(&GetState, &Value)))
     985    {
     986        switch (ch)
     987        {
     988            case 's':
     989                pszServiceName = Value.psz;
     990                try
     991                {
     992                    g_bstrServiceName = com::Bstr(Value.psz);
     993                }
     994                catch (...)
     995                {
     996                    autostartSvcLogError("runit failed, service name is not valid utf-8 string or out of memory");
     997                    return RTEXITCODE_FAILURE;
     998                }
     999                break;
     1000            default:
     1001                return autostartSvcDisplayGetOptError("runit", ch, &Value);
     1002        }
     1003    }
     1004
     1005    if (!pszServiceName)
     1006    {
     1007        autostartSvcLogError("runit failed, service name is missing");
     1008        return RTEXITCODE_FAILURE;
     1009    }
     1010
     1011    /*
     1012     * Register the service with the service control manager
     1013     * and start dispatching requests from it (all done by the API).
     1014     */
     1015    SERVICE_TABLE_ENTRYW const s_aServiceStartTable[] =
     1016    {
     1017        { g_bstrServiceName.raw(), autostartSvcWinServiceMain },
     1018        { NULL, NULL}
     1019    };
     1020    if (StartServiceCtrlDispatcherW(&s_aServiceStartTable[0]))
     1021    {
     1022        LogFlowFuncLeave();
     1023        return RTEXITCODE_SUCCESS; /* told to quit, so quit. */
     1024    }
     1025
     1026    DWORD err = GetLastError();
     1027    switch (err)
     1028    {
     1029        case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
     1030            autostartSvcWinServiceMain(0, NULL);//autostartSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");
     1031            break;
     1032        default:
     1033            autostartSvcLogError("StartServiceCtrlDispatcher failed, err=%u", err);
     1034            break;
     1035    }
     1036    return RTEXITCODE_FAILURE;
     1037}
     1038
     1039
     1040/**
     1041 * Show the version info.
     1042 *
     1043 * @returns RTEXITCODE_SUCCESS.
     1044 */
     1045static RTEXITCODE autostartSvcWinShowVersion(int argc, char **argv)
     1046{
     1047    /*
     1048     * Parse the arguments.
     1049     */
     1050    bool fBrief = false;
     1051    static const RTGETOPTDEF s_aOptions[] =
     1052    {
     1053        { "--brief", 'b', RTGETOPT_REQ_NOTHING }
     1054    };
    7551055    int ch;
    7561056    RTGETOPTUNION Value;
     
    7601060        switch (ch)
    7611061        {
    762             default:    return autostartSvcDisplayGetOptError("runit", ch, argc, argv, iArg, &Value);
    763         }
    764     if (iArg != argc)
    765         return autostartSvcDisplayTooManyArgsError("runit", argc, argv, iArg);
    766 
    767     /*
    768      * Register the service with the service control manager
    769      * and start dispatching requests from it (all done by the API).
    770      */
    771     static SERVICE_TABLE_ENTRY const s_aServiceStartTable[] =
    772     {
    773         { _T(AUTOSTART_SERVICE_NAME), autostartSvcWinServiceMain },
    774         { NULL, NULL}
    775     };
    776     if (StartServiceCtrlDispatcher(&s_aServiceStartTable[0]))
    777     {
    778         LogFlowFuncLeave();
    779         return RTEXITCODE_SUCCESS; /* told to quit, so quit. */
    780     }
    781 
    782     DWORD err = GetLastError();
    783     switch (err)
    784     {
    785         case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
    786             autostartSvcWinServiceMain(0, NULL);//autostartSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");
    787             break;
    788         default:
    789             autostartSvcLogError("StartServiceCtrlDispatcher failed, err=%d", err);
    790             break;
    791     }
    792     return RTEXITCODE_FAILURE;
    793 }
    794 
    795 
    796 /**
    797  * Show the version info.
    798  *
    799  * @returns RTEXITCODE_SUCCESS.
    800  */
    801 static RTEXITCODE autostartSvcWinShowVersion(int argc, char **argv)
    802 {
    803     /*
    804      * Parse the arguments.
    805      */
    806     bool fBrief = false;
    807     static const RTGETOPTDEF s_aOptions[] =
    808     {
    809         { "--brief", 'b', RTGETOPT_REQ_NOTHING }
    810     };
    811     int iArg = 0;
    812     int ch;
    813     RTGETOPTUNION Value;
    814     RTGETOPTSTATE GetState;
    815     RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    816     while ((ch = RTGetOpt(&GetState, &Value)))
    817         switch (ch)
    818         {
    8191062            case 'b':   fBrief = true;  break;
    820             default:    return autostartSvcDisplayGetOptError("version", ch, argc, argv, iArg, &Value);
    821 
    822         }
    823     if (iArg != argc)
    824         return autostartSvcDisplayTooManyArgsError("version", argc, argv, iArg);
     1063            default:    return autostartSvcDisplayGetOptError("version", ch, &Value);
     1064        }
    8251065
    8261066    /*
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h

    r76582 r80569  
    253253 * @todo    This should later be replaced by the release logger and callback destination(s).
    254254 */
    255 DECLHIDDEN(void) autostartSvcLogErrorV(const char *pszFormat, va_list va);
     255DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va);
    256256
    257257/**
     
    265265 * @todo    This should later be replaced by the release logger and callback destination(s).
    266266 */
    267 DECLHIDDEN(void) autostartSvcLogError(const char *pszFormat, ...);
     267DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...);
    268268
    269269/**
     
    297297 * @param   va          Format arguments.
    298298 */
    299 DECLHIDDEN(void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va);
     299DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va);
    300300
    301301/**
     
    305305 * @param   ...         Format arguments.
    306306 */
    307 DECLHIDDEN(void) autostartSvcDisplayError(const char *pszFormat, ...);
    308 
    309 /**
    310  * Deals with RTGetOpt failure.
    311  *
    312  * @returns 1
     307DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...);
     308
     309/**
     310 * Deals with RTGetOpt failure, i.e. an syntax error.
     311 *
     312 * @returns RTEXITCODE_SYNTAX
    313313 * @param   pszAction       The action name.
    314314 * @param   rc              The RTGetOpt return value.
    315  * @param   argc            The argument count.
    316  * @param   argv            The argument vector.
    317  * @param   iArg            The argument index.
    318315 * @param   pValue          The value returned by RTGetOpt.
    319316 */
    320 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg, PCRTGETOPTUNION pValue);
    321 
    322 /**
    323  * Bitch about too many arguments (after RTGetOpt stops).
    324  *
    325  * @returns RTEXITCODE_FAILURE
    326  * @param   pszAction       The action name.
    327  * @param   argc            The argument count.
    328  * @param   argv            The argument vector.
    329  * @param   iArg            The argument index.
    330  */
    331 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg);
     317DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, PCRTGETOPTUNION pValue);
    332318
    333319DECLHIDDEN(int) autostartSetup();
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp

    r76553 r80569  
    9494}
    9595
    96 DECLHIDDEN(void) autostartSvcLogErrorV(const char *pszFormat, va_list va)
     96DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va)
    9797{
    9898    if (*pszFormat)
     
    107107            autostartSvcOsLogStr(pszFormat, AUTOSTARTLOGTYPE_ERROR);
    108108    }
    109 }
    110 
    111 DECLHIDDEN(void) autostartSvcLogError(const char *pszFormat, ...)
     109    return RTEXITCODE_FAILURE;
     110}
     111
     112DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...)
    112113{
    113114    va_list va;
     
    115116    autostartSvcLogErrorV(pszFormat, va);
    116117    va_end(va);
     118    return RTEXITCODE_FAILURE;
    117119}
    118120
     
    203205}
    204206
    205 DECLHIDDEN(void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va)
     207DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va)
    206208{
    207209    RTStrmPrintf(g_pStdErr, "VBoxSupSvc error: ");
    208210    RTStrmPrintfV(g_pStdErr, pszFormat, va);
    209211    Log(("autostartSvcDisplayErrorV: %s", pszFormat)); /** @todo format it! */
    210 }
    211 
    212 DECLHIDDEN(void) autostartSvcDisplayError(const char *pszFormat, ...)
     212    return RTEXITCODE_FAILURE;
     213}
     214
     215DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...)
    213216{
    214217    va_list va;
     
    216219    autostartSvcDisplayErrorV(pszFormat, va);
    217220    va_end(va);
    218 }
    219 
    220 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg,
    221                                                       PCRTGETOPTUNION pValue)
    222 {
    223     RT_NOREF(pValue);
    224     autostartSvcDisplayError("%s - RTGetOpt failure, %Rrc (%d): %s\n",
    225                        pszAction, rc, rc, iArg < argc ? argv[iArg] : "<null>");
    226     return RTEXITCODE_FAILURE;
    227 }
    228 
    229 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg)
    230 {
    231     RT_NOREF(argc);
    232     Assert(iArg < argc);
    233     autostartSvcDisplayError("%s - Too many arguments: %s\n", pszAction, argv[iArg]);
    234     return RTEXITCODE_FAILURE;
     221    return RTEXITCODE_FAILURE;
     222}
     223
     224DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, PCRTGETOPTUNION pValue)
     225{
     226    char szMsg[4096];
     227    RTGetOptFormatError(szMsg, sizeof(szMsg), rc, pValue);
     228    autostartSvcDisplayError("%s - %s", pszAction, szMsg);
     229    return RTEXITCODE_SYNTAX;
    235230}
    236231
  • trunk/src/VBox/Frontends/VBoxBugReport/VBoxBugReport.cpp

    r78088 r80569  
    367367    handleRtError(RTProcCreateEx(m_papszArgs[0], m_papszArgs, RTENV_DEFAULT, 0,
    368368                                 NULL, &hStdOutErr, &hStdOutErr,
    369                                  NULL, NULL, &hProcess),
     369                                 NULL, NULL, NULL, &hProcess),
    370370                  "Failed to create process '%s'", m_papszArgs[0]);
    371371    RTPROCSTATUS status;
     
    444444    handleRtError(RTProcCreateEx(m_papszArgs[0], m_papszArgs, RTENV_DEFAULT, 0,
    445445                                 NULL, &hStdOutErr, &hStdOutErr,
    446                                  NULL, NULL, &hProcess),
     446                                 NULL, NULL, NULL, &hProcess),
    447447                  "Failed to create process '%s'", m_papszArgs[0]);
    448448    RTPROCSTATUS status;
  • trunk/src/VBox/Frontends/VBoxHeadless/Makefile.kmk

    r76553 r80569  
    4646VBoxHeadless_TEMPLATE  := $(if $(VBOX_WITH_HARDENING),VBOXMAINCLIENTDLL,VBOXMAINCLIENTEXE)
    4747VBoxHeadless_DEFS      += $(if $(VBOX_WITH_RECORDING),VBOX_WITH_RECORDING,)
    48 VBoxHeadless_INCS      = $(VBOX_GRAPHICS_INCS)
    49 VBoxHeadless_SOURCES    = VBoxHeadless.cpp
     48VBoxHeadless_INCS      = \
     49        $(VBOX_GRAPHICS_INCS) \
     50        ../Common
     51VBoxHeadless_SOURCES    = \
     52        VBoxHeadless.cpp \
     53        ../Common/PasswordInput.cpp
    5054ifdef VBOX_WITH_GUEST_PROPS
    5155 VBoxHeadless_DEFS     += VBOX_WITH_GUEST_PROPS
  • trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp

    r76553 r80569  
    6060#include <signal.h>
    6161#endif
     62
     63#include "PasswordInput.h"
    6264
    6365////////////////////////////////////////////////////////////////////////////////
     
    525527}
    526528#endif /* VBOX_WITH_RECORDING defined */
    527 
    528 static RTEXITCODE readPasswordFile(const char *pszFilename, com::Utf8Str *pPasswd)
    529 {
    530     size_t cbFile;
    531     char szPasswd[512];
    532     int vrc = VINF_SUCCESS;
    533     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    534     bool fStdIn = !strcmp(pszFilename, "stdin");
    535     PRTSTREAM pStrm;
    536     if (!fStdIn)
    537         vrc = RTStrmOpen(pszFilename, "r", &pStrm);
    538     else
    539         pStrm = g_pStdIn;
    540     if (RT_SUCCESS(vrc))
    541     {
    542         vrc = RTStrmReadEx(pStrm, szPasswd, sizeof(szPasswd)-1, &cbFile);
    543         if (RT_SUCCESS(vrc))
    544         {
    545             if (cbFile >= sizeof(szPasswd)-1)
    546             {
    547                 RTPrintf("Provided password in file '%s' is too long\n", pszFilename);
    548                 rcExit = RTEXITCODE_FAILURE;
    549             }
    550             else
    551             {
    552                 unsigned i;
    553                 for (i = 0; i < cbFile && !RT_C_IS_CNTRL(szPasswd[i]); i++)
    554                     ;
    555                 szPasswd[i] = '\0';
    556                 *pPasswd = szPasswd;
    557             }
    558         }
    559         else
    560         {
    561             RTPrintf("Cannot read password from file '%s': %Rrc\n", pszFilename, vrc);
    562             rcExit = RTEXITCODE_FAILURE;
    563         }
    564         if (!fStdIn)
    565             RTStrmClose(pStrm);
    566     }
    567     else
    568     {
    569         RTPrintf("Cannot open password file '%s' (%Rrc)\n", pszFilename, vrc);
    570         rcExit = RTEXITCODE_FAILURE;
    571     }
    572 
    573     return rcExit;
    574 }
    575 
    576 static RTEXITCODE settingsPasswordFile(ComPtr<IVirtualBox> virtualBox, const char *pszFilename)
    577 {
    578     com::Utf8Str passwd;
    579     RTEXITCODE rcExit = readPasswordFile(pszFilename, &passwd);
    580     if (rcExit == RTEXITCODE_SUCCESS)
    581     {
    582         int rc;
    583         CHECK_ERROR(virtualBox, SetSettingsSecret(com::Bstr(passwd).raw()));
    584         if (FAILED(rc))
    585             rcExit = RTEXITCODE_FAILURE;
    586     }
    587 
    588     return rcExit;
    589 }
    590 
    591529
    592530#ifdef RT_OS_DARWIN
  • trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk

    r77883 r80569  
    6666 VBoxManage_DEFS.win   = _WIN32_WINNT=0x0500
    6767 VBoxManage_INCS = \
    68         $(VBoxManage_0_OUTDIR)
     68        $(VBoxManage_0_OUTDIR) \
     69        ../Common
    6970 VBoxManage_INTERMEDIATES = \
    7071        $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h
     
    9495        $(if $(VBOX_WITH_NAT_SERVICE),VBoxManageNATNetwork.cpp,) \
    9596        $(if $(VBOX_WITH_NAT_SERVICE),../../NetworkServices/NetLib/VBoxNetPortForwardString.cpp,) \
    96         VBoxManageCloud.cpp
     97        VBoxManageCloud.cpp \
     98        ../Common/PasswordInput.cpp
    9799 VBoxManage_SOURCES.win = \
    98100        VBoxManage.rc
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r79611 r80569  
    365365}
    366366
    367 RTEXITCODE readPasswordFile(const char *pszFilename, com::Utf8Str *pPasswd)
    368 {
    369     size_t cbFile;
    370     char szPasswd[512];
    371     int vrc = VINF_SUCCESS;
    372     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    373     bool fStdIn = !strcmp(pszFilename, "stdin");
    374     PRTSTREAM pStrm;
    375     if (!fStdIn)
    376         vrc = RTStrmOpen(pszFilename, "r", &pStrm);
    377     else
    378         pStrm = g_pStdIn;
    379     if (RT_SUCCESS(vrc))
    380     {
    381         vrc = RTStrmReadEx(pStrm, szPasswd, sizeof(szPasswd)-1, &cbFile);
    382         if (RT_SUCCESS(vrc))
    383         {
    384             if (cbFile >= sizeof(szPasswd)-1)
    385                 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Provided password in file '%s' is too long", pszFilename);
    386             else
    387             {
    388                 unsigned i;
    389                 for (i = 0; i < cbFile && !RT_C_IS_CNTRL(szPasswd[i]); i++)
    390                     ;
    391                 szPasswd[i] = '\0';
    392                 *pPasswd = szPasswd;
    393             }
    394         }
    395         else
    396             rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Cannot read password from file '%s': %Rrc", pszFilename, vrc);
    397         if (!fStdIn)
    398             RTStrmClose(pStrm);
    399     }
    400     else
    401         rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Cannot open password file '%s' (%Rrc)", pszFilename, vrc);
    402 
    403     return rcExit;
    404 }
    405 
    406 static RTEXITCODE settingsPasswordFile(ComPtr<IVirtualBox> virtualBox, const char *pszFilename)
    407 {
    408     com::Utf8Str passwd;
    409     RTEXITCODE rcExit = readPasswordFile(pszFilename, &passwd);
    410     if (rcExit == RTEXITCODE_SUCCESS)
    411     {
    412         CHECK_ERROR2I_STMT(virtualBox, SetSettingsSecret(com::Bstr(passwd).raw()), rcExit = RTEXITCODE_FAILURE);
    413     }
    414 
    415     return rcExit;
    416 }
    417 
    418 RTEXITCODE readPasswordFromConsole(com::Utf8Str *pPassword, const char *pszPrompt, ...)
    419 {
    420     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    421     char aszPwdInput[_1K] = { 0 };
    422     va_list vaArgs;
    423 
    424     va_start(vaArgs, pszPrompt);
    425     int vrc = RTStrmPrintfV(g_pStdOut, pszPrompt, vaArgs);
    426     if (RT_SUCCESS(vrc))
    427     {
    428         bool fEchoOld = false;
    429         vrc = RTStrmInputGetEchoChars(g_pStdIn, &fEchoOld);
    430         if (RT_SUCCESS(vrc))
    431         {
    432             vrc = RTStrmInputSetEchoChars(g_pStdIn, false);
    433             if (RT_SUCCESS(vrc))
    434             {
    435                 vrc = RTStrmGetLine(g_pStdIn, &aszPwdInput[0], sizeof(aszPwdInput));
    436                 if (RT_SUCCESS(vrc))
    437                     *pPassword = aszPwdInput;
    438                 else
    439                     rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed read password from command line (%Rrc)", vrc);
    440 
    441                 int vrc2 = RTStrmInputSetEchoChars(g_pStdIn, fEchoOld);
    442                 AssertRC(vrc2);
    443             }
    444             else
    445                 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to disable echoing typed characters (%Rrc)", vrc);
    446         }
    447         else
    448             rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to retrieve echo setting (%Rrc)", vrc);
    449 
    450         RTStrmPutStr(g_pStdOut, "\n");
    451     }
    452     else
    453         rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to print prompt (%Rrc)", vrc);
    454     va_end(vaArgs);
    455 
    456     return rcExit;
    457 }
    458 
    459367#endif /* !VBOX_ONLY_DOCS */
    460368
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r79796 r80569  
    3737#ifndef VBOX_ONLY_DOCS
    3838# include "VBoxManageBuiltInHelp.h"
     39# include "PasswordInput.h"
    3940#endif
    4041
     
    218219
    219220#ifndef VBOX_ONLY_DOCS
    220 RTEXITCODE readPasswordFile(const char *pszFilename, com::Utf8Str *pPasswd);
    221 RTEXITCODE readPasswordFromConsole(com::Utf8Str *pPassword, const char *pszPrompt, ...);
    222 
    223221RTEXITCODE handleInternalCommands(HandlerArg *a);
    224222#endif /* !VBOX_ONLY_DOCS */
  • trunk/src/VBox/Frontends/VBoxSDL/Makefile.kmk

    r76553 r80569  
    4646        VBoxSDL.cpp \
    4747        Framebuffer.cpp \
    48         Helper.cpp
     48        Helper.cpp \
     49        ../Common/PasswordInput.cpp
    4950VBoxSDL_SOURCES.darwin = \
    5051        VBoxSDLMain-darwin.m \
     
    7071VBoxSDL_INCS = \
    7172        $(VBoxSDL_0_OUTDIR) \
    72         $(VBOX_GRAPHICS_INCS)
     73        $(VBOX_GRAPHICS_INCS) \
     74        ../Common
    7375ifeq ($(filter-out freebsd linux netbsd openbsd solaris,$(KBUILD_TARGET)),) # X11
    7476VBoxSDL_INCS += \
  • trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp

    r78995 r80569  
    8989#include <vector>
    9090#include <list>
     91
     92#include "PasswordInput.h"
    9193
    9294/* Xlib would re-define our enums */
     
    170172static int     WaitSDLEvent(SDL_Event *event);
    171173static void    SetFullscreen(bool enable);
    172 static RTEXITCODE readPasswordFile(const char *pszFilename, com::Utf8Str *pPasswd);
    173 static RTEXITCODE settingsPasswordFile(ComPtr<IVirtualBox> virtualBox, const char *pszFilename);
    174174
    175175#ifdef VBOX_WITH_SDL13
     
    31203120    RTLogFlush(NULL);
    31213121    return FAILED(rc) ? 1 : 0;
    3122 }
    3123 
    3124 static RTEXITCODE readPasswordFile(const char *pszFilename, com::Utf8Str *pPasswd)
    3125 {
    3126     size_t cbFile;
    3127     char szPasswd[512];
    3128     int vrc = VINF_SUCCESS;
    3129     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    3130     bool fStdIn = !strcmp(pszFilename, "stdin");
    3131     PRTSTREAM pStrm;
    3132     if (!fStdIn)
    3133         vrc = RTStrmOpen(pszFilename, "r", &pStrm);
    3134     else
    3135         pStrm = g_pStdIn;
    3136     if (RT_SUCCESS(vrc))
    3137     {
    3138         vrc = RTStrmReadEx(pStrm, szPasswd, sizeof(szPasswd)-1, &cbFile);
    3139         if (RT_SUCCESS(vrc))
    3140         {
    3141             if (cbFile >= sizeof(szPasswd)-1)
    3142             {
    3143                 RTPrintf("Provided password in file '%s' is too long\n", pszFilename);
    3144                 rcExit = RTEXITCODE_FAILURE;
    3145             }
    3146             else
    3147             {
    3148                 unsigned i;
    3149                 for (i = 0; i < cbFile && !RT_C_IS_CNTRL(szPasswd[i]); i++)
    3150                     ;
    3151                 szPasswd[i] = '\0';
    3152                 *pPasswd = szPasswd;
    3153             }
    3154         }
    3155         else
    3156         {
    3157             RTPrintf("Cannot read password from file '%s': %Rrc\n", pszFilename, vrc);
    3158             rcExit = RTEXITCODE_FAILURE;
    3159         }
    3160         if (!fStdIn)
    3161             RTStrmClose(pStrm);
    3162     }
    3163     else
    3164     {
    3165         RTPrintf("Cannot open password file '%s' (%Rrc)\n", pszFilename, vrc);
    3166         rcExit = RTEXITCODE_FAILURE;
    3167     }
    3168 
    3169     return rcExit;
    3170 }
    3171 
    3172 static RTEXITCODE settingsPasswordFile(ComPtr<IVirtualBox> virtualBox, const char *pszFilename)
    3173 {
    3174     com::Utf8Str passwd;
    3175     RTEXITCODE rcExit = readPasswordFile(pszFilename, &passwd);
    3176     if (rcExit == RTEXITCODE_SUCCESS)
    3177     {
    3178         int rc;
    3179         CHECK_ERROR(virtualBox, SetSettingsSecret(com::Bstr(passwd).raw()));
    3180         if (FAILED(rc))
    3181             rcExit = RTEXITCODE_FAILURE;
    3182     }
    3183 
    3184     return rcExit;
    31853122}
    31863123
  • trunk/src/VBox/Main/Makefile.kmk

    r80398 r80569  
    385385VBoxSDS_TEMPLATE = VBOXMAINEXE
    386386VBoxSDS_DEFS += VBOX_COM_OUTOFPROC_MODULE _WIN32_WINNT=0x0600
     387 ifdef VBOX_WITH_VBOXSDL
     388VBoxSDS_DEFS += VBOX_WITH_VBOXSDL
     389 endif
     390 ifdef VBOX_WITH_HEADLESS
     391VBoxSDS_DEFS += VBOX_WITH_HEADLESS
     392 endif
     393 ifdef VBOX_WITH_QTGUI
     394VBoxSDS_DEFS += VBOX_WITH_QTGUI
     395 endif
    387396VBoxSDS_INCS  = \
    388397        include \
     
    394403        src-global/win/VBoxSDS.cpp \
    395404        src-global/win/VirtualBoxSDSImpl.cpp \
    396         src-global/win/VBoxSDS.rc
     405        src-global/win/VBoxSDS.rc \
     406        src-all/MachineLaunchVMCommonWorker.cpp
    397407$(call KB_FN_DO_PASS0_ON_TARGET,VBoxSDS) # Sets VBoxSDS_0_OUTDIR
    398408
     
    553563        src-server/HostVideoInputDeviceImpl.cpp \
    554564        src-server/MachineImpl.cpp \
     565        src-all/MachineLaunchVMCommonWorker.cpp \
    555566        src-server/MachineImplCloneVM.cpp \
    556567        src-server/MachineImplMoveVM.cpp \
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r80426 r80569  
    2703327033  <interface
    2703427034    name="IVirtualBoxSDS" extends="$unknown" notdual="yes"
    27035     uuid="152265b8-fe7d-4077-9dd6-032bc3f1c5a3"
     27035    uuid="bc1a2773-18f2-4066-08ce-1e44d59d84af"
    2703627036    wsmap="suppress" internal="yes"
    2703727037    reservedMethods="0" reservedAttributes="0"
     
    2706827068        <param name="pid" type="long" dir="in">
    2706927069          <desc>The process ID of the VBoxSVC instance (same as during registration).</desc>
     27070        </param>
     27071      </method>
     27072
     27073      <method name="launchVMProcess">
     27074        <desc>
     27075          Spawns a new process that will execute the virtual machine in the interactive
     27076          windows session of calling user. Any additional checks are performed by created
     27077          process itself
     27078
     27079          If launching the VM succeeds, the new VM process will create its own session
     27080          and write-lock the machine for it, preventing conflicting changes from other
     27081          processes. If the machine is already locked (because it is already running or
     27082          because another session has a write lock), launching the VM process will therefore
     27083          fail. Reversely, future attempts to obtain a write lock will also fail while the
     27084          machine is running.
     27085
     27086          Launching a VM process can take some time (a new VM is started in a new process,
     27087          for which memory and other resources need to be set up) but the method does
     27088          not wait for completion and just returns the PID of created process.
     27089
     27090          <result name="E_INVALIDARG">
     27091            Some of the parameters are invalid.
     27092          </result>
     27093          <result name="VBOX_E_IPRT_ERROR">
     27094            Launching process for machine failed.
     27095          </result>
     27096        </desc>
     27097        <param name="machine" type="wstring" dir="in">
     27098          <desc>
     27099            The name or id of the machine the VM will start for.
     27100          </desc>
     27101        </param>
     27102        <param name="comment" type="wstring" dir="in">
     27103          <desc>
     27104            The comment for VM.
     27105          </desc>
     27106        </param>
     27107        <param name="frontend" type="wstring" dir="in">
     27108          <desc>
     27109            Front-end to use for the new VM process. The following are currently supported:
     27110            <ul>
     27111              <li><tt>"gui"</tt>: VirtualBox Qt GUI front-end</li>
     27112              <li><tt>"headless"</tt>: VBoxHeadless (VRDE Server) front-end</li>
     27113              <li><tt>"sdl"</tt>: VirtualBox SDL front-end</li>
     27114              <li><tt>""</tt>: use the per-VM default frontend if set, otherwise
     27115                the global default defined in the system properties. If neither
     27116                are set, the API will launch a <tt>"gui"</tt> session, which may
     27117                fail if there is no windowing environment available. See
     27118                <link to="IMachine::defaultFrontend"/> and
     27119                <link to="ISystemProperties::defaultFrontend"/>.</li>
     27120            </ul>
     27121          </desc>
     27122        </param>
     27123        <param name="environmentChanges" type="wstring" dir="in">
     27124          <desc>
     27125            Environment changes to pass to the VM process, putenv style using newline as separator.
     27126            <!-- TODO: make this a safearray so values can safely contain newlines and '\'. -->
     27127          </desc>
     27128        </param>
     27129        <param name="cmdOptions" type="wstring" dir="in">
     27130          <desc>
     27131            Additional command line options to pass to the VM process.
     27132          </desc>
     27133        </param>
     27134        <param name="sessionId" type="unsigned long" dir="in">
     27135          <desc>
     27136            Windows session where the VM process should be launched.
     27137          </desc>
     27138        </param>
     27139        <param name="pid" type="unsigned long" dir="return">
     27140          <desc>The PID of created process.</desc>
    2707027141        </param>
    2707127142      </method>
  • trunk/src/VBox/Main/include/VirtualBoxSDSImpl.h

    r76562 r80569  
    9494    STDMETHOD(RegisterVBoxSVC)(IVBoxSVCRegistration *aVBoxSVC, LONG aPid, IUnknown **aExistingVirtualBox);
    9595    STDMETHOD(DeregisterVBoxSVC)(IVBoxSVCRegistration *aVBoxSVC, LONG aPid);
     96    STDMETHOD(LaunchVMProcess)(IN_BSTR aMachine, IN_BSTR aComment, IN_BSTR aFrontend, IN_BSTR aEnvironmentChanges,
     97                               IN_BSTR aCmdOptions, ULONG aSessionId, ULONG *aPid);
    9698    /** @} */
    9799
  • trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp

    r77624 r80569  
    25082508                         NULL /*pszAsUser*/,
    25092509                         NULL /*pszPassword*/,
     2510                         NULL /*pvExtraData*/,
    25102511                         &hProcess);
    25112512    if (RT_SUCCESS(vrc))
  • trunk/src/VBox/Main/src-client/ClientTokenHolder.cpp

    r77436 r80569  
    250250    HANDLE initDoneSem = (HANDLE)data[1];
    251251
    252     HANDLE mutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, Bstr(strSessionId).raw());
    253     AssertMsg(mutex, ("cannot open token, err=%d\n", ::GetLastError()));
    254 
     252    Bstr bstrSessionId(strSessionId);
     253    HANDLE mutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, bstrSessionId.raw());
     254
     255    //AssertMsg(mutex, ("cannot open token, err=%u\n", ::GetLastError()));
     256    AssertMsg(mutex, ("cannot open token %ls, err=%u\n", bstrSessionId.raw(), ::GetLastError()));
    255257    if (mutex)
    256258    {
  • trunk/src/VBox/Main/src-global/win/VirtualBoxSDSImpl.cpp

    r76592 r80569  
    3131#include <iprt/critsect.h>
    3232#include <iprt/mem.h>
     33#include <iprt/process.h>
    3334#include <iprt/system.h>
    3435
     
    3738#include <sddl.h>
    3839#include <lmcons.h> /* UNLEN */
     40
     41#include "MachineLaunchVMCommonWorker.h"
     42
     43
     44/*********************************************************************************************************************************
     45*   Defined Constants And Macros                                                                                                 *
     46*********************************************************************************************************************************/
     47#define INTERACTIVE_SID_FLAG 0x1
     48#define LOCAL_SID_FLAG       0x2
     49#define LOGON_SID_FLAG       0x4
     50#define IS_INTERACTIVE       (LOCAL_SID_FLAG|INTERACTIVE_SID_FLAG|LOGON_SID_FLAG)
    3951
    4052
     
    388400        hrc = E_INVALIDARG;
    389401    LogRel2(("VirtualBoxSDS::deregisterVBoxSVC: returns %Rhrc\n", hrc));
     402    return hrc;
     403}
     404
     405
     406STDMETHODIMP VirtualBoxSDS::LaunchVMProcess(IN_BSTR aMachine, IN_BSTR aComment, IN_BSTR aFrontend, IN_BSTR aEnvironmentChanges,
     407                                            IN_BSTR aCmdOptions, ULONG aSessionId, ULONG *aPid)
     408{
     409    /*
     410     * Convert parameters to UTF-8.
     411     */
     412    Utf8Str strMachine(aMachine);
     413    Utf8Str strComment(aComment);
     414    Utf8Str strFrontend(aFrontend);
     415    Utf8Str strEnvironmentChanges(aEnvironmentChanges);
     416    Utf8Str strCmdOptions(aCmdOptions);
     417
     418    /*
     419     * Impersonate the caller.
     420     */
     421    HRESULT hrc = CoImpersonateClient();
     422    if (SUCCEEDED(hrc))
     423    {
     424        try
     425        {
     426            /*
     427             * Try launch the VM process as the client.
     428             */
     429            RTPROCESS pid;
     430            AssertCompile(sizeof(aSessionId) == sizeof(uint32_t));
     431            int vrc = ::MachineLaunchVMCommonWorker(strMachine, strComment, strFrontend, strEnvironmentChanges,
     432                                                    strCmdOptions, Utf8Str(),
     433                                                    RTPROC_FLAGS_AS_IMPERSONATED_TOKEN | RTPROC_FLAGS_SERVICE
     434                                                    | RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_DESIRED_SESSION_ID,
     435                                                    &aSessionId, pid);
     436            if (RT_SUCCESS(vrc))
     437            {
     438                *aPid = (ULONG)pid;
     439                LogRel(("VirtualBoxSDS::LaunchVMProcess: launchVM succeeded\n"));
     440            }
     441            else if (vrc == VERR_INVALID_PARAMETER)
     442            {
     443                hrc = E_INVALIDARG;
     444                LogRel(("VirtualBoxSDS::LaunchVMProcess: launchVM failed: %Rhrc\n", hrc));
     445            }
     446            else
     447            {
     448                hrc = VBOX_E_IPRT_ERROR;
     449                LogRel(("VirtualBoxSDS::LaunchVMProcess: launchVM failed: %Rhrc (%Rrc)\n", hrc));
     450            }
     451        }
     452        catch (...)
     453        {
     454            hrc = E_UNEXPECTED;
     455        }
     456        CoRevertToSelf();
     457    }
     458    else
     459        LogRel(("VirtualBoxSDS::LaunchVMProcess: CoImpersonateClient failed: %Rhrc\n", hrc));
    390460    return hrc;
    391461}
     
    592662}
    593663
     664
    594665#ifdef WITH_WATCHER
    595666/**
  • trunk/src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp

    r77178 r80569  
    15481548         */
    15491549        RTPROCESS hProcess;
    1550         rc = RTProcCreateEx(papszArgs[iSuArg], &papszArgs[iSuArg], RTENV_DEFAULT, 0 /*fFlags*/,
    1551                             NULL /*phStdIn*/, NULL /*phStdOut*/, NULL /*phStdErr*/, NULL /*pszAsUser*/, NULL /*pszPassword*/,
     1550        rc = RTProcCreateEx(papszArgs[iSuArg], &papszArgs[iSuArg], RTENV_DEFAULT, 0 /*fFlags*/, NULL /*phStdIn*/,
     1551                            NULL /*phStdOut*/, NULL /*phStdErr*/, NULL /*pszAsUser*/, NULL /*pszPassword*/, NULL /* pvExtraData*/,
    15521552                            &hProcess);
    15531553        if (RT_SUCCESS(rc))
  • trunk/src/VBox/Main/src-server/ClientToken.cpp

    r76553 r80569  
    4040#include "ClientToken.h"
    4141#include "MachineImpl.h"
     42
     43#ifdef RT_OS_WINDOWS
     44# include <sddl.h>
     45#endif
    4246
    4347Machine::ClientToken::ClientToken()
     
    8387#if defined(RT_OS_WINDOWS)
    8488    NOREF(pSessionMachine);
    85     Bstr tokenId = pMachine->mData->m_strConfigFileFull;
    86     for (size_t i = 0; i < tokenId.length(); i++)
    87         if (tokenId.raw()[i] == '\\')
    88             tokenId.raw()[i] = '/';
    89     mClientToken = ::CreateMutex(NULL, FALSE, tokenId.raw());
     89
     90    /* Get user's SID to use it as part of the mutex name to distinguish shared machine instances
     91     * between users
     92     */
     93    Utf8Str strUserSid;
     94    HANDLE  hProcessToken = INVALID_HANDLE_VALUE;
     95    if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hProcessToken))
     96    {
     97        DWORD dwSize = 0;
     98        BOOL fRc = ::GetTokenInformation(hProcessToken, TokenUser, NULL, 0, &dwSize);
     99        DWORD dwErr = ::GetLastError();
     100        if (!fRc && dwErr == ERROR_INSUFFICIENT_BUFFER && dwSize > 0)
     101        {
     102            PTOKEN_USER pTokenUser = (PTOKEN_USER)RTMemTmpAllocZ(dwSize);
     103            if (pTokenUser)
     104            {
     105                if (::GetTokenInformation(hProcessToken, TokenUser, pTokenUser, dwSize, &dwSize))
     106                {
     107                    PRTUTF16 wstrSid = NULL;
     108                    if (::ConvertSidToStringSid(pTokenUser->User.Sid, &wstrSid))
     109                    {
     110                        strUserSid = wstrSid;
     111                        ::LocalFree(wstrSid);
     112                    }
     113                    else
     114                        AssertMsgFailed(("Cannot convert SID to string, err=%u", ::GetLastError()));
     115                }
     116                else
     117                    AssertMsgFailed(("Cannot get thread access token information, err=%u", ::GetLastError()));
     118                RTMemFree(pTokenUser);
     119            }
     120            else
     121                AssertMsgFailed(("No memory"));
     122        }
     123        else
     124            AssertMsgFailed(("Cannot get thread access token information, err=%u", ::GetLastError()));
     125        CloseHandle(hProcessToken);
     126    }
     127    else
     128        AssertMsgFailed(("Cannot get thread access token, err=%u", ::GetLastError()));
     129
     130    Bstr tokenId = Bstr(Utf8Str("Global\\") + strUserSid + "/" + pMachine->mData->mUuid.toString());
     131
     132    /* create security descriptor to allow SYNCHRONIZE access from any windows sessions and users.
     133     * otherwise VM can't open the mutex if VBoxSVC and VM are in different session (e.g. some VM
     134     * started by autostart service)
     135     *
     136     * SDDL string contains following ACEs:
     137     *   CreateOwner           : MUTEX_ALL_ACCESS
     138     *   System                : MUTEX_ALL_ACCESS
     139     *   BuiltInAdministrators : MUTEX_ALL_ACCESS
     140     *   Everyone              : SYNCHRONIZE|MUTEX_MODIFY_STATE
     141     */
     142
     143    //static const RTUTF16 s_wszSecDesc[] = L"D:(A;;0x1F0001;;;CO)(A;;0x1F0001;;;SY)(A;;0x1F0001;;;BA)(A;;0x100001;;;WD)";
     144    com::BstrFmt bstrSecDesc("O:%sD:(A;;0x1F0001;;;CO)(A;;0x1F0001;;;SY)(A;;0x1F0001;;;BA)", strUserSid.c_str());
     145    PSECURITY_DESCRIPTOR pSecDesc = NULL;
     146    //AssertMsgStmt(::ConvertStringSecurityDescriptorToSecurityDescriptor(s_wszSecDesc, SDDL_REVISION_1, &pSecDesc, NULL),
     147    AssertMsgStmt(::ConvertStringSecurityDescriptorToSecurityDescriptor(bstrSecDesc.raw(), SDDL_REVISION_1, &pSecDesc, NULL),
     148                  ("Cannot create security descriptor for token '%ls', err=%u", tokenId.raw(), GetLastError()),
     149                  pSecDesc = NULL);
     150
     151    SECURITY_ATTRIBUTES SecAttr;
     152    SecAttr.lpSecurityDescriptor = pSecDesc;
     153    SecAttr.nLength              = sizeof(SecAttr);
     154    SecAttr.bInheritHandle       = FALSE;
     155    mClientToken = ::CreateMutex(&SecAttr, FALSE, tokenId.raw());
    90156    mClientTokenId = tokenId;
    91     AssertMsg(mClientToken,
    92               ("Cannot create token '%s', err=%d",
    93                mClientTokenId.c_str(), ::GetLastError()));
     157    AssertMsg(mClientToken, ("Cannot create token '%s', err=%d", mClientTokenId.c_str(), ::GetLastError()));
     158
     159    if (pSecDesc)
     160        ::LocalFree(pSecDesc);
     161
    94162#elif defined(RT_OS_OS2)
    95163    NOREF(pSessionMachine);
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r80074 r80569  
    4949#include "MachineImplMoveVM.h"
    5050#include "ExtPackManagerImpl.h"
     51#include "MachineLaunchVMCommonWorker.h"
    5152
    5253// generated header
     
    74097410    }
    74107411
    7411     /* get the path to the executable */
    7412     char szPath[RTPATH_MAX];
    7413     RTPathAppPrivateArch(szPath, sizeof(szPath) - 1);
    7414     size_t cchBufLeft = strlen(szPath);
    7415     szPath[cchBufLeft++] = RTPATH_DELIMITER;
    7416     szPath[cchBufLeft] = 0;
    7417     char *pszNamePart = szPath + cchBufLeft;
    7418     cchBufLeft = sizeof(szPath) - cchBufLeft;
    7419 
    7420     int vrc = VINF_SUCCESS;
    7421     RTPROCESS pid = NIL_RTPROCESS;
    7422 
    7423     RTENV env = RTENV_DEFAULT;
    7424 
    7425     if (!strEnvironment.isEmpty())
    7426     {
    7427         char *newEnvStr = NULL;
    7428 
    7429         do
    7430         {
    7431             /* clone the current environment */
    7432             int vrc2 = RTEnvClone(&env, RTENV_DEFAULT);
    7433             AssertRCBreakStmt(vrc2, vrc = vrc2);
    7434 
    7435             newEnvStr = RTStrDup(strEnvironment.c_str());
    7436             AssertPtrBreakStmt(newEnvStr, vrc = vrc2);
    7437 
    7438             /* put new variables to the environment
    7439              * (ignore empty variable names here since RTEnv API
    7440              * intentionally doesn't do that) */
    7441             char *var = newEnvStr;
    7442             for (char *p = newEnvStr; *p; ++p)
    7443             {
    7444                 if (*p == '\n' && (p == newEnvStr || *(p - 1) != '\\'))
    7445                 {
    7446                     *p = '\0';
    7447                     if (*var)
    7448                     {
    7449                         char *val = strchr(var, '=');
    7450                         if (val)
    7451                         {
    7452                             *val++ = '\0';
    7453                             vrc2 = RTEnvSetEx(env, var, val);
    7454                         }
    7455                         else
    7456                             vrc2 = RTEnvUnsetEx(env, var);
    7457                         if (RT_FAILURE(vrc2))
    7458                             break;
    7459                     }
    7460                     var = p + 1;
    7461                 }
    7462             }
    7463             if (RT_SUCCESS(vrc2) && *var)
    7464                 vrc2 = RTEnvPutEx(env, var);
    7465 
    7466             AssertRCBreakStmt(vrc2, vrc = vrc2);
    7467         }
    7468         while (0);
    7469 
    7470         if (newEnvStr != NULL)
    7471             RTStrFree(newEnvStr);
    7472     }
    7473 
    74747412    /* Hardening logging */
    74757413#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_HARDENING)
     
    74937431        RTFileDelete(strOldStartupLogFile.c_str());
    74947432    }
    7495     const char *pszSupHardeningLogArg = strSupHardeningLogArg.c_str();
    74967433#else
    7497     const char *pszSupHardeningLogArg = NULL;
     7434    Utf8Str strSupHardeningLogArg;
    74987435#endif
    74997436
     7437    Utf8Str strAppOverride;
     7438#ifdef RT_OS_DARWIN /* Avoid Launch Services confusing this with the selector by using a helper app. */
     7439    strAppOverride = i_getExtraData(Utf8Str("VBoxInternal2/VirtualBoxVMAppOverride"));
     7440#endif
     7441
     7442    bool fUseVBoxSDS = false;
    75007443    Utf8Str strCanonicalName;
    7501 
     7444    if (false)
     7445    { }
    75027446#ifdef VBOX_WITH_QTGUI
    7503     if (   !strFrontend.compare("gui", Utf8Str::CaseInsensitive)
    7504         || !strFrontend.compare("GUI/Qt", Utf8Str::CaseInsensitive)
    7505         || !strFrontend.compare("separate", Utf8Str::CaseInsensitive)
    7506         || !strFrontend.compare("gui/separate", Utf8Str::CaseInsensitive)
    7507         || !strFrontend.compare("GUI/Qt/separate", Utf8Str::CaseInsensitive))
     7447    else if (   !strFrontend.compare("gui", Utf8Str::CaseInsensitive)
     7448             || !strFrontend.compare("GUI/Qt", Utf8Str::CaseInsensitive)
     7449             || !strFrontend.compare("separate", Utf8Str::CaseInsensitive)
     7450             || !strFrontend.compare("gui/separate", Utf8Str::CaseInsensitive)
     7451             || !strFrontend.compare("GUI/Qt/separate", Utf8Str::CaseInsensitive))
    75087452    {
    75097453        strCanonicalName = "GUI/Qt";
    7510 # ifdef RT_OS_DARWIN /* Avoid Launch Services confusing this with the selector by using a helper app. */
    7511         /* Modify the base path so that we don't need to use ".." below. */
    7512         RTPathStripTrailingSlash(szPath);
    7513         RTPathStripFilename(szPath);
    7514         cchBufLeft = strlen(szPath);
    7515         pszNamePart = szPath + cchBufLeft;
    7516         cchBufLeft = sizeof(szPath) - cchBufLeft;
    7517 
    7518 #  define OSX_APP_NAME "VirtualBoxVM"
    7519 #  define OSX_APP_PATH_FMT "/Resources/%s.app/Contents/MacOS/VirtualBoxVM"
    7520 
    7521         Utf8Str strAppOverride = i_getExtraData(Utf8Str("VBoxInternal2/VirtualBoxVMAppOverride"));
    7522         if (   strAppOverride.contains(".")
    7523             || strAppOverride.contains("/")
    7524             || strAppOverride.contains("\\")
    7525             || strAppOverride.contains(":"))
    7526             strAppOverride.setNull();
    7527         Utf8Str strAppPath;
    7528         if (!strAppOverride.isEmpty())
    7529         {
    7530             strAppPath = Utf8StrFmt(OSX_APP_PATH_FMT, strAppOverride.c_str());
    7531             Utf8Str strFullPath(szPath);
    7532             strFullPath.append(strAppPath);
    7533             /* there is a race, but people using this deserve the failure */
    7534             if (!RTFileExists(strFullPath.c_str()))
    7535                 strAppOverride.setNull();
    7536         }
    7537         if (strAppOverride.isEmpty())
    7538             strAppPath = Utf8StrFmt(OSX_APP_PATH_FMT, OSX_APP_NAME);
    7539         AssertReturn(cchBufLeft > strAppPath.length(), E_UNEXPECTED);
    7540         strcpy(pszNamePart, strAppPath.c_str());
    7541 # else
    7542         static const char s_szVirtualBox_exe[] = "VirtualBoxVM" HOSTSUFF_EXE;
    7543         Assert(cchBufLeft >= sizeof(s_szVirtualBox_exe));
    7544         strcpy(pszNamePart, s_szVirtualBox_exe);
    7545 # endif
    7546 
    7547         Utf8Str idStr = mData->mUuid.toString();
    7548         const char *apszArgs[] =
    7549         {
    7550             szPath,
    7551             "--comment", mUserData->s.strName.c_str(),
    7552             "--startvm", idStr.c_str(),
    7553             "--no-startvm-errormsgbox",
    7554             NULL, /* For "--separate". */
    7555             NULL, /* For "--sup-startup-log". */
    7556             NULL
    7557         };
    7558         unsigned iArg = 6;
    7559         if (fSeparate)
    7560             apszArgs[iArg++] = "--separate";
    7561         apszArgs[iArg++] = pszSupHardeningLogArg;
    7562 
    7563         vrc = RTProcCreate(szPath, apszArgs, env, 0, &pid);
    7564     }
    7565 #else /* !VBOX_WITH_QTGUI */
    7566     if (0)
    7567         ;
    7568 #endif /* VBOX_WITH_QTGUI */
    7569 
     7454        fUseVBoxSDS = true;
     7455    }
     7456#endif
     7457#ifdef VBOX_WITH_VBOXSDL
     7458    else if (   !strFrontend.compare("sdl", Utf8Str::CaseInsensitive)
     7459             || !strFrontend.compare("GUI/SDL", Utf8Str::CaseInsensitive)
     7460             || !strFrontend.compare("sdl/separate", Utf8Str::CaseInsensitive)
     7461             || !strFrontend.compare("GUI/SDL/separate", Utf8Str::CaseInsensitive))
     7462    {
     7463        strCanonicalName = "GUI/SDL";
     7464        fUseVBoxSDS = true;
     7465    }
     7466#endif
     7467#ifdef VBOX_WITH_HEADLESS
     7468    else if (   !strFrontend.compare("headless", Utf8Str::CaseInsensitive)
     7469             || !strFrontend.compare("capture", Utf8Str::CaseInsensitive)
     7470             || !strFrontend.compare("vrdp", Utf8Str::CaseInsensitive) /* Deprecated. Same as headless. */)
     7471    {
     7472        strCanonicalName = "headless";
     7473    }
     7474#endif
    75707475    else
    7571 
    7572 #ifdef VBOX_WITH_VBOXSDL
    7573     if (   !strFrontend.compare("sdl", Utf8Str::CaseInsensitive)
    7574         || !strFrontend.compare("GUI/SDL", Utf8Str::CaseInsensitive)
    7575         || !strFrontend.compare("sdl/separate", Utf8Str::CaseInsensitive)
    7576         || !strFrontend.compare("GUI/SDL/separate", Utf8Str::CaseInsensitive))
    7577     {
    7578         strCanonicalName = "GUI/SDL";
    7579         static const char s_szVBoxSDL_exe[] = "VBoxSDL" HOSTSUFF_EXE;
    7580         Assert(cchBufLeft >= sizeof(s_szVBoxSDL_exe));
    7581         strcpy(pszNamePart, s_szVBoxSDL_exe);
    7582 
    7583         Utf8Str idStr = mData->mUuid.toString();
    7584         const char *apszArgs[] =
    7585         {
    7586             szPath,
    7587             "--comment", mUserData->s.strName.c_str(),
    7588             "--startvm", idStr.c_str(),
    7589             NULL, /* For "--separate". */
    7590             NULL, /* For "--sup-startup-log". */
    7591             NULL
    7592         };
    7593         unsigned iArg = 5;
    7594         if (fSeparate)
    7595             apszArgs[iArg++] = "--separate";
    7596         apszArgs[iArg++] = pszSupHardeningLogArg;
    7597 
    7598         vrc = RTProcCreate(szPath, apszArgs, env, 0, &pid);
    7599     }
    7600 #else /* !VBOX_WITH_VBOXSDL */
    7601     if (0)
    7602         ;
    7603 #endif /* !VBOX_WITH_VBOXSDL */
    7604 
     7476        return setError(E_INVALIDARG, tr("Invalid frontend name: '%s'"), strFrontend.c_str());
     7477
     7478    Utf8Str idStr = mData->mUuid.toString();
     7479    Utf8Str const &strMachineName = mUserData->s.strName;
     7480    RTPROCESS pid = NIL_RTPROCESS;
     7481
     7482#if !defined(VBOX_WITH_SDS) || !defined(RT_OS_WINDOWS)
     7483    RT_NOREF(fUseVBoxSDS);
     7484#else
     7485    DWORD idCallerSession = ~(DWORD)0;
     7486    if (fUseVBoxSDS)
     7487    {
     7488        /*
     7489         * The VBoxSDS should be used for process launching the VM with
     7490         * GUI only if the caller and the VBoxSDS are in different Windows
     7491         * sessions and the caller in the interactive one.
     7492         */
     7493        fUseVBoxSDS = false;
     7494
     7495        /* Get windows session of the current process.  The process token used
     7496           due to several reasons:
     7497           1. The token is absent for the current thread except someone set it
     7498              for us.
     7499           2. Needs to get the id of the session where the process is started.
     7500           We only need to do this once, though. */
     7501        static DWORD s_idCurrentSession = ~(DWORD)0;
     7502        DWORD idCurrentSession = s_idCurrentSession;
     7503        if (idCurrentSession == ~(DWORD)0)
     7504        {
     7505            HANDLE hCurrentProcessToken = NULL;
     7506            if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_READ, &hCurrentProcessToken))
     7507            {
     7508                DWORD cbIgn = 0;
     7509                if (GetTokenInformation(hCurrentProcessToken, TokenSessionId, &idCurrentSession, sizeof(idCurrentSession), &cbIgn))
     7510                    s_idCurrentSession = idCurrentSession;
     7511                else
     7512                {
     7513                    idCurrentSession = ~(DWORD)0;
     7514                    LogRelFunc(("GetTokenInformation/TokenSessionId on self failed: %u\n", GetLastError()));
     7515                }
     7516                CloseHandle(hCurrentProcessToken);
     7517            }
     7518            else
     7519                LogRelFunc(("OpenProcessToken/self failed: %u\n", GetLastError()));
     7520        }
     7521
     7522        /* get the caller's session */
     7523        HRESULT hrc = CoImpersonateClient();
     7524        if (SUCCEEDED(hrc))
     7525        {
     7526            HANDLE hCallerThreadToken;
     7527            if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_READ,
     7528                                FALSE /* OpenAsSelf - for impersonation at SecurityIdentification level */,
     7529                                &hCallerThreadToken))
     7530            {
     7531                SetLastError(NO_ERROR);
     7532                DWORD cbIgn = 0;
     7533                if (GetTokenInformation(hCallerThreadToken, TokenSessionId, &idCallerSession, sizeof(DWORD), &cbIgn))
     7534                {
     7535                    /* Only need to use SDS if the session ID differs: */
     7536                    if (idCurrentSession != idCallerSession)
     7537                    {
     7538                        fUseVBoxSDS = false;
     7539
     7540                        /* Obtain the groups the access token belongs to so we can see if the session is interactive: */
     7541                        DWORD         cbTokenGroups = 0;
     7542                        PTOKEN_GROUPS pTokenGroups  = NULL;
     7543                        if (   !GetTokenInformation(hCallerThreadToken, TokenGroups, pTokenGroups, 0, &cbTokenGroups)
     7544                            && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
     7545                            pTokenGroups = (PTOKEN_GROUPS)RTMemTmpAllocZ(cbTokenGroups);
     7546                        if (GetTokenInformation(hCallerThreadToken, TokenGroups, pTokenGroups, cbTokenGroups, &cbTokenGroups))
     7547                        {
     7548                            /* Well-known interactive SID: SECURITY_INTERACTIVE_RID, S-1-5-4: */
     7549                            SID_IDENTIFIER_AUTHORITY sidIdNTAuthority = SECURITY_NT_AUTHORITY;
     7550                            PSID                     pInteractiveSid = NULL;
     7551                            if (AllocateAndInitializeSid(&sidIdNTAuthority, 1, 4, 0, 0, 0, 0, 0, 0, 0, &pInteractiveSid))
     7552                            {
     7553                                /* Iterate over the groups looking for the interactive SID: */
     7554                                fUseVBoxSDS = false;
     7555                                for (DWORD dwIndex = 0; dwIndex < pTokenGroups->GroupCount; dwIndex++)
     7556                                    if (EqualSid(pTokenGroups->Groups[dwIndex].Sid, pInteractiveSid))
     7557                                    {
     7558                                        fUseVBoxSDS = true;
     7559                                        break;
     7560                                    }
     7561                                FreeSid(pInteractiveSid);
     7562                            }
     7563                        }
     7564                        else
     7565                            LogRelFunc(("GetTokenInformation/TokenGroups failed: %u\n", GetLastError()));
     7566                        RTMemTmpFree(pTokenGroups);
     7567                    }
     7568                }
     7569                else
     7570                    LogRelFunc(("GetTokenInformation/TokenSessionId failed: %u\n", GetLastError()));
     7571                CloseHandle(hCallerThreadToken);
     7572            }
     7573            else
     7574                LogRelFunc(("OpenThreadToken/client failed: %u\n", GetLastError()));
     7575            CoRevertToSelf();
     7576        }
     7577        else
     7578            LogRelFunc(("CoImpersonateClient failed: %Rhrc\n", hrc));
     7579    }
     7580    if (fUseVBoxSDS)
     7581    {
     7582        /* connect to VBoxSDS */
     7583        ComPtr<IVirtualBoxSDS> pVBoxSDS;
     7584        HRESULT rc = pVBoxSDS.createLocalObject(CLSID_VirtualBoxSDS);
     7585        if (FAILED(rc))
     7586            return setError(rc, tr("Failed to start the machine '%s'. A connection to VBoxSDS cannot be established"),
     7587                            strMachineName.c_str());
     7588
     7589        /* By default the RPC_C_IMP_LEVEL_IDENTIFY is used for impersonation the client. It allows
     7590           ACL checking but restricts an access to system objects e.g. files. Call to CoSetProxyBlanket
     7591           elevates the impersonation level up to RPC_C_IMP_LEVEL_IMPERSONATE allowing the VBoxSDS
     7592           service to access the files. */
     7593        rc = CoSetProxyBlanket(pVBoxSDS,
     7594                               RPC_C_AUTHN_DEFAULT,
     7595                               RPC_C_AUTHZ_DEFAULT,
     7596                               COLE_DEFAULT_PRINCIPAL,
     7597                               RPC_C_AUTHN_LEVEL_DEFAULT,
     7598                               RPC_C_IMP_LEVEL_IMPERSONATE,
     7599                               NULL,
     7600                               EOAC_DEFAULT);
     7601        if (FAILED(rc))
     7602            return setError(rc, tr("Failed to start the machine '%s'. CoSetProxyBlanket failed"), strMachineName.c_str());
     7603        ULONG uPid = 0;
     7604        rc = pVBoxSDS->LaunchVMProcess(Bstr(idStr).raw(), Bstr(strMachineName).raw(), Bstr(strFrontend).raw(),
     7605                                       Bstr(strEnvironment).raw(), Bstr(strSupHardeningLogArg).raw(),
     7606                                       idCallerSession, &uPid);
     7607        if (FAILED(rc))
     7608            return setError(rc, tr("Failed to start the machine '%s'. Process creation failed"), strMachineName.c_str());
     7609        pid = (RTPROCESS)uPid;
     7610    }
    76057611    else
    7606 
    7607 #ifdef VBOX_WITH_HEADLESS
    7608     if (   !strFrontend.compare("headless", Utf8Str::CaseInsensitive)
    7609         || !strFrontend.compare("capture", Utf8Str::CaseInsensitive)
    7610         || !strFrontend.compare("vrdp", Utf8Str::CaseInsensitive) /* Deprecated. Same as headless. */
    7611        )
    7612     {
    7613         strCanonicalName = "headless";
    7614         /* On pre-4.0 the "headless" type was used for passing "--vrdp off" to VBoxHeadless to let it work in OSE,
    7615          * which did not contain VRDP server. In VBox 4.0 the remote desktop server (VRDE) is optional,
    7616          * and a VM works even if the server has not been installed.
    7617          * So in 4.0 the "headless" behavior remains the same for default VBox installations.
    7618          * Only if a VRDE has been installed and the VM enables it, the "headless" will work
    7619          * differently in 4.0 and 3.x.
    7620          */
    7621         static const char s_szVBoxHeadless_exe[] = "VBoxHeadless" HOSTSUFF_EXE;
    7622         Assert(cchBufLeft >= sizeof(s_szVBoxHeadless_exe));
    7623         strcpy(pszNamePart, s_szVBoxHeadless_exe);
    7624 
    7625         Utf8Str idStr = mData->mUuid.toString();
    7626         const char *apszArgs[] =
    7627         {
    7628             szPath,
    7629             "--comment", mUserData->s.strName.c_str(),
    7630             "--startvm", idStr.c_str(),
    7631             "--vrde", "config",
    7632             NULL, /* For "--capture". */
    7633             NULL, /* For "--sup-startup-log". */
    7634             NULL
    7635         };
    7636         unsigned iArg = 7;
    7637         if (!strFrontend.compare("capture", Utf8Str::CaseInsensitive))
    7638             apszArgs[iArg++] = "--capture";
    7639         apszArgs[iArg++] = pszSupHardeningLogArg;
    7640 
    7641 # ifdef RT_OS_WINDOWS
    7642         vrc = RTProcCreate(szPath, apszArgs, env, RTPROC_FLAGS_NO_WINDOW, &pid);
    7643 # else
    7644         vrc = RTProcCreate(szPath, apszArgs, env, 0, &pid);
    7645 # endif
    7646     }
    7647 #else /* !VBOX_WITH_HEADLESS */
    7648     if (0)
    7649         ;
    7650 #endif /* !VBOX_WITH_HEADLESS */
    7651     else
    7652     {
    7653         RTEnvDestroy(env);
    7654         return setError(E_INVALIDARG,
    7655                         tr("Invalid frontend name: '%s'"),
    7656                         strFrontend.c_str());
    7657     }
    7658 
    7659     RTEnvDestroy(env);
    7660 
    7661     if (RT_FAILURE(vrc))
    7662         return setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
    7663                             tr("Could not launch a process for the machine '%s' (%Rrc)"),
    7664                             mUserData->s.strName.c_str(), vrc);
    7665 
    7666     LogFlowThisFunc(("launched.pid=%d(0x%x)\n", pid, pid));
     7612#endif /* VBOX_WITH_VBOXSDS && RT_OS_WINDOWS */
     7613    {
     7614        int vrc = MachineLaunchVMCommonWorker(idStr, strMachineName, strFrontend, strEnvironment, strSupHardeningLogArg,
     7615                                              strAppOverride, 0 /*fFlags*/, NULL /*pvExtraData*/, pid);
     7616        if (RT_FAILURE(vrc))
     7617            return setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
     7618                                tr("Could not launch the VM process for the machine '%s' (%Rrc)"), strMachineName.c_str(), vrc);
     7619    }
     7620
     7621    LogRel(("Launched VM: %u pid: %u (%#x) frontend: %s name: %s\n",
     7622            idStr.c_str(), pid, pid, strFrontend.c_str(), strMachineName.c_str()));
    76677623
    76687624    if (!fSeparate)
  • trunk/src/VBox/Main/src-server/generic/AutostartDb-generic.cpp

    r76553 r80569  
    190190    rc = autostartModifyDb(true /* fAutostart */, true /* fAddVM */);
    191191    RTCritSectLeave(&this->CritSect);
    192 #elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
     192#elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
    193193    NOREF(pszVMId); /* Not needed */
    194194    rc = VINF_SUCCESS;
     
    210210    rc = autostartModifyDb(true /* fAutostart */, false /* fAddVM */);
    211211    RTCritSectLeave(&this->CritSect);
    212 #elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
     212#elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
    213213    NOREF(pszVMId); /* Not needed */
    214214    rc = VINF_SUCCESS;
     
    230230    rc = autostartModifyDb(false /* fAutostart */, true /* fAddVM */);
    231231    RTCritSectLeave(&this->CritSect);
    232 #elif defined(RT_OS_DARWIN)
     232#elif defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS)
    233233    NOREF(pszVMId); /* Not needed */
    234234    rc = VINF_SUCCESS;
     
    250250    rc = autostartModifyDb(false /* fAutostart */, false /* fAddVM */);
    251251    RTCritSectLeave(&this->CritSect);
    252 #elif defined(RT_OS_DARWIN)
    253     NOREF(pszVMId); /* Not needed */
    254     rc = VINF_SUCCESS;
    255 #else
    256     NOREF(pszVMId);
    257     rc = VERR_NOT_SUPPORTED;
    258 #endif
    259 
    260     return rc;
    261 }
    262 
     252#elif defined(RT_OS_DARWIN) || defined (RT_OS_WINDOWS)
     253    NOREF(pszVMId); /* Not needed */
     254    rc = VINF_SUCCESS;
     255#else
     256    NOREF(pszVMId);
     257    rc = VERR_NOT_SUPPORTED;
     258#endif
     259
     260    return rc;
     261}
     262
  • trunk/src/VBox/Runtime/common/fuzz/fuzz-observer.cpp

    r77758 r80569  
    474474{
    475475    int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], pExecCtx->hEnv, 0 /*fFlags*/, &pExecCtx->StdinHandle,
    476                             &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, &pExecCtx->hProc);
     476                            &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, NULL, &pExecCtx->hProc);
    477477    if (RT_SUCCESS(rc))
    478478    {
     
    577577{
    578578    int rc = RTProcCreateEx(pThis->pszBinary, &pExecCtx->apszArgs[0], pExecCtx->hEnv, 0 /*fFlags*/, &pExecCtx->StdinHandle,
    579                             &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, &pExecCtx->hProc);
     579                            &pExecCtx->StdoutHandle, &pExecCtx->StderrHandle, NULL, NULL, NULL, &pExecCtx->hProc);
    580580    if (RT_SUCCESS(rc))
    581581    {
  • trunk/src/VBox/Runtime/generic/RTProcDaemonize-generic.cpp

    r76553 r80569  
    8484                                RTPROC_FLAGS_DETACHED | RTPROC_FLAGS_SAME_CONTRACT,
    8585                                &hStdIn, &hStdOutAndErr, &hStdOutAndErr,
    86                                 NULL /*pszAsUser*/,  NULL /*pszPassword*/, NULL /*phProcess*/);
     86                                NULL /*pszAsUser*/,  NULL /*pszPassword*/, NULL /*pExtraData*/, NULL /*phProcess*/);
    8787
    8888            RTFileClose(hStdOutAndErr.u.hFile);
  • trunk/src/VBox/Runtime/r3/posix/process-creation-posix.cpp

    r79559 r80569  
    512512    return RTProcCreateEx(pszExec, papszArgs, Env, fFlags,
    513513                          NULL, NULL, NULL,  /* standard handles */
    514                           NULL /*pszAsUser*/, NULL /* pszPassword*/,
     514                          NULL /*pszAsUser*/, NULL /* pszPassword*/, NULL /*pvExtraData*/,
    515515                          pProcess);
    516516}
     
    682682RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
    683683                               PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
    684                                const char *pszPassword, PRTPROCESS phProcess)
     684                               const char *pszPassword, void *pvExtraData, PRTPROCESS phProcess)
    685685{
    686686    int rc;
     
    704704        return VERR_PROC_DETACH_NOT_SUPPORTED;
    705705#endif
     706    AssertReturn(pvExtraData == NULL || (fFlags & RTPROC_FLAGS_DESIRED_SESSION_ID), VERR_INVALID_PARAMETER);
    706707
    707708    /*
  • trunk/src/VBox/Runtime/r3/win/process-win.cpp

    r80503 r80569  
    140140/* advapi32.dll: */
    141141static PFNCREATEPROCESSWITHLOGON        g_pfnCreateProcessWithLogonW    = NULL;
    142 static PFNLSALOOKUPNAMES2               g_pfnLsaLookupNames2            = NULL;
    143142static decltype(LogonUserW)            *g_pfnLogonUserW                 = NULL;
    144143static decltype(CreateProcessAsUserW)  *g_pfnCreateProcessAsUserW       = NULL;
    145 static decltype(LsaNtStatusToWinError) *g_pfnLsaNtStatusToWinError      = NULL;
    146144/* user32.dll: */
    147145static decltype(OpenWindowStationW)    *g_pfnOpenWindowStationW         = NULL;
     
    353351        if (RT_FAILURE(rc)) { g_pfnCreateProcessWithLogonW = NULL; Assert(g_enmWinVer <= kRTWinOSType_NT4); }
    354352
    355         rc = RTLdrGetSymbol(hMod, "LsaLookupNames2", (void **)&g_pfnLsaLookupNames2);
    356         if (RT_FAILURE(rc)) { g_pfnLsaLookupNames2 = NULL; Assert(g_enmWinVer <= kRTWinOSType_NT4); }
    357 
    358353        rc = RTLdrGetSymbol(hMod, "LogonUserW", (void **)&g_pfnLogonUserW);
    359354        if (RT_FAILURE(rc)) { g_pfnLogonUserW = NULL; Assert(g_enmWinVer <= kRTWinOSType_NT350); }
     
    361356        rc = RTLdrGetSymbol(hMod, "CreateProcessAsUserW", (void **)&g_pfnCreateProcessAsUserW);
    362357        if (RT_FAILURE(rc)) { g_pfnCreateProcessAsUserW = NULL; Assert(g_enmWinVer <= kRTWinOSType_NT350); }
    363 
    364         rc = RTLdrGetSymbol(hMod, "LsaNtStatusToWinError", (void **)&g_pfnLsaNtStatusToWinError);
    365         if (RT_FAILURE(rc)) { g_pfnLsaNtStatusToWinError = NULL; Assert(g_enmWinVer <= kRTWinOSType_NT350); }
    366358
    367359        RTLdrClose(hMod);
     
    413405                          NULL, NULL, NULL,  /* standard handles */
    414406                          NULL /*pszAsUser*/, NULL /* pszPassword*/,
    415                           pProcess);
     407                          NULL /*pvExtraData*/, pProcess);
    416408}
    417409
     
    482474
    483475/**
    484  * Get the process token of the process indicated by @a dwPID if the @a pSid
    485  * matches.
     476 * Get the process token of the process indicated by @a dwPID if the @a pSid and
     477 * @a idSessionDesired matches.
    486478 *
    487479 * @returns IPRT status code.
    488  * @param   dwPid           The process identifier.
    489  * @param   pSid            The secure identifier of the user.
    490  * @param   phToken         Where to return the a duplicate of the process token
    491  *                          handle on success. (The caller closes it.)
    492  */
    493 static int rtProcWinGetProcessTokenHandle(DWORD dwPid, PSID pSid, PHANDLE phToken)
     480 * @param   dwPid               The process identifier.
     481 * @param   pSid                The secure identifier of the user.
     482 * @param   idDesiredSession    The session the process candidate should
     483 *                              preferably belong to, UINT32_MAX if anything
     484 *                              goes.
     485 * @param   phToken             Where to return the a duplicate of the process token
     486 *                              handle on success. (The caller closes it.)
     487 */
     488static int rtProcWinGetProcessTokenHandle(DWORD dwPid, PSID pSid, DWORD idDesiredSession, PHANDLE phToken)
    494489{
    495490    AssertPtr(pSid);
     
    502497        HANDLE hTokenProc;
    503498        if (OpenProcessToken(hProc,
    504                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE
     499                             TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE
    505500                             | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
    506501                             &hTokenProc))
    507502        {
     503            /*
     504             * Query the user SID from the token.
     505             */
    508506            SetLastError(NO_ERROR);
    509507            DWORD   dwSize = 0;
     
    519517                    if (GetTokenInformation(hTokenProc, TokenUser, pTokenUser, dwSize, &dwSize))
    520518                    {
     519                        /*
     520                         * Match token user with the user we're want to create a process as.
     521                         */
    521522                        if (   IsValidSid(pTokenUser->User.Sid)
    522523                            && EqualSid(pTokenUser->User.Sid, pSid))
    523524                        {
    524525                            /*
    525                              * So we found the process instance which belongs to the user we want to
    526                              * to run our new process under. This duplicated token will be used for
    527                              * the actual CreateProcessAsUserW() call then.
     526                             * Do we need to match the session ID?
    528527                             */
    529                             rc = rtProcWinDuplicateToken(hTokenProc, phToken);
     528                            rc = VINF_SUCCESS;
     529                            if (idDesiredSession != UINT32_MAX)
     530                            {
     531                                DWORD idCurSession = UINT32_MAX;
     532                                if (GetTokenInformation(hTokenProc, TokenSessionId, &idCurSession, sizeof(DWORD), &dwSize))
     533                                    rc = idDesiredSession == idCurSession ? VINF_SUCCESS : VERR_NOT_FOUND;
     534                                else
     535                                    rc = RTErrConvertFromWin32(GetLastError());
     536                            }
     537                            if (RT_SUCCESS(rc))
     538                            {
     539                                /*
     540                                 * Got a match.  Duplicate the token.  This duplicated token will
     541                                 * be used for the actual CreateProcessAsUserW() call then.
     542                                 */
     543                                rc = rtProcWinDuplicateToken(hTokenProc, phToken);
     544                            }
    530545                        }
    531546                        else
     
    627642                        if (   cbRet > 0
    628643                            && _stricmp(pszProcName, papszNames[i]) == 0
    629                             && RT_SUCCESS(rtProcWinGetProcessTokenHandle(paPids[iPid], pSid, phToken)))
     644                            && RT_SUCCESS(rtProcWinGetProcessTokenHandle(paPids[iPid], pSid, UINT32_MAX, phToken)))
    630645                            fFound = true;
    631646                        CloseHandle(hProc);
     
    645660
    646661/**
    647  * Finds a one of the processes in @a papszNames running with user @a pSid and
    648  * returns a duplicate handle to its token.
     662 * Finds a one of the processes in @a papszNames running with user @a pSid and possibly
     663 * in the required windows session. Returns a duplicate handle to its token.
    649664 *
    650665 * @returns Success indicator.
    651  * @param   papszNames      The process candidates, in prioritized order.
    652  * @param   pSid            The secure identifier of the user.
    653  * @param   phToken         Where to return the token handle - duplicate,
    654  *                          caller closes it on success.
    655  */
    656 static bool rtProcWinFindTokenByProcess(const char * const *papszNames, PSID pSid, PHANDLE phToken)
     666 * @param   papszNames          The process candidates, in prioritized order.
     667 * @param   pSid                The secure identifier of the user.
     668 * @param   idDesiredSession    The session the process candidate should
     669 *                              belong to if possible, UINT32_MAX if anything
     670 *                              goes.
     671 * @param   phToken             Where to return the token handle - duplicate,
     672 *                              caller closes it on success.
     673 */
     674static bool rtProcWinFindTokenByProcess(const char * const *papszNames, PSID pSid, uint32_t idDesiredSession, PHANDLE phToken)
    657675{
    658676    AssertPtr(papszNames);
     
    685703                        if (_stricmp(ProcEntry.szExeFile, papszNames[i]) == 0)
    686704                        {
    687                             int rc = rtProcWinGetProcessTokenHandle(ProcEntry.th32ProcessID, pSid, phToken);
     705                            int rc = rtProcWinGetProcessTokenHandle(ProcEntry.th32ProcessID, pSid, idDesiredSession, phToken);
    688706                            if (RT_SUCCESS(rc))
    689707                            {
     
    10221040    Assert(pSidRet);
    10231041    RTMemTmpFree(pUser);
     1042    *prc = VINF_SUCCESS;
    10241043    return pSidRet;
    10251044}
     
    15621581                                  RTENV hEnv, DWORD dwCreationFlags,
    15631582                                  STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo,
    1564                                   uint32_t fFlags, const char *pszExec)
     1583                                  uint32_t fFlags, const char *pszExec, uint32_t idDesiredSession)
    15651584{
    15661585    /*
     
    16141633             * For the token search we need a SID.
    16151634             */
    1616             PSID pSid = NULL;
    1617             if ((fFlags & RTPROC_FLAGS_AS_IMPERSONATED_TOKEN) || pwszUser == NULL)
    1618                 pSid = rtProcWinGetTokenUserSid(hTokenLogon, &rc);
    1619             else
    1620             {
    1621                 /** @todo r=bird: why can't we do this in the same manner as in the
    1622                  *        RTPROC_FLAGS_AS_IMPERSONATED_TOKEN case above? */
    1623 
    1624                 /* Try query the SID and domain sizes first. */
    1625                 DWORD        cbSid      = 0; /* Must be zero to query size! */
    1626                 DWORD        cwcDomain  = 0;
    1627                 SID_NAME_USE SidNameUse = SidTypeUser;
    1628                 fRc = LookupAccountNameW(NULL, pwszUser, NULL, &cbSid, NULL, &cwcDomain, &SidNameUse);
    1629                 if (!fRc)
    1630                 {
    1631                     dwErr = GetLastError();
    1632 
    1633                     /*
    1634                      * The errors ERROR_TRUSTED_DOMAIN_FAILURE and ERROR_TRUSTED_RELATIONSHIP_FAILURE
    1635                      * can happen if an ADC (Active Domain Controller) is offline or not reachable.
    1636                      *
    1637                      * Try to handle these errors gracefully by asking the local LSA cache of the
    1638                      * client OS instead then. For this to work, the desired user must have at
    1639                      * least logged in once at that client -- otherwise there will be no cached
    1640                      * authentication available and this fallback will fail.
    1641                      */
    1642                     if (   g_pfnLsaLookupNames2 /* >= Windows XP */
    1643                         && (   dwErr == ERROR_TRUSTED_DOMAIN_FAILURE
    1644                             || dwErr == ERROR_TRUSTED_RELATIONSHIP_FAILURE))
    1645                     {
    1646                         LSA_OBJECT_ATTRIBUTES objAttr;
    1647                         RT_ZERO(objAttr);
    1648                         objAttr.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
    1649 
    1650                         LSA_HANDLE lsahPolicy;
    1651                         NTSTATUS ntSts = LsaOpenPolicy(NULL, &objAttr, POLICY_LOOKUP_NAMES, &lsahPolicy);
    1652                         if (ntSts == STATUS_SUCCESS)
    1653                         {
    1654                             RTPROCWINACCOUNTINFO accountInfo;
    1655                             RT_ZERO(accountInfo);
    1656                             rc = rtProcWinParseAccountInfo(pwszUser, &accountInfo);
    1657                             AssertRC(rc);
    1658                             AssertPtr(accountInfo.pwszUserName);
    1659 
    1660                             LSA_UNICODE_STRING lsaUser;
    1661                             lsaUser.Buffer        = accountInfo.pwszUserName;
    1662                             lsaUser.Length        = (USHORT)(RTUtf16Len(accountInfo.pwszUserName) * sizeof(WCHAR));
    1663                             lsaUser.MaximumLength = lsaUser.Length;
    1664 
    1665                             PLSA_REFERENCED_DOMAIN_LIST pDomainList     = NULL;
    1666                             PLSA_TRANSLATED_SID2        pTranslatedSids = NULL;
    1667                             ntSts = g_pfnLsaLookupNames2(lsahPolicy, 0 /* Flags */,
    1668                                                          1 /* Number of users to lookup */,
    1669                                                          &lsaUser, &pDomainList, &pTranslatedSids);
    1670                             if (ntSts == STATUS_SUCCESS)
    1671                             {
    1672                                 AssertPtr(pDomainList);
    1673                                 AssertPtr(pTranslatedSids);
    1674 # ifdef DEBUG
    1675                                 LogRelFunc(("LsaLookupNames2: cDomains=%u, DomainIndex=%ld, SidUse=%ld\n",
    1676                                             pDomainList->Entries, pTranslatedSids[0].DomainIndex, pTranslatedSids[0].Use));
    1677 # endif
    1678                                 Assert(pTranslatedSids[0].Use == SidTypeUser);
    1679 
    1680                                 if (pDomainList->Entries)
    1681                                 {
    1682                                     AssertPtr(pDomainList->Domains);
    1683                                     LogRelFunc(("LsaLookupNames2: Domain=%ls\n",
    1684                                                 pDomainList->Domains[pTranslatedSids[0].DomainIndex].Name.Buffer));
    1685                                 }
    1686 
    1687                                 cbSid = GetLengthSid(pTranslatedSids->Sid) + 16;
    1688                                 Assert(cbSid);
    1689                                 pSid = (PSID)RTMemAllocZ(cbSid);
    1690                                 if (!CopySid(cbSid, pSid, pTranslatedSids->Sid))
    1691                                 {
    1692                                     dwErr = GetLastError();
    1693                                     LogRelFunc(("CopySid failed with: %ld\n", dwErr));
    1694                                     rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    1695                                 }
    1696                             }
    1697                             else if (g_pfnLsaNtStatusToWinError)
    1698                             {
    1699                                 dwErr = g_pfnLsaNtStatusToWinError(ntSts);
    1700                                 LogRelFunc(("LsaLookupNames2 failed with: %ld\n", dwErr));
    1701                                 rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    1702                             }
    1703                             else
    1704                             {
    1705                                 LogRelFunc(("LsaLookupNames2 failed with: %#x\n", ntSts));
    1706                                 rc = RTErrConvertFromNtStatus(ntSts);
    1707                             }
    1708 
    1709                             if (pDomainList)
    1710                             {
    1711                                 LsaFreeMemory(pDomainList);
    1712                                 pDomainList = NULL;
    1713                             }
    1714                             if (pTranslatedSids)
    1715                             {
    1716                                 LsaFreeMemory(pTranslatedSids);
    1717                                 pTranslatedSids = NULL;
    1718                             }
    1719 
    1720                             rtProcWinFreeAccountInfo(&accountInfo);
    1721                             LsaClose(lsahPolicy);
    1722                         }
    1723                         else if (g_pfnLsaNtStatusToWinError)
    1724                         {
    1725                             dwErr = g_pfnLsaNtStatusToWinError(ntSts);
    1726                             LogRelFunc(("LsaOpenPolicy failed with: %ld\n", dwErr));
    1727                             rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_3;
    1728                         }
    1729                         else
    1730                         {
    1731                             LogRelFunc(("LsaOpenPolicy failed with: %#x\n", ntSts));
    1732                             rc = RTErrConvertFromNtStatus(ntSts);
    1733                         }
    1734 
    1735                         /* Note: pSid will be free'd down below. */
    1736                     }
    1737                     else if (dwErr == ERROR_INSUFFICIENT_BUFFER)
    1738                     {
    1739                         /* Allocate memory for the LookupAccountNameW output buffers and do it for real. */
    1740                         cbSid = fRc && cbSid != 0 ? cbSid + 16 : _1K;
    1741                         pSid = (PSID)RTMemAllocZ(cbSid);
    1742                         if (pSid)
    1743                         {
    1744                             cwcDomain = fRc ? cwcDomain + 2 : _4K;
    1745                             PRTUTF16 pwszDomain = (PRTUTF16)RTMemAllocZ(cwcDomain * sizeof(RTUTF16));
    1746                             if (pwszDomain)
    1747                             {
    1748                                 /* Note: Just pass in the UPN (User Principal Name), e.g. someone@example.com */
    1749                                 if (!LookupAccountNameW(NULL /*lpSystemName*/, pwszUser, pSid, &cbSid, pwszDomain, &cwcDomain,
    1750                                                         &SidNameUse))
    1751                                 {
    1752                                     dwErr = GetLastError();
    1753                                     LogRelFunc(("LookupAccountNameW(2) failed with: %ld\n", dwErr));
    1754                                     rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_4;
    1755                                 }
    1756 
    1757                                 RTMemFree(pwszDomain);
    1758                             }
    1759                             else
    1760                                 rc = VERR_NO_MEMORY;
    1761 
    1762                             /* Note: pSid will be free'd down below. */
    1763                         }
    1764                         else
    1765                             rc = VERR_NO_MEMORY;
    1766                     }
    1767                     else
    1768                     {
    1769                         LogRelFunc(("LookupAccountNameW(1) failed with: %ld\n", dwErr));
    1770                         rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_2;
    1771                     }
    1772                 }
    1773             }
    1774 
     1635            PSID pSid = rtProcWinGetTokenUserSid(hTokenLogon, &rc);
     1636
     1637            /*
     1638             * If we got a valid SID, search the running processes.
     1639             */
    17751640            /*
    17761641             * If we got a valid SID, search the running processes.
     
    17921657                        NULL
    17931658                    };
    1794                     fFound = rtProcWinFindTokenByProcess(s_papszProcNames, pSid, &hTokenUserDesktop);
     1659                    fFound = rtProcWinFindTokenByProcess(s_papszProcNames, pSid, idDesiredSession, &hTokenUserDesktop);
    17951660                    dwErr  = 0;
    17961661                }
     
    18381703            {
    18391704                /*
    1840                  * Load the profile, if requested.  (Must be done prior to
    1841                  * creating the enviornment.)
     1705                 * Load the profile, if requested.  (Must be done prior to creating the enviornment.)
     1706                 *
     1707                 * Note! We don't have sufficient rights when impersonating a user, but we can
     1708                 *       ASSUME the user is logged on and has its profile loaded into HKEY_USERS already.
    18421709                 */
    18431710                PROFILEINFOW ProfileInfo;
    18441711                PRTUTF16     pwszUserFree = NULL;
    18451712                RT_ZERO(ProfileInfo);
    1846                 if (fFlags & RTPROC_FLAGS_PROFILE) /** @todo r=bird: We probably don't need to load anything if pwszUser is NULL... */
     1713                /** @todo r=bird: We probably don't need to load anything if pwszUser is NULL... */
     1714                if ((fFlags & (RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN)) == RTPROC_FLAGS_PROFILE)
    18471715                {
    18481716                    if (!pwszUser)
     
    18821750                                    rtProcWinStationPrep(hTokenToUse, pStartupInfo, &hOldWinStation);
    18831751
    1884                                 /* Specify a window station and desktop when start interactive
    1885                                  * process from service with an impersonated token. */
    1886                                 /** @todo r=bird: Why is this needed? */
    1887                                 /** @todo r=bird: Why don't we do this for the non-impersonated token case? */
    1888                                 /** @todo r=bird: Remind me, does pure RDP logins get a winSta0 too, or do
    1889                                  *        the get a mangled name similar to the services? */
    1890                                 if (   fFound
    1891                                     &&    (fFlags & (RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN))
    1892                                        ==           (RTPROC_FLAGS_SERVICE | RTPROC_FLAGS_AS_IMPERSONATED_TOKEN))
    1893                                     pStartupInfo->lpDesktop = L"WinSta0\\default";
    1894 
    18951752                                /*
    18961753                                 * Useful KB articles:
     
    21992056                                 RTENV hEnv, DWORD dwCreationFlags,
    22002057                                 STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo,
    2201                                  uint32_t fFlags, const char *pszExec)
     2058                                 uint32_t fFlags, const char *pszExec, uint32_t idDesiredSession)
    22022059{
    22032060    /*
     
    22162073    }
    22172074    return rtProcWinCreateAsUser2(pwszUser, pwszPassword, ppwszExec, pwszCmdLine,
    2218                                   hEnv, dwCreationFlags, pStartupInfo, pProcInfo, fFlags, pszExec);
     2075                                  hEnv, dwCreationFlags, pStartupInfo, pProcInfo, fFlags, pszExec, idDesiredSession);
    22192076}
    22202077
     
    23662223RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
    23672224                               PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
    2368                                const char *pszPassword, PRTPROCESS phProcess)
     2225                               const char *pszPassword, void *pvExtraData, PRTPROCESS phProcess)
    23692226{
    23702227    /*
     
    23812238    AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER);
    23822239    AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER);
     2240
     2241    /* Extra data: */
     2242    uint32_t idDesiredSession = UINT32_MAX;
     2243    if (   (fFlags & (RTPROC_FLAGS_DESIRED_SESSION_ID | RTPROC_FLAGS_SERVICE))
     2244        ==           (RTPROC_FLAGS_DESIRED_SESSION_ID | RTPROC_FLAGS_SERVICE))
     2245    {
     2246        AssertPtrReturn(pvExtraData, VERR_INVALID_POINTER);
     2247        idDesiredSession = *(uint32_t *)pvExtraData;
     2248    }
     2249    else
     2250        AssertReturn(!(fFlags & RTPROC_FLAGS_DESIRED_SESSION_ID), VERR_INVALID_FLAGS);
    23832251
    23842252    /*
     
    25852453                        rc = rtProcWinCreateAsUser(pwszUser, pwszPassword,
    25862454                                                   &pwszExec, pwszCmdLine, hEnv, dwCreationFlags,
    2587                                                    &StartupInfo, &ProcInfo, fFlags, pszExec);
     2455                                                   &StartupInfo, &ProcInfo, fFlags, pszExec, idDesiredSession);
    25882456
    25892457                        if (pwszPassword && *pwszPassword)
  • trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp

    r76553 r80569  
    219219    RTPROCESS hProc;
    220220    RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/,
    221                                          NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     221                                         NULL, NULL, NULL, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    222222    RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
    223223    RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
     
    233233    int rc;
    234234    RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange, RTPROC_FLAGS_ENV_CHANGE_RECORD,
    235                                          NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     235                                         NULL, NULL, NULL, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    236236    if (RT_SUCCESS(rc))
    237237    {
     
    248248    apszArgs[2] = "noinherit";
    249249    RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, RTPROC_FLAGS_PROFILE,
    250                                          NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     250                                         NULL, NULL, NULL, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    251251    if (RT_SUCCESS(rc))
    252252    {
     
    263263    RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange,
    264264                                         RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_ENV_CHANGE_RECORD,
    265                                          NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     265                                         NULL, NULL, NULL, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    266266    if (RT_SUCCESS(rc))
    267267    {
     
    386386    RTPROCESS hProc;
    387387    int rc = RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL,
    388                             "non-existing-user", "wrong-password", &hProc);
     388                            "non-existing-user", "wrong-password", NULL, &hProc);
    389389    if (rc != VERR_AUTHENTICATION_FAILURE && rc != VERR_PRIVILEGE_NOT_HELD && rc != VERR_PROC_TCB_PRIV_NOT_HELD)
    390390        RTTestIFailed("rc=%Rrc", rc);
     
    392392    /* Test for invalid application. */
    393393    RTTESTI_CHECK_RC(RTProcCreateEx("non-existing-app", apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    394                                     NULL, NULL, NULL, NULL, &hProc), VERR_FILE_NOT_FOUND);
     394                                    NULL, NULL, NULL, NULL, NULL, &hProc), VERR_FILE_NOT_FOUND);
    395395
    396396    /* Test a (hopefully) valid user/password logon (given by parameters of this function). */
    397397    RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    398                                          NULL, NULL, pszUser, pszPassword, &hProc), VINF_SUCCESS);
     398                                         NULL, NULL, pszUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    399399    RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
    400400    RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
     
    431431    RTPROCESS hProc;
    432432    RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, g_apszArgs4, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    433                                          NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     433                                         NULL, NULL, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    434434    RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
    435435    RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
     
    472472    RTPROCESS hProc;
    473473    RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    474                                          &Handle, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     474                                         &Handle, &Handle, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    475475    RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
    476476
     
    537537    RTPROCESS hProc;
    538538    RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    539                                          NULL, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     539                                         NULL, &Handle, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    540540    RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
    541541
     
    603603    RTPROCESS hProc;
    604604    RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    605                                          &Handle, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
     605                                         &Handle, NULL, pszAsUser, pszPassword, NULL, &hProc), VINF_SUCCESS);
    606606    RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
    607607
  • trunk/src/VBox/ValidationKit/utils/TestExecServ/TestExecService.cpp

    r79423 r80569  
    27182718        rc = RTProcCreateEx(pszExecName, papszArgs, pTxsExec->hEnv, 0 /*fFlags*/,
    27192719                            pTxsExec->StdIn.phChild, pTxsExec->StdOut.phChild, pTxsExec->StdErr.phChild,
    2720                             *pszUsername ? pszUsername : NULL, NULL,
     2720                            *pszUsername ? pszUsername : NULL, NULL, NULL,
    27212721                            &pTxsExec->hProcess);
    27222722        if (RT_SUCCESS(rc))
  • trunk/src/bldprogs/scmsubversion.cpp

    r76553 r80569  
    419419                                NULL /*pszAsUser*/,
    420420                                NULL /*pszPassword*/,
     421                                NULL /*pvExtraData*/,
    421422                                &hProc);
    422423            rc2 = RTHandleClose(&hChildStdErr); AssertRC(rc2);
     
    556557                            NULL /*pszAsUser*/,
    557558                            NULL /*pszPassword*/,
     559                            NULL /*pvExtraData*/,
    558560                            &hProc);
    559561
  • trunk/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxproces.c

    r33404 r80569  
    601601    vrc = RTProcCreateEx(path, (const char **)argv, childEnv,
    602602                         RTPROC_FLAGS_DETACHED, pStdIn, pStdOut, pStdErr,
    603                          NULL /* pszAsUser */, NULL /* pszPassword */,
     603                         NULL /* pszAsUser */, NULL /* pszPassword */, NULL /* pExtraData */,
    604604                         NULL /* phProcess */);
    605605    if (newEnv != RTENV_DEFAULT) {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette