STDMETHODIMP GuestFileEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
{
    switch (aType)
    {
    case VBoxEventType_OnGuestFileStateChanged:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestFileStateChangedEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestFile> pProcess;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pProcess.asOutParam()));
            AssertBreak(!pProcess.isNull());
            FileStatus_T fileSts;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&fileSts));
            Bstr strPath;
            CHECK_ERROR_BREAK(pProcess, COMGETTER(FileName)(strPath.asOutParam()));
            ULONG uID;
            CHECK_ERROR_BREAK(pProcess, COMGETTER(Id)(&uID));

            RTPrintf("File ID=%RU32 \"%s\" changed status to [%s]\n",
                     uID, Utf8Str(strPath).c_str(), gctlFileStatusToText(fileSts));

        } while (0);
        break;
    }

    default:
        AssertFailed();
    }

    return S_OK;
}
/**
 * Handles the osinfo sub-command.
 *
 * @returns Suitable exit code.
 * @param   a                   The handler arguments.
 * @param   pDebugger           Pointer to the debugger interface.
 */
static RTEXITCODE handleDebugVM_OSInfo(HandlerArg *a, IMachineDebugger *pDebugger)
{
    if (a->argc != 2)
        return errorTooManyParameters(&a->argv[1]);

    com::Bstr bstrName;
    CHECK_ERROR2I_RET(pDebugger, COMGETTER(OSName)(bstrName.asOutParam()), RTEXITCODE_FAILURE);
    com::Bstr bstrVersion;
    CHECK_ERROR2I_RET(pDebugger, COMGETTER(OSVersion)(bstrVersion.asOutParam()), RTEXITCODE_FAILURE);
    RTPrintf("Name:    %ls\n", bstrName.raw());
    RTPrintf("Version: %ls\n", bstrVersion.raw());
    return RTEXITCODE_SUCCESS;
}
/**
 * Handles logrel-settings.
 *
 * @returns Exit code.
 * @param   pDebugger           The debugger interface.
 * @param   fFlags              The debugvm show flags.
 */
