Changeset 80569 in vbox for trunk/src/VBox/Main
- Timestamp:
- Sep 3, 2019 2:34:21 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 133086
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/Makefile.kmk
r80398 r80569 385 385 VBoxSDS_TEMPLATE = VBOXMAINEXE 386 386 VBoxSDS_DEFS += VBOX_COM_OUTOFPROC_MODULE _WIN32_WINNT=0x0600 387 ifdef VBOX_WITH_VBOXSDL 388 VBoxSDS_DEFS += VBOX_WITH_VBOXSDL 389 endif 390 ifdef VBOX_WITH_HEADLESS 391 VBoxSDS_DEFS += VBOX_WITH_HEADLESS 392 endif 393 ifdef VBOX_WITH_QTGUI 394 VBoxSDS_DEFS += VBOX_WITH_QTGUI 395 endif 387 396 VBoxSDS_INCS = \ 388 397 include \ … … 394 403 src-global/win/VBoxSDS.cpp \ 395 404 src-global/win/VirtualBoxSDSImpl.cpp \ 396 src-global/win/VBoxSDS.rc 405 src-global/win/VBoxSDS.rc \ 406 src-all/MachineLaunchVMCommonWorker.cpp 397 407 $(call KB_FN_DO_PASS0_ON_TARGET,VBoxSDS) # Sets VBoxSDS_0_OUTDIR 398 408 … … 553 563 src-server/HostVideoInputDeviceImpl.cpp \ 554 564 src-server/MachineImpl.cpp \ 565 src-all/MachineLaunchVMCommonWorker.cpp \ 555 566 src-server/MachineImplCloneVM.cpp \ 556 567 src-server/MachineImplMoveVM.cpp \ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r80426 r80569 27033 27033 <interface 27034 27034 name="IVirtualBoxSDS" extends="$unknown" notdual="yes" 27035 uuid=" 152265b8-fe7d-4077-9dd6-032bc3f1c5a3"27035 uuid="bc1a2773-18f2-4066-08ce-1e44d59d84af" 27036 27036 wsmap="suppress" internal="yes" 27037 27037 reservedMethods="0" reservedAttributes="0" … … 27068 27068 <param name="pid" type="long" dir="in"> 27069 27069 <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> 27070 27141 </param> 27071 27142 </method> -
trunk/src/VBox/Main/include/VirtualBoxSDSImpl.h
r76562 r80569 94 94 STDMETHOD(RegisterVBoxSVC)(IVBoxSVCRegistration *aVBoxSVC, LONG aPid, IUnknown **aExistingVirtualBox); 95 95 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); 96 98 /** @} */ 97 99 -
trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp
r77624 r80569 2508 2508 NULL /*pszAsUser*/, 2509 2509 NULL /*pszPassword*/, 2510 NULL /*pvExtraData*/, 2510 2511 &hProcess); 2511 2512 if (RT_SUCCESS(vrc)) -
trunk/src/VBox/Main/src-client/ClientTokenHolder.cpp
r77436 r80569 250 250 HANDLE initDoneSem = (HANDLE)data[1]; 251 251 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())); 255 257 if (mutex) 256 258 { -
trunk/src/VBox/Main/src-global/win/VirtualBoxSDSImpl.cpp
r76592 r80569 31 31 #include <iprt/critsect.h> 32 32 #include <iprt/mem.h> 33 #include <iprt/process.h> 33 34 #include <iprt/system.h> 34 35 … … 37 38 #include <sddl.h> 38 39 #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) 39 51 40 52 … … 388 400 hrc = E_INVALIDARG; 389 401 LogRel2(("VirtualBoxSDS::deregisterVBoxSVC: returns %Rhrc\n", hrc)); 402 return hrc; 403 } 404 405 406 STDMETHODIMP 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)); 390 460 return hrc; 391 461 } … … 592 662 } 593 663 664 594 665 #ifdef WITH_WATCHER 595 666 /** -
trunk/src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp
r77178 r80569 1548 1548 */ 1549 1549 RTPROCESS hProcess; 1550 rc = RTProcCreateEx(papszArgs[iSuArg], &papszArgs[iSuArg], RTENV_DEFAULT, 0 /*fFlags*/, 1551 NULL /*phStd In*/, 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*/, 1552 1552 &hProcess); 1553 1553 if (RT_SUCCESS(rc)) -
trunk/src/VBox/Main/src-server/ClientToken.cpp
r76553 r80569 40 40 #include "ClientToken.h" 41 41 #include "MachineImpl.h" 42 43 #ifdef RT_OS_WINDOWS 44 # include <sddl.h> 45 #endif 42 46 43 47 Machine::ClientToken::ClientToken() … … 83 87 #if defined(RT_OS_WINDOWS) 84 88 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()); 90 156 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 94 162 #elif defined(RT_OS_OS2) 95 163 NOREF(pSessionMachine); -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r80074 r80569 49 49 #include "MachineImplMoveVM.h" 50 50 #include "ExtPackManagerImpl.h" 51 #include "MachineLaunchVMCommonWorker.h" 51 52 52 53 // generated header … … 7409 7410 } 7410 7411 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 do7430 {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 environment7439 * (ignore empty variable names here since RTEnv API7440 * 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 else7456 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 7474 7412 /* Hardening logging */ 7475 7413 #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_HARDENING) … … 7493 7431 RTFileDelete(strOldStartupLogFile.c_str()); 7494 7432 } 7495 const char *pszSupHardeningLogArg = strSupHardeningLogArg.c_str();7496 7433 #else 7497 const char *pszSupHardeningLogArg = NULL;7434 Utf8Str strSupHardeningLogArg; 7498 7435 #endif 7499 7436 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; 7500 7443 Utf8Str strCanonicalName; 7501 7444 if (false) 7445 { } 7502 7446 #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)) 7508 7452 { 7509 7453 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 7570 7475 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 } 7605 7611 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())); 7667 7623 7668 7624 if (!fSeparate) -
trunk/src/VBox/Main/src-server/generic/AutostartDb-generic.cpp
r76553 r80569 190 190 rc = autostartModifyDb(true /* fAutostart */, true /* fAddVM */); 191 191 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) 193 193 NOREF(pszVMId); /* Not needed */ 194 194 rc = VINF_SUCCESS; … … 210 210 rc = autostartModifyDb(true /* fAutostart */, false /* fAddVM */); 211 211 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) 213 213 NOREF(pszVMId); /* Not needed */ 214 214 rc = VINF_SUCCESS; … … 230 230 rc = autostartModifyDb(false /* fAutostart */, true /* fAddVM */); 231 231 RTCritSectLeave(&this->CritSect); 232 #elif defined(RT_OS_DARWIN) 232 #elif defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) 233 233 NOREF(pszVMId); /* Not needed */ 234 234 rc = VINF_SUCCESS; … … 250 250 rc = autostartModifyDb(false /* fAutostart */, false /* fAddVM */); 251 251 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
Note:
See TracChangeset
for help on using the changeset viewer.