/*++ 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 #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; }