static RTEXITCODE handleDebugVM_Show_LogRelSettings(IMachineDebugger *pDebugger, uint32_t fFlags)
{
    if ((fFlags & DEBUGVM_SHOW_FLAGS_FMT_MASK) == DEBUGVM_SHOW_FLAGS_HUMAN_READABLE)
        RTPrintf("Release logger settings:\n");

    com::Bstr bstr;
    CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogRelFlags)(bstr.asOutParam()), RTEXITCODE_FAILURE);
    handleDebugVM_Show_PrintVar("VBOX_RELEASE_LOG", &bstr, fFlags);

    CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogRelGroups)(bstr.asOutParam()), RTEXITCODE_FAILURE);
    handleDebugVM_Show_PrintVar("VBOX_RELEASE_LOG_FLAGS", &bstr, fFlags);

    CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogRelDestinations)(bstr.asOutParam()), RTEXITCODE_FAILURE);
    handleDebugVM_Show_PrintVar("VBOX_RELEASE_LOG_DEST", &bstr, fFlags);
    return RTEXITCODE_SUCCESS;
}
/* readonly attribute nsIException inner; */
NS_IMETHODIMP VirtualBoxErrorInfo::GetInner (nsIException **aInner)
{
    ComPtr<IVirtualBoxErrorInfo> info;
    nsresult rv = COMGETTER(Next) (info.asOutParam());
    if (FAILED(rv)) return rv;
    return info.queryInterfaceTo(aInner);
}
STDMETHODIMP VirtualBoxErrorInfo::GetGUID (GUID *guid)
{
    Bstr iid;
    HRESULT rc = COMGETTER(InterfaceID) (iid.asOutParam());
    if (SUCCEEDED(rc))
        *guid = Guid(iid).ref();
    return rc;
}
void GuestSessionEventListener::uninit(void)
{
    GuestEventProcs::iterator itProc = mProcs.begin();
    while (itProc != mProcs.end())
    {
        if (!itProc->first.isNull())
        {
            HRESULT rc;
            do
            {
                /* Listener unregistration. */
                ComPtr<IEventSource> pES;
                CHECK_ERROR_BREAK(itProc->first, COMGETTER(EventSource)(pES.asOutParam()));
                if (!pES.isNull())
                    CHECK_ERROR_BREAK(pES, UnregisterListener(itProc->second.mListener));
            } while (0);
            itProc->first->Release();
        }

        ++itProc;
    }
    mProcs.clear();

    GuestEventFiles::iterator itFile = mFiles.begin();
    while (itFile != mFiles.end())
    {
        if (!itFile->first.isNull())
        {
            HRESULT rc;
            do
            {
                /* Listener unregistration. */
                ComPtr<IEventSource> pES;
                CHECK_ERROR_BREAK(itFile->first, COMGETTER(EventSource)(pES.asOutParam()));
                if (!pES.isNull())
                    CHECK_ERROR_BREAK(pES, UnregisterListener(itFile->second.mListener));
            } while (0);
            itFile->first->Release();
        }

        ++itFile;
    }
    mFiles.clear();
}
/* readonly attribute nsresult result; */
NS_IMETHODIMP VirtualBoxErrorInfo::GetResult (nsresult *aResult)
{
    if (!aResult)
      return NS_ERROR_INVALID_POINTER;

    PRInt32 lrc;
    nsresult rc = COMGETTER(ResultCode) (&lrc);
    if (SUCCEEDED(rc))
      *aResult = lrc;
    return rc;
}
Exemplo n.º 8
0
void HostUSBDeviceFilter::i_saveSettings(settings::USBDeviceFilter &data)
{
    AutoCaller autoCaller(this);
    AssertComRCReturnVoid(autoCaller.rc());

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    data.strName = bd->mData.strName;
    data.fActive = bd->mData.fActive;
    i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_VENDOR_ID, data.strVendorId);
    i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_PRODUCT_ID, data.strProductId);
    i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_DEVICE, data.strRevision);
    i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer);
    i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_PRODUCT_STR, data.strProduct);
    i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber);
    i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_PORT, data.strPort);

    COMGETTER(Action)(&data.action);
}
RTEXITCODE handleDebugVM(HandlerArg *pArgs)
{
    RTEXITCODE rcExit = RTEXITCODE_FAILURE;

    /*
     * The first argument is the VM name or UUID.  Open a session to it.
     */
    if (pArgs->argc < 2)
        return errorNoSubcommand();
    ComPtr<IMachine> ptrMachine;
    CHECK_ERROR2I_RET(pArgs->virtualBox, FindMachine(com::Bstr(pArgs->argv[0]).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE);
    CHECK_ERROR2I_RET(ptrMachine, LockMachine(pArgs->session, LockType_Shared), RTEXITCODE_FAILURE);

    /*
     * Get the associated console and machine debugger.
     */
    HRESULT rc;
    ComPtr<IConsole> ptrConsole;
    CHECK_ERROR(pArgs->session, COMGETTER(Console)(ptrConsole.asOutParam()));
    if (SUCCEEDED(rc))
    {
        if (ptrConsole.isNotNull())
        {
            ComPtr<IMachineDebugger> ptrDebugger;
            CHECK_ERROR(ptrConsole, COMGETTER(Debugger)(ptrDebugger.asOutParam()));
            if (SUCCEEDED(rc))
            {
                /*
                 * String switch on the sub-command.
                 */
                const char *pszSubCmd = pArgs->argv[1];
                if (!strcmp(pszSubCmd, "dumpvmcore"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_DUMPVMCORE);
                    rcExit = handleDebugVM_DumpVMCore(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "getregisters"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_GETREGISTERS);
                    rcExit = handleDebugVM_GetRegisters(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "info"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_INFO);
                    rcExit = handleDebugVM_Info(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "injectnmi"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_INJECTNMI);
                    rcExit = handleDebugVM_InjectNMI(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "log"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_LOG);
                    rcExit = handleDebugVM_LogXXXX(pArgs, ptrDebugger, pszSubCmd);
                }
                else if (!strcmp(pszSubCmd, "logdest"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_LOGDEST);
                    rcExit = handleDebugVM_LogXXXX(pArgs, ptrDebugger, pszSubCmd);
                }
                else if (!strcmp(pszSubCmd, "logflags"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_LOGFLAGS);
                    rcExit = handleDebugVM_LogXXXX(pArgs, ptrDebugger, pszSubCmd);
                }
                else if (!strcmp(pszSubCmd, "osdetect"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_OSDETECT);
                    rcExit = handleDebugVM_OSDetect(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "osinfo"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_OSINFO);
                    rcExit = handleDebugVM_OSInfo(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "osdmesg"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_OSDMESG);
                    rcExit = handleDebugVM_OSDmesg(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "setregisters"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_SETREGISTERS);
                    rcExit = handleDebugVM_SetRegisters(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "show"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_SHOW);
                    rcExit = handleDebugVM_Show(pArgs, ptrDebugger);
                }
                else if (!strcmp(pszSubCmd, "statistics"))
                {
                    setCurrentSubcommand(HELP_SCOPE_DEBUGVM_STATISTICS);
                    rcExit = handleDebugVM_Statistics(pArgs, ptrDebugger);
                }
                else
                    errorUnknownSubcommand(pszSubCmd);
            }
        }
        else
            RTMsgError("Machine '%s' is not currently running.\n", pArgs->argv[0]);
    }

    pArgs->session->UnlockMachine();

    return rcExit;
}
Exemplo n.º 10
0
HRESULT Progress::waitForAsyncProgressCompletion(const ComPtr<IProgress> &aPProgressAsync)
{
    LogFlowThisFuncEnter();

    /* Note: we don't lock here, cause we just using public methods. */

    HRESULT rc           = S_OK;
    BOOL fCancelable     = FALSE;
    BOOL fCompleted      = FALSE;
    BOOL fCanceled       = FALSE;
    ULONG prevPercent    = UINT32_MAX;
    ULONG currentPercent = 0;
    ULONG cOp            = 0;
    /* Is the async process cancelable? */
    rc = aPProgressAsync->COMGETTER(Cancelable)(&fCancelable);
    if (FAILED(rc)) return rc;
    /* Loop as long as the sync process isn't completed. */
    while (SUCCEEDED(aPProgressAsync->COMGETTER(Completed(&fCompleted))))
    {
        /* We can forward any cancel request to the async process only when
         * it is cancelable. */
        if (fCancelable)
        {
            rc = COMGETTER(Canceled)(&fCanceled);
            if (FAILED(rc)) return rc;
            if (fCanceled)
            {
                rc = aPProgressAsync->Cancel();
                if (FAILED(rc)) return rc;
            }
        }
        /* Even if the user canceled the process, we have to wait until the
           async task has finished his work (cleanup and such). Otherwise there
           will be sync trouble (still wrong state, dead locks, ...) on the
           used objects. So just do nothing, but wait for the complete
           notification. */
        if (!fCanceled)
        {
            /* Check if the current operation has changed. It is also possible that
             * in the meantime more than one async operation was finished. So we
             * have to loop as long as we reached the same operation count. */
            ULONG curOp;
            for (;;)
            {
                rc = aPProgressAsync->COMGETTER(Operation(&curOp));
                if (FAILED(rc)) return rc;
                if (cOp != curOp)
                {
                    Bstr bstr;
                    ULONG currentWeight;
                    rc = aPProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));
                    if (FAILED(rc)) return rc;
                    rc = aPProgressAsync->COMGETTER(OperationWeight(&currentWeight));
                    if (FAILED(rc)) return rc;
                    rc = SetNextOperation(bstr.raw(), currentWeight);
                    if (FAILED(rc)) return rc;
                    ++cOp;
                }
                else
                    break;
            }

            rc = aPProgressAsync->COMGETTER(OperationPercent(&currentPercent));
            if (FAILED(rc)) return rc;
            if (currentPercent != prevPercent)
            {
                prevPercent = currentPercent;
                rc = SetCurrentOperationProgress(currentPercent);
                if (FAILED(rc)) return rc;
            }
        }
        if (fCompleted)
            break;

        /* Make sure the loop is not too tight */
        rc = aPProgressAsync->WaitForCompletion(100);
        if (FAILED(rc)) return rc;
    }

    LogFlowThisFuncLeave();

    return rc;
}
STDMETHODIMP GuestEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
{
    switch (aType)
    {
    case VBoxEventType_OnGuestSessionRegistered:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestSessionRegisteredEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestSession> pSession;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
            AssertBreak(!pSession.isNull());
            BOOL fRegistered;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
            Bstr strName;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));
            ULONG uID;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));

            RTPrintf("Session ID=%RU32 \"%s\" %s\n",
                     uID, Utf8Str(strName).c_str(),
                     fRegistered ? "registered" : "unregistered");
            if (fRegistered)
            {
                if (mfVerbose)
                    RTPrintf("Registering ...\n");

                /* Register for IGuestSession events. */
                ComObjPtr<GuestSessionEventListenerImpl> pListener;
                pListener.createObject();
                CHECK_ERROR_BREAK(pListener, init(new GuestSessionEventListener()));

                ComPtr<IEventSource> es;
                CHECK_ERROR_BREAK(pSession, COMGETTER(EventSource)(es.asOutParam()));
                com::SafeArray<VBoxEventType_T> eventTypes;
                eventTypes.push_back(VBoxEventType_OnGuestFileRegistered);
                eventTypes.push_back(VBoxEventType_OnGuestProcessRegistered);
                CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
                                                       true /* Active listener */));

                GuestSessionStats sessionStats(pListener);
                mSessions[pSession] = sessionStats;
            }
            else
            {
                GuestEventSessions::iterator itSession = mSessions.find(pSession);
                if (itSession != mSessions.end())
                {
                    if (mfVerbose)
                        RTPrintf("Unregistering ...\n");

                    if (!itSession->first.isNull())
                    {
                        /* Listener unregistration. */
                        ComPtr<IEventSource> pES;
                        CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam()));
                        if (!pES.isNull())
                            CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener));
                        itSession->first->Release();
                    }

                    mSessions.erase(itSession);
                }
            }

        } while (0);
        break;
    }

    default:
        AssertFailed();
    }

    return S_OK;
}
STDMETHODIMP GuestSessionEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
{
    switch (aType)
    {
    case VBoxEventType_OnGuestFileRegistered:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestFileRegisteredEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestFile> pFile;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pFile.asOutParam()));
            AssertBreak(!pFile.isNull());
            BOOL fRegistered;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
            Bstr strPath;
            CHECK_ERROR_BREAK(pFile, COMGETTER(FileName)(strPath.asOutParam()));

            RTPrintf("File \"%s\" %s\n",
                     Utf8Str(strPath).c_str(),
                     fRegistered ? "registered" : "unregistered");
            if (fRegistered)
            {
                if (mfVerbose)
                    RTPrintf("Registering ...\n");

                /* Register for IGuestFile events. */
                ComObjPtr<GuestFileEventListenerImpl> pListener;
                pListener.createObject();
                CHECK_ERROR_BREAK(pListener, init(new GuestFileEventListener()));

                ComPtr<IEventSource> es;
                CHECK_ERROR_BREAK(pFile, COMGETTER(EventSource)(es.asOutParam()));
                com::SafeArray<VBoxEventType_T> eventTypes;
                eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
                CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
                                                       true /* Active listener */));

                GuestFileStats fileStats(pListener);
                mFiles[pFile] = fileStats;
            }
            else
            {
                GuestEventFiles::iterator itFile = mFiles.find(pFile);
                if (itFile != mFiles.end())
                {
                    if (mfVerbose)
                        RTPrintf("Unregistering file ...\n");

                    if (!itFile->first.isNull())
                    {
                        /* Listener unregistration. */
                        ComPtr<IEventSource> pES;
                        CHECK_ERROR(itFile->first, COMGETTER(EventSource)(pES.asOutParam()));
                        if (!pES.isNull())
                            CHECK_ERROR(pES, UnregisterListener(itFile->second.mListener));
                        itFile->first->Release();
                    }

                    mFiles.erase(itFile);
                }
            }

        } while (0);
        break;
    }

    case VBoxEventType_OnGuestProcessRegistered:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestProcessRegisteredEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());

            ComPtr<IGuestProcess> pProcess;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam()));
            AssertBreak(!pProcess.isNull());
            BOOL fRegistered;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
            Bstr strPath;
            CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam()));

            RTPrintf("Process \"%s\" %s\n",
                     Utf8Str(strPath).c_str(),
                     fRegistered ? "registered" : "unregistered");
            if (fRegistered)
            {
                if (mfVerbose)
                    RTPrintf("Registering ...\n");

                /* Register for IGuestProcess events. */
                ComObjPtr<GuestProcessEventListenerImpl> pListener;
                pListener.createObject();
                CHECK_ERROR_BREAK(pListener, init(new GuestProcessEventListener()));

                ComPtr<IEventSource> es;
                CHECK_ERROR_BREAK(pProcess, COMGETTER(EventSource)(es.asOutParam()));
                com::SafeArray<VBoxEventType_T> eventTypes;
                eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
                CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
                                                       true /* Active listener */));

                GuestProcStats procStats(pListener);
                mProcs[pProcess] = procStats;
            }
            else
            {
                GuestEventProcs::iterator itProc = mProcs.find(pProcess);
                if (itProc != mProcs.end())
                {
                    if (mfVerbose)
                        RTPrintf("Unregistering process ...\n");

                    if (!itProc->first.isNull())
                    {
                        /* Listener unregistration. */
                        ComPtr<IEventSource> pES;
                        CHECK_ERROR(itProc->first, COMGETTER(EventSource)(pES.asOutParam()));
                        if (!pES.isNull())
                            CHECK_ERROR(pES, UnregisterListener(itProc->second.mListener));
                        itProc->first->Release();
                    }

                    mProcs.erase(itProc);
                }
            }

        } while (0);
        break;
    }

    case VBoxEventType_OnGuestSessionStateChanged:
    {
        HRESULT rc;
        do
        {
            ComPtr<IGuestSessionStateChangedEvent> pEvent = aEvent;
            Assert(!pEvent.isNull());
            ComPtr<IGuestSession> pSession;
            CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
            AssertBreak(!pSession.isNull());

            GuestSessionStatus_T sessSts;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Status)(&sessSts));
            ULONG uID;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));
            Bstr strName;
            CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));

            RTPrintf("Session ID=%RU32 \"%s\" changed status to [%s]\n",
                     uID, Utf8Str(strName).c_str(), gctlGuestSessionStatusToText(sessSts));

        } while (0);
        break;
    }

    default:
        AssertFailed();
    }

    return S_OK;
}
$NetBSD$

--- src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp.orig	2015-03-02 10:09:37.000000000 -0500
+++ src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	2015-03-12 18:33:09.348465000 -0400
@@ -1732,7 +1732,7 @@
                 CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam()));
 
                 uint32_t aliasMode = 0;
-                if (!RTStrCmp(ValueUnion.psz, "default") == 0)
+                if (RTStrCmp(ValueUnion.psz, "default") != 0)
                 {
                     char *token = (char *)ValueUnion.psz;
                     while(token)
STDMETHODIMP VirtualBoxErrorInfo::GetSource (BSTR *source)
{
    return COMGETTER(Component) (source);
}
STDMETHODIMP VirtualBoxErrorInfo::GetDescription (BSTR *description)
{
    return COMGETTER(Text) (description);
}