windows-nt/Source/XPSP1/NT/base/win32/fusion/sxs/partialassemblyversion.cpp
2020-09-26 16:20:57 +08:00

234 lines
5.1 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
partialassemblyversion.cpp
Abstract:
Class describing a partial/wildcarded assembly version.
Author:
Michael J. Grier (MGrier) 13-May-2000
Revision History:
--*/
#include "stdinc.h"
#include <windows.h>
#include "sxsp.h"
#include "partialassemblyversion.h"
BOOL
CPartialAssemblyVersion::Parse(
PCWSTR sz,
SIZE_T Cch
)
{
BOOL fSuccess = FALSE;
ULONG cDots = 0;
PCWSTR pszTemp;
SIZE_T CchLeft;
USHORT usTemp;
ASSEMBLY_VERSION avTemp;
PCWSTR pszLast;
BOOL MajorSpecified = FALSE;
BOOL MinorSpecified = FALSE;
BOOL BuildSpecified = FALSE;
BOOL RevisionSpecified = FALSE;
// Somehow people often leave trailing nulls; we'll just back off Cch in this case.
while ((Cch != 0) && (sz[Cch - 1] == L'\0'))
Cch--;
avTemp.Major = 0;
avTemp.Minor = 0;
avTemp.Revision = 0;
avTemp.Build = 0;
// "*" means everything unspecified...
if ((Cch == 1) && (sz[0] == L'*'))
{
m_MajorSpecified = FALSE;
m_MinorSpecified = FALSE;
m_BuildSpecified = FALSE;
m_RevisionSpecified = FALSE;
fSuccess = TRUE;
goto Exit;
}
pszTemp = sz;
CchLeft = Cch;
while (CchLeft-- != 0)
{
WCHAR wch = *pszTemp++;
if (wch == L'.')
{
cDots++;
if (cDots >= 4)
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
}
else if ((wch != L'*') && ((wch < L'0') || (wch > L'9')))
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
}
if (cDots < 3)
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
pszTemp = sz;
pszLast = sz + Cch;
usTemp = 0;
for (;;)
{
WCHAR wch = *pszTemp++;
if (wch == L'*')
{
// If there's been a previous digit, we can't then have a * (there's no matching version number "5*")
if (MajorSpecified)
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
if (*pszTemp != L'.')
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
break;
}
if (wch == L'.')
break;
usTemp = (usTemp * 10) + (wch - L'0');
MajorSpecified = TRUE;
}
avTemp.Major = usTemp;
usTemp = 0;
for (;;)
{
WCHAR wch = *pszTemp++;
if (wch == L'*')
{
// If there's been a previous digit, we can't then have a * (there's no matching version number "5*")
if (MinorSpecified)
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
if (*pszTemp != L'.')
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
break;
}
if (wch == L'.')
break;
usTemp = (usTemp * 10) + (wch - L'0');
MinorSpecified = TRUE;
}
avTemp.Minor = usTemp;
usTemp = 0;
for (;;)
{
WCHAR wch = *pszTemp++;
if (wch == L'*')
{
// If there's been a previous digit, we can't then have a * (there's no matching version number "5*")
if (RevisionSpecified)
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
if (*pszTemp != L'.')
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
break;
}
if (wch == L'.')
break;
usTemp = (usTemp * 10) + (wch - L'0');
RevisionSpecified = TRUE;
}
avTemp.Revision = usTemp;
// Now the tricky bit. We aren't necessarily null-terminated, so we
// have to just look for hitting the end.
usTemp = 0;
while (pszTemp < pszLast)
{
WCHAR wch = *pszTemp++;
if (wch == L'*')
{
// If there's been a previous digit, we can't then have a * (there's no matching version number "5*")
if (MajorSpecified)
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
// If that wasn't the last character, it was wrong.
if (pszTemp < pszLast)
{
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
goto Exit;
}
break;
}
usTemp = (usTemp * 10) + (wch - L'0');
BuildSpecified = TRUE;
}
avTemp.Build = usTemp;
m_AssemblyVersion = avTemp;
m_MajorSpecified = MajorSpecified;
m_MinorSpecified = MinorSpecified;
m_RevisionSpecified = RevisionSpecified;
m_BuildSpecified = BuildSpecified;
fSuccess = TRUE;
Exit:
return fSuccess;
}