diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
|---|---|---|
| committer | <> | 2014-05-08 15:03:54 +0000 |
| commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
| tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp | |
| parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
| download | VirtualBox-master.tar.gz | |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp')
| -rw-r--r-- | src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp | 211 |
1 files changed, 130 insertions, 81 deletions
diff --git a/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp b/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp index 4a6d62f5..bca3b245 100644 --- a/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp +++ b/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp @@ -21,7 +21,7 @@ #include <VBox/com/Guid.h> #include <VBox/com/ErrorInfo.h> #include <VBox/com/errorprint.h> -#include <VBox/com/EventQueue.h> +#include <VBox/com/NativeEventQueue.h> #include <VBox/com/VirtualBox.h> #include <VBox/com/listeners.h> @@ -73,7 +73,7 @@ using namespace com; /* global weak references (for event handlers) */ static IConsole *gConsole = NULL; -static EventQueue *gEventQ = NULL; +static NativeEventQueue *gEventQ = NULL; /* flag whether frontend should terminate */ static volatile bool g_fTerminateFE = false; @@ -164,93 +164,129 @@ public: { case VBoxEventType_OnGuestPropertyChanged: { - ComPtr<IGuestPropertyChangedEvent> gpcev = aEvent; - Assert(gpcev); + ComPtr<IGuestPropertyChangedEvent> pChangedEvent = aEvent; + Assert(pChangedEvent); - Bstr aKey; - gpcev->COMGETTER(Name)(aKey.asOutParam()); + HRESULT hrc; - if (aKey == Bstr("/VirtualBox/GuestInfo/OS/NoLoggedInUsers")) + ComPtr <IMachine> pMachine; + if (gConsole) { - /* Check if this is our machine and the "disconnect on logout feature" is enabled. */ - BOOL fProcessDisconnectOnGuestLogout = FALSE; - ComPtr <IMachine> machine; - HRESULT hrc = S_OK; - - if (gConsole) + hrc = gConsole->COMGETTER(Machine)(pMachine.asOutParam()); + if (SUCCEEDED(hrc) && pMachine) { - hrc = gConsole->COMGETTER(Machine)(machine.asOutParam()); - if (SUCCEEDED(hrc) && machine) - { - Bstr id, machineId; - hrc = machine->COMGETTER(Id)(id.asOutParam()); - gpcev->COMGETTER(MachineId)(machineId.asOutParam()); - if (id == machineId) - { - Bstr value1; - hrc = machine->GetExtraData(Bstr("VRDP/DisconnectOnGuestLogout").raw(), - value1.asOutParam()); - if (SUCCEEDED(hrc) && value1 == "1") - { - fProcessDisconnectOnGuestLogout = TRUE; - } - } - } + Bstr gpMachineId, machineId; + hrc = pMachine->COMGETTER(Id)(gpMachineId.asOutParam()); + AssertComRC(hrc); + hrc = pChangedEvent->COMGETTER(MachineId)(machineId.asOutParam()); + AssertComRC(hrc); + if (gpMachineId != machineId) + hrc = VBOX_E_OBJECT_NOT_FOUND; } + } + else + hrc = VBOX_E_INVALID_VM_STATE; + + if (SUCCEEDED(hrc)) + { + Bstr strKey; + hrc = pChangedEvent->COMGETTER(Name)(strKey.asOutParam()); + AssertComRC(hrc); + + Bstr strValue; + hrc = pChangedEvent->COMGETTER(Value)(strValue.asOutParam()); + AssertComRC(hrc); - if (fProcessDisconnectOnGuestLogout) + Utf8Str utf8Key = strKey; + Utf8Str utf8Value = strValue; + LogRelFlow(("Guest property \"%s\" has been changed to \"%s\"\n", + utf8Key.c_str(), utf8Value.c_str())); + + if (utf8Key.equals("/VirtualBox/GuestInfo/OS/NoLoggedInUsers")) { - bool fDropConnection = false; + LogRelFlow(("Guest indicates that there %s logged in users\n", + utf8Value.equals("true") ? "are no" : "are")); - Bstr value; - gpcev->COMGETTER(Value)(value.asOutParam()); - Utf8Str utf8Value = value; + /* Check if this is our machine and the "disconnect on logout feature" is enabled. */ + BOOL fProcessDisconnectOnGuestLogout = FALSE; - if (!mfNoLoggedInUsers) /* Only if the property really changes. */ + /* Does the machine handle VRDP disconnects? */ + Bstr strDiscon; + hrc = pMachine->GetExtraData(Bstr("VRDP/DisconnectOnGuestLogout").raw(), + strDiscon.asOutParam()); + if (SUCCEEDED(hrc)) { - if ( utf8Value == "true" - /* Guest property got deleted due to reset, - * so it has no value anymore. */ - || utf8Value.isEmpty()) - { - mfNoLoggedInUsers = true; - fDropConnection = true; - } + Utf8Str utf8Discon = strDiscon; + fProcessDisconnectOnGuestLogout = utf8Discon.equals("1") + ? TRUE : FALSE; } - else if (utf8Value == "false") - mfNoLoggedInUsers = false; - /* Guest property got deleted due to reset, - * take the shortcut without touching the mfNoLoggedInUsers - * state. */ - else if (utf8Value.isEmpty()) - fDropConnection = true; - - if (fDropConnection) + + LogRelFlow(("VRDE: hrc=%Rhrc: Host %s disconnecting clients (current host state known: %s)\n", + hrc, fProcessDisconnectOnGuestLogout ? "will handle" : "does not handle", + mfNoLoggedInUsers ? "No users logged in" : "Users logged in")); + + if (fProcessDisconnectOnGuestLogout) { - /* If there is a connection, drop it. */ - ComPtr<IVRDEServerInfo> info; - hrc = gConsole->COMGETTER(VRDEServerInfo)(info.asOutParam()); - if (SUCCEEDED(hrc) && info) + bool fDropConnection = false; + if (!mfNoLoggedInUsers) /* Only if the property really changes. */ + { + if ( utf8Value == "true" + /* Guest property got deleted due to reset, + * so it has no value anymore. */ + || utf8Value.isEmpty()) + { + mfNoLoggedInUsers = true; + fDropConnection = true; + } + } + else if (utf8Value == "false") + mfNoLoggedInUsers = false; + /* Guest property got deleted due to reset, + * take the shortcut without touching the mfNoLoggedInUsers + * state. */ + else if (utf8Value.isEmpty()) + fDropConnection = true; + + LogRelFlow(("VRDE: szNoLoggedInUsers=%s, mfNoLoggedInUsers=%RTbool, fDropConnection=%RTbool\n", + utf8Value.c_str(), mfNoLoggedInUsers, fDropConnection)); + + if (fDropConnection) { - ULONG cClients = 0; - hrc = info->COMGETTER(NumberOfClients)(&cClients); - if (SUCCEEDED(hrc) && cClients > 0) + /* If there is a connection, drop it. */ + ComPtr<IVRDEServerInfo> info; + hrc = gConsole->COMGETTER(VRDEServerInfo)(info.asOutParam()); + if (SUCCEEDED(hrc) && info) { - ComPtr <IVRDEServer> vrdeServer; - hrc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); - if (SUCCEEDED(hrc) && vrdeServer) + ULONG cClients = 0; + hrc = info->COMGETTER(NumberOfClients)(&cClients); + + LogRelFlow(("VRDE: connected clients=%RU32\n", cClients)); + if (SUCCEEDED(hrc) && cClients > 0) { - LogRel(("VRDE: the guest user has logged out, disconnecting remote clients.\n")); - vrdeServer->COMSETTER(Enabled)(FALSE); - vrdeServer->COMSETTER(Enabled)(TRUE); + ComPtr <IVRDEServer> vrdeServer; + hrc = pMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + if (SUCCEEDED(hrc) && vrdeServer) + { + LogRel(("VRDE: the guest user has logged out, disconnecting remote clients.\n")); + hrc = vrdeServer->COMSETTER(Enabled)(FALSE); + AssertComRC(hrc); + HRESULT hrc2 = vrdeServer->COMSETTER(Enabled)(TRUE); + if (SUCCEEDED(hrc)) + hrc = hrc2; + } } } } } } + + if (FAILED(hrc)) + LogRelFlow(("VRDE: returned error=%Rhrc\n", hrc)); } + break; } + default: AssertFailed(); } @@ -259,6 +295,7 @@ public: } private: + bool mfNoLoggedInUsers; }; @@ -295,7 +332,7 @@ public: { ComPtr<IMouseCapabilityChangedEvent> mccev = aEvent; - Assert(mccev); + Assert(!mccev.isNull()); BOOL fSupportsAbsolute = false; mccev->COMGETTER(SupportsAbsolute)(&fSupportsAbsolute); @@ -496,7 +533,12 @@ static void parse_environ(unsigned long *pulFrameWidth, unsigned long *pulFrameH unsigned long *pulBitRate, const char **ppszFileName) { const char *pszEnvTemp; - +/** @todo r=bird: This isn't up to scratch. The life time of an RTEnvGet + * return value is only up to the next RTEnv*, *getenv, *putenv, + * setenv call in _any_ process in the system and the it has known and + * documented code page issues. + * + * Use RTEnvGetEx instead! */ if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREWIDTH")) != 0) { errno = 0; @@ -612,18 +654,18 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) unsigned fPATM = ~0U; unsigned fCSAM = ~0U; #ifdef VBOX_WITH_VIDEO_REC - unsigned fVIDEOREC = 0; + bool fVideoRec = 0; unsigned long ulFrameWidth = 800; unsigned long ulFrameHeight = 600; - unsigned long ulBitRate = 300000; - char pszMPEGFile[RTPATH_MAX]; + unsigned long ulBitRate = 300000; /** @todo r=bird: The COM type ULONG isn't unsigned long, it's 32-bit unsigned int. */ + char szMpegFile[RTPATH_MAX]; const char *pszFileNameParam = "VBox-%d.vob"; #endif /* VBOX_WITH_VIDEO_REC */ - LogFlow (("VBoxHeadless STARTED.\n")); - RTPrintf (VBOX_PRODUCT " Headless Interface " VBOX_VERSION_STRING "\n" - "(C) 2008-" VBOX_C_YEAR " " VBOX_VENDOR "\n" - "All rights reserved.\n\n"); + LogFlow(("VBoxHeadless STARTED.\n")); + RTPrintf(VBOX_PRODUCT " Headless Interface " VBOX_VERSION_STRING "\n" + "(C) 2008-" VBOX_C_YEAR " " VBOX_VENDOR "\n" + "All rights reserved.\n\n"); #ifdef VBOX_WITH_VIDEO_REC /* Parse the environment */ @@ -754,7 +796,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) break; #ifdef VBOX_WITH_VIDEO_REC case 'c': - fVIDEOREC = true; + fVideoRec = true; break; case 'w': ulFrameWidth = ValueUnion.u32; @@ -818,7 +860,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) LogError("VBoxHeadless: ERROR: Only one format modifier is allowed in the capture file name.", -1); return 1; } - RTStrPrintf(&pszMPEGFile[0], RTPATH_MAX, pszFileNameParam, RTProcSelf()); + RTStrPrintf(&szMpegFile[0], RTPATH_MAX, pszFileNameParam, RTProcSelf()); #endif /* defined VBOX_WITH_VIDEO_REC */ if (!pcszNameOrUUID) @@ -933,7 +975,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) RTLDRMOD hLdrVideoRecFB; PFNREGISTERVIDEORECFB pfnRegisterVideoRecFB; - if (fVIDEOREC) + if (fVideoRec) { HRESULT rcc = S_OK; int rrc = VINF_SUCCESS; @@ -957,7 +999,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) { Log2(("VBoxHeadless: calling pfnRegisterVideoRecFB\n")); rcc = pfnRegisterVideoRecFB(ulFrameWidth, ulFrameHeight, ulBitRate, - pszMPEGFile, &pFramebuffer); + szMpegFile, &pFramebuffer); if (rcc != S_OK) LogError("Failed to initialise video capturing - make sure that the file format\n" "you wish to use is supported on your system\n", rcc); @@ -983,7 +1025,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) for (uScreenId = 0; uScreenId < cMonitors; uScreenId++) { # ifdef VBOX_WITH_VIDEO_REC - if (fVIDEOREC && uScreenId == 0) + if (fVideoRec && uScreenId == 0) { /* Already registered. */ continue; @@ -1067,7 +1109,7 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) /* initialize global references */ gConsole = console; - gEventQ = com::EventQueue::getMainEventQueue(); + gEventQ = com::NativeEventQueue::getMainEventQueue(); /* VirtualBoxClient events registration. */ { @@ -1251,6 +1293,13 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp) vboxListener = listener; com::SafeArray<VBoxEventType_T> eventTypes; eventTypes.push_back(VBoxEventType_OnGuestPropertyChanged); + + /** + * @todo Set the notification pattern to "/VirtualBox/GuestInfo/OS/ *Logged*" + * to not cause too much load. The current API is broken as + * IMachine::GuestPropertyNotificationPatterns() would change the + * filter for _all_ clients. This is not what we want! + */ CHECK_ERROR(es, RegisterListener(vboxListener, ComSafeArrayAsInParam(eventTypes), true)); } |
