VirtualBox

Changeset 95274 in vbox for trunk/src/VBox/Main/src-global


Ignore:
Timestamp:
Jun 14, 2022 10:48:33 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151855
Message:

FE/VBoxAutostart/adi: Added experimental support for running VBoxSVC session 0 (service session). Did some minor cleanup for the patch posted at comment 95. Disabled by default for now. bugref:9341

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-global/win/VirtualBoxSDSImpl.cpp

    r93115 r95274  
    2222#define LOG_GROUP LOG_GROUP_MAIN_VIRTUALBOXSDS
    2323#include <VBox/com/VirtualBox.h>
     24#include <VBox/com/utils.h>
    2425#include "VirtualBoxSDSImpl.h"
    2526
     
    3132#include <iprt/asm.h>
    3233#include <iprt/critsect.h>
     34#include <iprt/env.h>
     35#include <iprt/err.h>
    3336#include <iprt/mem.h>
     37#include <iprt/path.h>
    3438#include <iprt/process.h>
    3539#include <iprt/system.h>
     
    7175    /** The PID of the chosen one. */
    7276    RTPROCESS                       m_pidTheChosenOne;
     77    /** The tick count when the process in Windows session 0 started */
     78    uint32_t                        m_tickTheChosenOne;
    7379    /** The current watcher thread index, UINT32_MAX if not watched. */
    7480    uint32_t                        m_iWatcher;
     
    8995        , m_strUsername(a_rStrUsername)
    9096        , m_pidTheChosenOne(NIL_RTPROCESS)
     97        , m_tickTheChosenOne(0)
    9198#ifdef WITH_WATCHER
    9299        , m_iWatcher(UINT32_MAX)
     
    146153        }
    147154        m_pidTheChosenOne = NIL_RTPROCESS;
     155        m_tickTheChosenOne = 0;
    148156    }
    149157
     
    250258    {
    251259        *aExistingVirtualBox = NULL;
    252 
    253260        /*
    254261         * Get the client user SID and name.
     
    263270                /*
    264271                 * If there already is a chosen one, ask it for a IVirtualBox instance
    265                  * to return to the caller.  Should it be dead or unresponsive, the caller
     272                 * to return to the caller. Should it be dead or unresponsive, the caller
    266273                 * takes its place.
    267                  */
     274                */
    268275                if (pUserData->m_ptrTheChosenOne.isNotNull())
    269276                {
     
    271278                    {
    272279                        hrc = pUserData->m_ptrTheChosenOne->GetVirtualBox(aExistingVirtualBox);
     280                        /* seems the VBoxSVC in windows session 0 is not yet finished object creation.
     281                         * Give it a time. */
     282                        if (FAILED(hrc) && GetTickCount() - pUserData->m_tickTheChosenOne < 60 * 1000)
     283                            hrc = E_PENDING;
    273284                    }
    274285                    catch (...)
     
    284295#endif
    285296                        pUserData->i_unchooseTheOne(true /*fIrregular*/);
     297                        hrc = S_OK;
    286298                    }
    287299                }
     
    289301                    hrc = S_OK;
    290302
    291                 /*
    292                  * No chosen one?  Make the caller the new chosen one!
    293                  */
    294                 if (pUserData->m_ptrTheChosenOne.isNull())
     303                /* No chosen one?  Make the caller the new chosen one! */
     304                if (SUCCEEDED(hrc) && pUserData->m_ptrTheChosenOne.isNull())
    295305                {
    296                     LogRel(("registerVBoxSVC: Making aPid=%u (%#x) the chosen one for user %s (%s)!\n",
    297                             aPid, aPid, pUserData->m_strUserSid.c_str(), pUserData->m_strUsername.c_str()));
     306#ifdef VBOX_WITH_VBOXSVC_SESSION_0
     307                    /* Get user token. */
     308                    HANDLE hThreadToken = NULL;
     309                    hrc = CoImpersonateClient();
     310                    if (SUCCEEDED(hrc))
     311                    {
     312                        hrc = E_FAIL;
     313                        if (OpenThreadToken(GetCurrentThread(),
     314                                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE
     315                                            | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
     316                                            TRUE /* OpenAsSelf - for impersonation at SecurityIdentification level */,
     317                                            &hThreadToken))
     318                        {
     319                            HANDLE hNewToken;
     320                            if (DuplicateTokenEx(hThreadToken, MAXIMUM_ALLOWED, NULL /*SecurityAttribs*/,
     321                                                    SecurityIdentification, TokenPrimary, &hNewToken))
     322                            {
     323                                CloseHandle(hThreadToken);
     324                                hThreadToken = hNewToken;
     325                                hrc = S_OK;
     326                            }
     327                            else
     328                                LogRel(("registerVBoxSVC: DuplicateTokenEx failed: %ld\n", GetLastError()));
     329                        }
     330                        else
     331                            LogRel(("registerVBoxSVC: OpenThreadToken failed: %ld\n", GetLastError()));
     332
     333                        CoRevertToSelf();
     334                    }
     335                    else
     336                        LogRel(("registerVBoxSVC: CoImpersonateClient failed: %Rhrc\n", hrc));
     337
     338                    /* check windows session */
     339                    DWORD dwSessionId = 0;
     340                    if (SUCCEEDED(hrc) && hThreadToken != NULL)
     341                    {
     342                        hrc = E_FAIL;
     343                        DWORD cbSessionId = sizeof(DWORD);
     344                        if (GetTokenInformation(hThreadToken, TokenSessionId, (LPVOID)&dwSessionId, cbSessionId, &cbSessionId))
     345                        {
     346                            if (cbSessionId == sizeof(DWORD))
     347                                hrc = S_OK;
     348                            else
     349                                LogRel(("registerVBoxSVC: GetTokenInformation return value has invalid size\n"));
     350                        }
     351                        else
     352                            LogRel(("registerVBoxSVC: GetTokenInformation failed: %ld\n", GetLastError()));
     353                    }
     354                    if (SUCCEEDED(hrc) && dwSessionId != 0)
     355                    {
     356                        /* if VBoxSVC in the Windows session 0 is not started or if it did not
     357                            * registered during a minute, start new one */
     358                        if (   pUserData->m_pidTheChosenOne == NIL_RTPROCESS
     359                            || GetTickCount() - pUserData->m_tickTheChosenOne > 60 * 1000)
     360                        {
     361                            uint32_t uSessionId = 0;
     362                            if (SetTokenInformation(hThreadToken, TokenSessionId, &uSessionId, sizeof(uint32_t)))
     363                            {
     364                                /* start VBoxSVC process */
     365                                /* Get the path to the executable directory w/ trailing slash: */
     366                                char szPath[RTPATH_MAX];
     367                                int vrc = RTPathAppPrivateArch(szPath, sizeof(szPath));
     368                                AssertRCReturn(vrc, vrc);
     369                                size_t cbBufLeft = RTPathEnsureTrailingSeparator(szPath, sizeof(szPath));
     370                                AssertReturn(cbBufLeft > 0, VERR_FILENAME_TOO_LONG);
     371                                char *pszNamePart = &szPath[cbBufLeft]; NOREF(pszNamePart);
     372                                cbBufLeft = sizeof(szPath) - cbBufLeft;
     373                                static const char s_szVirtualBox_exe[] = "VBoxSVC.exe";
     374                                vrc = RTStrCopy(pszNamePart, cbBufLeft, s_szVirtualBox_exe);
     375                                AssertRCReturn(vrc, vrc);
     376                                const char *apszArgs[] =
     377                                {
     378                                    szPath,
     379                                    "--registervbox",
     380                                    NULL
     381                                };
     382
     383                                RTPROCESS pid;
     384                                vrc = RTProcCreateEx(szPath,
     385                                                     apszArgs,
     386                                                     RTENV_DEFAULT,
     387                                                     RTPROC_FLAGS_TOKEN_SUPPLIED,
     388                                                     NULL, NULL, NULL, NULL, NULL, &hThreadToken, &pid);
     389
     390                                if (RT_SUCCESS(vrc))
     391                                {
     392                                    pUserData->m_pidTheChosenOne = pid;
     393                                    pUserData->m_tickTheChosenOne = GetTickCount();
     394                                    hrc = E_PENDING;
     395                                }
     396                                else
     397                                    LogRel(("registerVBoxSVC: Create VBoxSVC process failed: %Rrc\n", vrc));
     398                            }
     399                            else
     400                            {
     401                                hrc = E_FAIL;
     402                                LogRel(("registerVBoxSVC: SetTokenInformation failed: %ld\n", GetLastError()));
     403                            }
     404                        }
     405                        else /* the VBoxSVC in Windows session 0 already started */
     406                            hrc = E_PENDING;
     407                    }
     408                    CloseHandle(hThreadToken);
     409
     410                    if (SUCCEEDED(hrc) && dwSessionId == 0)
     411                    {
     412#endif
     413                        LogRel(("registerVBoxSVC: Making aPid=%u (%#x) the chosen one for user %s (%s)!\n",
     414                                aPid, aPid, pUserData->m_strUserSid.c_str(), pUserData->m_strUsername.c_str()));
    298415#ifdef WITH_WATCHER
    299                     /* Open the process so we can watch it. */
    300                     HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE /*fInherit*/, aPid);
    301                     if (hProcess == NULL)
    302                         hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE /*fInherit*/, aPid);
    303                     if (hProcess == NULL)
    304                         hProcess = OpenProcess(SYNCHRONIZE, FALSE /*fInherit*/, aPid);
    305                     if (hProcess != NULL)
    306                     {
    307                         if (i_watchIt(pUserData, hProcess, aPid))
     416                        /* Open the process so we can watch it. */
     417                        HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE /*fInherit*/, aPid);
     418                        if (hProcess == NULL)
     419                            hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE /*fInherit*/, aPid);
     420                        if (hProcess == NULL)
     421                            hProcess = OpenProcess(SYNCHRONIZE, FALSE /*fInherit*/, aPid);
     422                        if (hProcess != NULL)
     423                        {
     424                            if (i_watchIt(pUserData, hProcess, aPid))
    308425#endif
    309                         {
    310                             /* Make it official... */
    311                             pUserData->m_ptrTheChosenOne = aVBoxSVC;
    312                             pUserData->m_pidTheChosenOne = aPid;
    313                             hrc = S_OK;
     426                            {
     427                                /* Make it official... */
     428                                pUserData->m_ptrTheChosenOne = aVBoxSVC;
     429                                pUserData->m_pidTheChosenOne = aPid;
     430                                hrc = S_OK;
     431                            }
     432#ifdef WITH_WATCHER
     433                            else
     434                            {
     435
     436                                LogRel(("registerVBoxSVC: i_watchIt failed!\n"));
     437                                hrc = RPC_E_OUT_OF_RESOURCES;
     438                            }
    314439                        }
    315 #ifdef WITH_WATCHER
    316440                        else
    317441                        {
    318 
    319                             LogRel(("registerVBoxSVC: i_watchIt failed!\n"));
    320                             hrc = RPC_E_OUT_OF_RESOURCES;
     442                            LogRel(("registerVBoxSVC: OpenProcess() failed: %ld\n", GetLastError()));
     443                            hrc = E_ACCESSDENIED;
    321444                        }
    322                     }
    323                     else
    324                     {
    325                         LogRel(("registerVBoxSVC: OpenProcess failed: %u\n", GetLastError()));
    326                         hrc = E_ACCESSDENIED;
     445#endif
     446#ifdef VBOX_WITH_VBOXSVC_SESSION_0
    327447                    }
    328448#endif
    329449                }
    330 
    331450                pUserData->i_unlock();
    332451                pUserData->i_release();
     
    474593    a_pStrUsername->setNull();
    475594
    476     CoInitializeEx(NULL, COINIT_MULTITHREADED); // is this necessary?
    477595    HRESULT hrc = CoImpersonateClient();
    478596    if (SUCCEEDED(hrc))
     
    555673    else
    556674        LogRel(("i_GetClientUserSID: CoImpersonateClient failed: %Rhrc\n", hrc));
    557     CoUninitialize();
    558675    return fRet;
    559676}
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