STDMETHODIMP Guest::COMGETTER(AdditionsRevision)(ULONG *a_puAdditionsRevision) { CheckComArgOutPointerValid(a_puAdditionsRevision); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); /* * Return the ReportGuestInfo2 version info if available. */ if ( !mData.mAdditionsVersionNew.isEmpty() || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None) *a_puAdditionsRevision = mData.mAdditionsRevision; else { /* * If we're running older guest additions (< 3.2.0) try get it from * the guest properties. Detected switched around Version and * Revision in early 3.1.x releases (see r57115). */ ComPtr<IMachine> ptrMachine = mParent->machine(); alock.release(); /* No need to hold this during the IPC fun. */ Bstr bstr; hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Revision").raw(), bstr.asOutParam()); if (SUCCEEDED(hrc)) { Utf8Str str(bstr); uint32_t uRevision; int vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision); if (vrc != VINF_SUCCESS && str.count('.') == 2) { hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Version").raw(), bstr.asOutParam()); if (SUCCEEDED(hrc)) { str = bstr; vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision); } } if (vrc == VINF_SUCCESS) *a_puAdditionsRevision = uRevision; else hrc = VBOX_E_IPRT_ERROR; } if (FAILED(hrc)) { /* Return 0 if we don't know. */ *a_puAdditionsRevision = 0; hrc = S_OK; } } } return hrc; }
RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion) { /* * Reset the variables kept in state. */ pState->pDef = NULL; pState->uIndex = UINT32_MAX; /* * Make sure the union is completely cleared out, whatever happens below. */ pValueUnion->u64 = 0; pValueUnion->pDef = NULL; /* * The next option. */ bool fShort; int iThis; const char *pszArgThis; PCRTGETOPTDEF pOpt; if (pState->pszNextShort) { /* * We've got short options left over from the previous call. */ pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions, pState->fFlags); if (!pOpt) { pValueUnion->psz = pState->pszNextShort; return VERR_GETOPT_UNKNOWN_OPTION; } pState->pszNextShort++; pszArgThis = pState->pszNextShort - 2; iThis = pState->iNext; fShort = true; } else { /* * Pop off the next argument. Sorting options and dealing with the * dash-dash makes this a little extra complicated. */ for (;;) { if (pState->iNext >= pState->argc) return 0; if (pState->cNonOptions) { if (pState->cNonOptions == INT32_MAX) { pValueUnion->psz = pState->argv[pState->iNext++]; return VINF_GETOPT_NOT_OPTION; } if (pState->iNext + pState->cNonOptions >= pState->argc) { pState->cNonOptions = INT32_MAX; continue; } } iThis = pState->iNext++; pszArgThis = pState->argv[iThis + pState->cNonOptions]; /* * Do a long option search first and then a short option one. * This way we can make sure single dash long options doesn't * get mixed up with short ones. */ pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions, pState->fFlags); if ( !pOpt && pszArgThis[0] == '-' && pszArgThis[1] != '-' && pszArgThis[1] != '\0') { pOpt = rtGetOptSearchShort(pszArgThis[1], pState->paOptions, pState->cOptions, pState->fFlags); fShort = pOpt != NULL; } else fShort = false; /* Look for dash-dash. */ if (!pOpt && !strcmp(pszArgThis, "--")) { rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]); pState->cNonOptions = INT32_MAX; continue; } /* Options first hacks. */ if (pState->fFlags & RTGETOPTINIT_FLAGS_OPTS_FIRST) { if (pOpt) rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]); else if (*pszArgThis == '-') { pValueUnion->psz = pszArgThis; return VERR_GETOPT_UNKNOWN_OPTION; } else { /* not an option, add it to the non-options and try again. */ pState->iNext--; pState->cNonOptions++; /* Switch to returning non-options if we've reached the end. */ if (pState->iNext + pState->cNonOptions >= pState->argc) pState->cNonOptions = INT32_MAX; continue; } } /* done */ break; } } if (pOpt) { pValueUnion->pDef = pOpt; /* in case of no value or error. */ if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING) { /* * Find the argument value. * * A value is required with the argument. We're trying to be * understanding here and will permit any of the following: * -svalue, -s value, -s:value and -s=value * (Ditto for long options.) */ const char *pszValue; if (fShort) { if (pszArgThis[2] == '\0') { if (iThis + 1 >= pState->argc) return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; pszValue = pState->argv[iThis + pState->cNonOptions + 1]; rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); pState->iNext++; } else /* same argument. */ pszValue = &pszArgThis[2 + (pszArgThis[2] == ':' || pszArgThis[2] == '=')]; if (pState->pszNextShort) { pState->pszNextShort = NULL; pState->iNext++; } } else { size_t cchLong = strlen(pOpt->pszLong); if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) { if (pszArgThis[cchLong] == '\0') return VERR_GETOPT_INDEX_MISSING; uint32_t uIndex; char *pszRet = NULL; int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex); if (rc == VWRN_TRAILING_CHARS) { if ( pszRet[0] != ':' && pszRet[0] != '=') return VERR_GETOPT_INVALID_ARGUMENT_FORMAT; pState->uIndex = uIndex; pszValue = pszRet + 1; } else if (rc == VINF_SUCCESS) { if (iThis + 1 >= pState->argc) return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; pState->uIndex = uIndex; pszValue = pState->argv[iThis + pState->cNonOptions + 1]; rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); pState->iNext++; } else AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */ } else { if (pszArgThis[cchLong] == '\0') { if (iThis + 1 >= pState->argc) return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING; pszValue = pState->argv[iThis + pState->cNonOptions + 1]; rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]); pState->iNext++; } else /* same argument. */ pszValue = &pszArgThis[cchLong + 1]; } } /* * Set up the ValueUnion. */ int rc = rtGetOptProcessValue(pOpt->fFlags, pszValue, pValueUnion); if (RT_FAILURE(rc)) return rc; } else if (fShort) { /* * Deal with "compressed" short option lists, correcting the next * state variables for the start and end cases. */ if (pszArgThis[2]) { if (!pState->pszNextShort) { /* start */ pState->pszNextShort = &pszArgThis[2]; pState->iNext--; } } else if (pState->pszNextShort) { /* end */ pState->pszNextShort = NULL; pState->iNext++; } } else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX) { size_t cchLong = strlen(pOpt->pszLong); if (pszArgThis[cchLong] == '\0') return VERR_GETOPT_INDEX_MISSING; uint32_t uIndex; if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS) pState->uIndex = uIndex; else AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */ } pState->pDef = pOpt; return pOpt->iShort; } /* * Not a known option argument. If it starts with a switch char (-) we'll * fail with unknown option, and if it doesn't we'll return it as a non-option. */ if (*pszArgThis == '-') { pValueUnion->psz = pszArgThis; return VERR_GETOPT_UNKNOWN_OPTION; } pValueUnion->psz = pszArgThis; return VINF_GETOPT_NOT_OPTION; }