in src/vswhere.lib/VersionRange.cpp [192:262]
HRESULT VersionRange::ParseVersionString(
_In_ const LPCWSTR pwszVersionBegin,
_In_ const LPCWSTR pwszVersionEnd,
_Out_ PULONGLONG pullVersion
)
{
_ASSERT(pwszVersionBegin);
_ASSERT(pwszVersionEnd);
_ASSERT(pullVersion);
HRESULT hr = S_OK;
LPWSTR pwszFieldBegin = const_cast<LPWSTR>(pwszVersionBegin);
LPWSTR pwszFieldEnd = const_cast<LPWSTR>(pwszVersionBegin);
WORD cFields = 0;
ULONG ulField = 0;
ULONGLONG ullVersion = 0;
*pullVersion = 0;
for (;;)
{
if (4 <= cFields)
{
ExitOnFailure(hr = E_INVALIDARG, "Too many version fields.");
}
while (pwszFieldEnd < pwszVersionEnd && L'.' != *pwszFieldEnd)
{
if (isspace(*pwszFieldEnd, neutral_locale))
{
ExitOnFailure(hr = E_INVALIDARG, "Space in version field.");
}
++pwszFieldEnd;
}
if (pwszFieldBegin == pwszFieldEnd)
{
ExitOnFailure(hr = E_INVALIDARG, "Empty version field.");
}
LPWSTR pwszEnd = NULL;
ulField = ::wcstoul(pwszFieldBegin, &pwszEnd, 10);
if (USHRT_MAX < ulField)
{
ExitOnFailure(hr = E_INVALIDARG, "Version field too large.");
}
else if (0 == ulField && pwszEnd != pwszFieldEnd)
{
ExitOnFailure(hr = E_INVALIDARG, "NaN");
}
pwszFieldEnd = pwszEnd;
ullVersion |= (ULONGLONG)ulField << ((3 - cFields) * 16);
++cFields;
if (pwszFieldEnd >= pwszVersionEnd)
{
break;
}
pwszFieldBegin = ++pwszFieldEnd;
}
*pullVersion = ullVersion;
Exit:
return hr;
}