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/HostServices/GuestProperties | |
| 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/HostServices/GuestProperties')
| -rw-r--r-- | src/VBox/HostServices/GuestProperties/service.cpp | 213 | ||||
| -rw-r--r-- | src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp | 12 |
2 files changed, 125 insertions, 100 deletions
diff --git a/src/VBox/HostServices/GuestProperties/service.cpp b/src/VBox/HostServices/GuestProperties/service.cpp index addcbec5..bd3a1626 100644 --- a/src/VBox/HostServices/GuestProperties/service.cpp +++ b/src/VBox/HostServices/GuestProperties/service.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2008 Oracle Corporation + * Copyright (C) 2008-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -138,18 +138,20 @@ struct GuestCall VBOXHGCMCALLHANDLE mHandle; /** The function that was requested */ uint32_t mFunction; + /** Number of call parameters. */ + uint32_t mParmsCnt; /** The call parameters */ VBOXHGCMSVCPARM *mParms; /** The default return value, used for passing warnings */ int mRc; /** The standard constructor */ - GuestCall() : u32ClientId(0), mFunction(0) {} + GuestCall(void) : u32ClientId(0), mFunction(0), mParmsCnt(0) {} /** The normal constructor */ GuestCall(uint32_t aClientId, VBOXHGCMCALLHANDLE aHandle, uint32_t aFunction, - VBOXHGCMSVCPARM aParms[], int aRc) - : u32ClientId(aClientId), mHandle(aHandle), mFunction(aFunction), mParms(aParms), - mRc(aRc) {} + uint32_t aParmsCnt, VBOXHGCMSVCPARM aParms[], int aRc) + : u32ClientId(aClientId), mHandle(aHandle), mFunction(aFunction), + mParmsCnt(aParmsCnt), mParms(aParms), mRc(aRc) {} }; /** The guest call list type */ typedef std::list <GuestCall> CallList; @@ -170,7 +172,8 @@ private: RTSTRSPACE mhProperties; /** The number of properties. */ unsigned mcProperties; - /** The list of property changes for guest notifications */ + /** The list of property changes for guest notifications; + * only used for timestamp tracking in notifications at the moment */ PropertyList mGuestNotifications; /** The list of outstanding guest notification calls */ CallList mGuestWaiters; @@ -375,8 +378,8 @@ private: VBOXHGCMSVCPARM paParms[]); int getOldNotificationInternal(const char *pszPattern, uint64_t u64Timestamp, Property *pProp); - int getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop); - void doNotifications(const char *pszProperty, uint64_t u64Timestamp); + int getNotificationWriteOut(uint32_t cParms, VBOXHGCMSVCPARM paParms[], Property prop); + int doNotifications(const char *pszProperty, uint64_t u64Timestamp); int notifyHost(const char *pszName, const char *pszValue, uint64_t u64Timestamp, const char *pszFlags); @@ -701,35 +704,41 @@ int Service::setProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGues } else if (mcProperties < MAX_PROPS) { - /* Create a new string space record. */ - pProp = new Property(pcszName, pcszValue, u64TimeNano, fFlags); - if (pProp) + try { + /* Create a new string space record. */ + pProp = new Property(pcszName, pcszValue, u64TimeNano, fFlags); + AssertPtr(pProp); + if (RTStrSpaceInsert(&mhProperties, &pProp->mStrCore)) mcProperties++; else { AssertFailed(); delete pProp; - rc = VERR_INTERNAL_ERROR_3; + + rc = VERR_ALREADY_EXISTS; } } - else + catch (std::bad_alloc) + { rc = VERR_NO_MEMORY; + } } else rc = VERR_TOO_MUCH_DATA; /* - * Send a notification to the host and return. + * Send a notification to the guest and host and return. */ // if (isGuest) /* Notify the host even for properties that the host // * changed. Less efficient, but ensures consistency. */ - doNotifications(pcszName, u64TimeNano); - Log2(("Set string %s, rc=%Rrc, value=%s\n", pcszName, rc, pcszValue)); + int rc2 = doNotifications(pcszName, u64TimeNano); + if (RT_SUCCESS(rc)) + rc = rc2; } - LogFlowThisFunc(("rc = %Rrc (%s = %s)\n", rc, pcszName, pcszValue)); + LogFlowThisFunc(("%s=%s, rc=%Rrc\n", pcszName, pcszValue, rc)); return rc; } @@ -763,7 +772,7 @@ int Service::delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGues rc = VERR_INVALID_PARAMETER; if (RT_FAILURE(rc)) { - LogFlowThisFunc(("rc = %Rrc\n", rc)); + LogFlowThisFunc(("rc=%Rrc\n", rc)); return rc; } @@ -787,10 +796,12 @@ int Service::delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGues delete pProp; // if (isGuest) /* Notify the host even for properties that the host // * changed. Less efficient, but ensures consistency. */ - doNotifications(pcszName, u64Timestamp); + int rc2 = doNotifications(pcszName, u64Timestamp); + if (RT_SUCCESS(rc)) + rc = rc2; } - LogFlowThisFunc(("rc = %Rrc (%s)\n", rc, pcszName)); + LogFlowThisFunc(("%s: rc=%Rrc\n", pcszName, rc)); return rc; } @@ -967,15 +978,17 @@ int Service::getOldNotificationInternal(const char *pszPatterns, /** Helper query used by getNotification */ -int Service::getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop) +int Service::getNotificationWriteOut(uint32_t cParms, VBOXHGCMSVCPARM paParms[], Property prop) { - int rc = VINF_SUCCESS; + AssertReturn(cParms == 4, VERR_INVALID_PARAMETER); /* Basic sanity checking. */ + /* Format the data to write to the buffer. */ std::string buffer; uint64_t u64Timestamp; char *pchBuf; uint32_t cbBuf; - rc = paParms[2].getBuffer((void **)&pchBuf, &cbBuf); + + int rc = paParms[2].getBuffer((void **)&pchBuf, &cbBuf); if (RT_SUCCESS(rc)) { char szFlags[MAX_FLAGS_LEN]; @@ -1014,8 +1027,8 @@ int Service::getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop) * @thread HGCM * @throws can throw std::bad_alloc */ -int Service::getNotification(uint32_t u32ClientId, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, - VBOXHGCMSVCPARM paParms[]) +int Service::getNotification(uint32_t u32ClientId, VBOXHGCMCALLHANDLE callHandle, + uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { int rc = VINF_SUCCESS; char *pszPatterns = NULL; /* shut up gcc */ @@ -1034,9 +1047,9 @@ int Service::getNotification(uint32_t u32ClientId, VBOXHGCMCALLHANDLE callHandle || RT_FAILURE(paParms[2].getBuffer((void **)&pchBuf, &cbBuf)) /* return buffer */ ) rc = VERR_INVALID_PARAMETER; + if (RT_SUCCESS(rc)) - LogFlow((" pszPatterns=%s, u64Timestamp=%llu\n", pszPatterns, - u64Timestamp)); + LogFlow(("pszPatterns=%s, u64Timestamp=%llu\n", pszPatterns, u64Timestamp)); /* * If no timestamp was supplied or no notification was found in the queue @@ -1045,45 +1058,50 @@ int Service::getNotification(uint32_t u32ClientId, VBOXHGCMCALLHANDLE callHandle Property prop; if (RT_SUCCESS(rc) && u64Timestamp != 0) rc = getOldNotification(pszPatterns, u64Timestamp, &prop); - if (RT_SUCCESS(rc) && prop.isNull()) + if (RT_SUCCESS(rc)) { - /* - * Check if the client already had the same request. - * Complete the old request with an error in this case. - * Protection against clients, which cancel and resubmits requests. - */ - CallList::iterator it = mGuestWaiters.begin(); - while (it != mGuestWaiters.end()) + if (prop.isNull()) { - const char *pszPatternsExisting; - uint32_t cchPatternsExisting; - int rc3 = it->mParms[0].getString(&pszPatternsExisting, &cchPatternsExisting); - - if ( RT_SUCCESS(rc3) - && u32ClientId == it->u32ClientId - && RTStrCmp(pszPatterns, pszPatternsExisting) == 0) + /* + * Check if the client already had the same request. + * Complete the old request with an error in this case. + * Protection against clients, which cancel and resubmits requests. + */ + CallList::iterator it = mGuestWaiters.begin(); + while (it != mGuestWaiters.end()) { - /* Complete the old request. */ - mpHelpers->pfnCallComplete(it->mHandle, VERR_INTERRUPTED); - it = mGuestWaiters.erase(it); + const char *pszPatternsExisting; + uint32_t cchPatternsExisting; + int rc3 = it->mParms[0].getString(&pszPatternsExisting, &cchPatternsExisting); + + if ( RT_SUCCESS(rc3) + && u32ClientId == it->u32ClientId + && RTStrCmp(pszPatterns, pszPatternsExisting) == 0) + { + /* Complete the old request. */ + mpHelpers->pfnCallComplete(it->mHandle, VERR_INTERRUPTED); + it = mGuestWaiters.erase(it); + } + else + ++it; } - else - ++it; - } - mGuestWaiters.push_back(GuestCall(u32ClientId, callHandle, GET_NOTIFICATION, - paParms, rc)); - rc = VINF_HGCM_ASYNC_EXECUTE; - } - /* - * Otherwise reply at once with the enqueued notification we found. - */ - else - { - int rc2 = getNotificationWriteOut(paParms, prop); - if (RT_FAILURE(rc2)) - rc = rc2; + mGuestWaiters.push_back(GuestCall(u32ClientId, callHandle, GET_NOTIFICATION, + cParms, paParms, rc)); + rc = VINF_HGCM_ASYNC_EXECUTE; + } + /* + * Otherwise reply at once with the enqueued notification we found. + */ + else + { + int rc2 = getNotificationWriteOut(cParms, paParms, prop); + if (RT_FAILURE(rc2)) + rc = rc2; + } } + + LogFlowThisFunc(("returning rc=%Rrc\n", rc)); return rc; } @@ -1096,10 +1114,10 @@ int Service::getNotification(uint32_t u32ClientId, VBOXHGCMCALLHANDLE callHandle * * @thread HGCM service */ -void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp) +int Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp) { - AssertPtrReturnVoid(pszProperty); - LogFlowThisFunc (("pszProperty=%s, u64Timestamp=%llu\n", pszProperty, u64Timestamp)); + AssertPtrReturn(pszProperty, VERR_INVALID_POINTER); + LogFlowThisFunc(("pszProperty=%s, u64Timestamp=%llu\n", pszProperty, u64Timestamp)); /* Ensure that our timestamp is different to the last one. */ if ( !mGuestNotifications.empty() && u64Timestamp == mGuestNotifications.back().mTimestamp) @@ -1121,8 +1139,8 @@ void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp) prop.mFlags = pProp->mFlags; } - /* Release waiters if applicable and add the event to the queue for - * guest notifications */ + /* Release guest waiters if applicable and add the event + * to the queue for guest notifications */ int rc = VINF_SUCCESS; try { @@ -1135,7 +1153,7 @@ void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp) if (prop.Matches(pszPatterns)) { GuestCall curCall = *it; - int rc2 = getNotificationWriteOut(curCall.mParms, prop); + int rc2 = getNotificationWriteOut(curCall.mParmsCnt, curCall.mParms, prop); if (RT_SUCCESS(rc2)) rc2 = curCall.mRc; mpHelpers->pfnCallComplete(curCall.mHandle, rc2); @@ -1144,41 +1162,48 @@ void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp) else ++it; } + mGuestNotifications.push_back(prop); + + /** @todo r=andy This list does not have a purpose but for tracking + * the timestamps ... */ + if (mGuestNotifications.size() > MAX_GUEST_NOTIFICATIONS) + mGuestNotifications.pop_front(); } catch (std::bad_alloc) { rc = VERR_NO_MEMORY; } - if (mGuestNotifications.size() > MAX_GUEST_NOTIFICATIONS) - mGuestNotifications.pop_front(); - /* - * Host notifications - first case: if the property exists then send its - * current value - */ - if (pProp && mpfnHostCallback != NULL) + if ( RT_SUCCESS(rc) + && mpfnHostCallback) { - char szFlags[MAX_FLAGS_LEN]; - /* Send out a host notification */ - const char *pszValue = prop.mValue.c_str(); - if (RT_SUCCESS(rc)) + /* + * Host notifications - first case: if the property exists then send its + * current value + */ + if (pProp) + { + char szFlags[MAX_FLAGS_LEN]; + /* Send out a host notification */ + const char *pszValue = prop.mValue.c_str(); rc = writeFlags(prop.mFlags, szFlags); - if (RT_SUCCESS(rc)) - rc = notifyHost(pszProperty, pszValue, u64Timestamp, szFlags); - } - - /* - * Host notifications - second case: if the property does not exist then - * send the host an empty value - */ - if (!pProp && mpfnHostCallback != NULL) - { - /* Send out a host notification */ - if (RT_SUCCESS(rc)) + if (RT_SUCCESS(rc)) + rc = notifyHost(pszProperty, pszValue, u64Timestamp, szFlags); + } + /* + * Host notifications - second case: if the property does not exist then + * send the host an empty value + */ + else + { + /* Send out a host notification */ rc = notifyHost(pszProperty, "", u64Timestamp, ""); + } } - LogFlowThisFunc(("returning\n")); + + LogFlowThisFunc(("returning rc=%Rrc\n", rc)); + return rc; } /** @@ -1200,10 +1225,10 @@ int Service::notifyHost(const char *pszName, const char *pszValue, HostCallbackData.pcszValue = pszValue; HostCallbackData.u64Timestamp = u64Timestamp; HostCallbackData.pcszFlags = pszFlags; - int rc = mpfnHostCallback (mpvHostData, 0 /*u32Function*/, - (void *)(&HostCallbackData), - sizeof(HostCallbackData)); - LogFlowFunc (("returning %Rrc\n", rc)); + int rc = mpfnHostCallback(mpvHostData, 0 /*u32Function*/, + (void *)(&HostCallbackData), + sizeof(HostCallbackData)); + LogFlowFunc(("returning rc=%Rrc\n", rc)); return rc; } diff --git a/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp b/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp index 782fd87a..a1d3c387 100644 --- a/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp +++ b/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2008 Oracle Corporation + * Copyright (C) 2008-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -431,7 +431,7 @@ int doSetProperty(VBOXHGCMSVCFNTABLE *pTable, const char *pcszName, */ static void testSetProp(VBOXHGCMSVCFNTABLE *pTable) { - RTTestISub("SET_PROP, SET_PROP_VALUE, SET_PROP_HOST, SET_PROP_VALUE_HOST"); + RTTestISub("SET_PROP, _VALUE, _HOST, _VALUE_HOST"); /** Array of properties for testing SET_PROP_HOST and _GUEST. */ static const struct @@ -745,7 +745,7 @@ struct asyncNotification_ */ static void setupAsyncNotification(VBOXHGCMSVCFNTABLE *pTable) { - RTTestISub("Asynchronous GET_NOTIFICATION call with no notifications are available"); + RTTestISub("Async GET_NOTIFICATION without notifications"); static char s_szPattern[] = ""; g_AsyncNotification.aParms[0].setPointer((void *)s_szPattern, sizeof(s_szPattern)); @@ -796,7 +796,7 @@ static void test2(void) /* Set up the asynchronous notification test */ setupAsyncNotification(&svcTable); testSetProp(&svcTable); - RTTestISub("Checking the data returned by the asynchronous notification call"); + RTTestISub("Async notification call data"); testAsyncNotification(&svcTable); /* Our previous notification call should have completed by now. */ testDelProp(&svcTable); @@ -838,7 +838,7 @@ static int doSetGlobalFlags(VBOXHGCMSVCFNTABLE *pTable, ePropFlags eFlags) */ static void testSetPropROGuest(VBOXHGCMSVCFNTABLE *pTable) { - RTTestISub("SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls with READONLYGUEST set globally"); + RTTestISub("global READONLYGUEST and SET_PROP*"); /** Array of properties for testing SET_PROP_HOST and _GUEST with the * READONLYGUEST global flag set. */ @@ -908,7 +908,7 @@ static void testSetPropROGuest(VBOXHGCMSVCFNTABLE *pTable) */ static void testDelPropROGuest(VBOXHGCMSVCFNTABLE *pTable) { - RTTestISub("DEL_PROP and DEL_PROP_HOST calls with RDONLYGUEST set globally"); + RTTestISub("global READONLYGUEST and DEL_PROP*"); /** Array of properties for testing DEL_PROP_HOST and _GUEST with * READONLYGUEST set globally. */ |
