Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

261 lines
6.2 KiB

  1. #include "stdinc.h"
  2. #include "fusionparser.h"
  3. #include "policystatement.h"
  4. #include "sxsid.h"
  5. BOOL
  6. CPolicyStatementRedirect::Initialize(
  7. const CBaseStringBuffer &rbuffFromVersionRange,
  8. const CBaseStringBuffer &rbuffToVersion,
  9. bool &rfValid
  10. )
  11. {
  12. BOOL fSuccess = FALSE;
  13. FN_TRACE_WIN32(fSuccess);
  14. PCWSTR pszDash;
  15. CStringBuffer buffTemp;
  16. ASSEMBLY_VERSION avFromMin = { 0 };
  17. ASSEMBLY_VERSION avFromMax = { 0 };
  18. ASSEMBLY_VERSION avTo = { 0 };
  19. bool fValid;
  20. rfValid = false;
  21. INTERNAL_ERROR_CHECK(rbuffToVersion.Cch() < NUMBER_OF(m_rgwchNewVersion));
  22. // let's see if we have a singleton or a range...
  23. pszDash = wcschr(rbuffFromVersionRange, L'-');
  24. if (pszDash == NULL)
  25. {
  26. // It must be a singleton. Parse it.
  27. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMin, rbuffFromVersionRange, rbuffFromVersionRange.Cch(), fValid));
  28. if (fValid)
  29. avFromMax = avFromMin;
  30. }
  31. else
  32. {
  33. SIZE_T cchFirstSegment = static_cast<SIZE_T>(pszDash - rbuffFromVersionRange);
  34. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMin, rbuffFromVersionRange, cchFirstSegment, fValid));
  35. if (fValid)
  36. {
  37. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMax, pszDash + 1, rbuffFromVersionRange.Cch() - (cchFirstSegment + 1), fValid));
  38. if (avFromMin > avFromMax)
  39. fValid = false;
  40. }
  41. }
  42. if (fValid)
  43. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avTo, rbuffToVersion, rbuffToVersion.Cch(), fValid));
  44. if (fValid)
  45. {
  46. // Everything parsed OK. We keep the binary/numeric form of the from range so that we can do
  47. // fast comparisons, but we keep the string of the to version because assembly identity attributes
  48. // are stored as strings.
  49. m_cchNewVersion = rbuffToVersion.Cch();
  50. memcpy(m_rgwchNewVersion, static_cast<PCWSTR>(rbuffToVersion), (rbuffToVersion.Cch() + 1) * sizeof(WCHAR));
  51. m_avFromMin = avFromMin;
  52. m_avFromMax = avFromMax;
  53. rfValid = true;
  54. }
  55. fSuccess = TRUE;
  56. Exit:
  57. return fSuccess;
  58. }
  59. BOOL
  60. CPolicyStatementRedirect::TryMap(
  61. const ASSEMBLY_VERSION &rav,
  62. SIZE_T cchBuffer,
  63. PWSTR pBuffer,
  64. SIZE_T &rcchWritten,
  65. bool &rfMapped
  66. )
  67. {
  68. BOOL fSuccess = FALSE;
  69. FN_TRACE_WIN32(fSuccess);
  70. rfMapped = false;
  71. rcchWritten = 0;
  72. if ((rav >= m_avFromMin) &&
  73. (rav <= m_avFromMax))
  74. {
  75. if ((m_cchNewVersion + 1) > cchBuffer)
  76. ORIGINATE_WIN32_FAILURE_AND_EXIT(BufferTooSmall, ERROR_INSUFFICIENT_BUFFER);
  77. memcpy(pBuffer, m_rgwchNewVersion, (m_cchNewVersion + 1) * sizeof(WCHAR));
  78. rcchWritten = m_cchNewVersion;
  79. rfMapped = true;
  80. }
  81. fSuccess = TRUE;
  82. Exit:
  83. return fSuccess;
  84. }
  85. BOOL
  86. CPolicyStatementRedirect::CheckForOverlap(
  87. const CPolicyStatementRedirect &rRedirect,
  88. bool &rfOverlaps
  89. )
  90. {
  91. BOOL fSuccess = FALSE;
  92. FN_TRACE_WIN32(fSuccess);
  93. rfOverlaps = false;
  94. // we can assume that the other redirect is well formed (min <= max)
  95. if (((rRedirect.m_avFromMax >= m_avFromMin) &&
  96. (rRedirect.m_avFromMax <= m_avFromMax)) ||
  97. ((rRedirect.m_avFromMin <= m_avFromMax) &&
  98. (rRedirect.m_avFromMin >= m_avFromMin)))
  99. {
  100. rfOverlaps = true;
  101. }
  102. fSuccess = TRUE;
  103. // Exit:
  104. return fSuccess;
  105. }
  106. //
  107. // Implementation of CPolicyStatement
  108. //
  109. BOOL
  110. CPolicyStatement::Initialize()
  111. {
  112. return TRUE;
  113. }
  114. BOOL
  115. CPolicyStatement::AddRedirect(
  116. const CBaseStringBuffer &rbuffFromVersion,
  117. const CBaseStringBuffer &rbuffToVersion,
  118. bool &rfValid
  119. )
  120. {
  121. BOOL fSuccess = FALSE;
  122. FN_TRACE_WIN32(fSuccess);
  123. CPolicyStatementRedirect *Redirect = NULL;
  124. CDequeIterator<CPolicyStatementRedirect, FIELD_OFFSET(CPolicyStatementRedirect, m_leLinks)> iter;
  125. bool fOverlaps;
  126. bool fValid = false;
  127. rfValid = false;
  128. IFALLOCFAILED_EXIT(Redirect = new CPolicyStatementRedirect);
  129. IFW32FALSE_EXIT(Redirect->Initialize(rbuffFromVersion, rbuffToVersion, fValid));
  130. if (fValid)
  131. {
  132. iter.Rebind(&m_Redirects);
  133. for (iter.Reset(); iter.More(); iter.Next())
  134. {
  135. IFW32FALSE_EXIT(iter->CheckForOverlap(*Redirect, fOverlaps));
  136. if (fOverlaps)
  137. {
  138. fValid = false;
  139. break;
  140. }
  141. }
  142. iter.Unbind();
  143. }
  144. if (fValid)
  145. {
  146. // Looks good; add it!
  147. m_Redirects.AddToTail(Redirect);
  148. Redirect = NULL;
  149. rfValid = true;
  150. }
  151. fSuccess = TRUE;
  152. Exit:
  153. if (Redirect != NULL)
  154. FUSION_DELETE_SINGLETON(Redirect);
  155. return fSuccess;
  156. }
  157. BOOL
  158. CPolicyStatement::ApplyPolicy(
  159. PASSEMBLY_IDENTITY AssemblyIdentity,
  160. bool &rfPolicyApplied
  161. )
  162. {
  163. BOOL fSuccess = FALSE;
  164. FN_TRACE_WIN32(fSuccess);
  165. PCWSTR Version = NULL;
  166. SIZE_T VersionCch = 0;
  167. WCHAR rgwchVersionBuffer[(4 * 5) + (3 * 1) + 1];
  168. SIZE_T cchWritten = 0;
  169. CDequeIterator<CPolicyStatementRedirect, FIELD_OFFSET(CPolicyStatementRedirect, m_leLinks)> iter;
  170. ASSEMBLY_VERSION av;
  171. bool fSyntaxValid;
  172. bool fMapped = false;
  173. rfPolicyApplied = false;
  174. PARAMETER_CHECK(AssemblyIdentity != NULL);
  175. IFW32FALSE_EXIT(
  176. ::SxspGetAssemblyIdentityAttributeValue(
  177. 0,
  178. AssemblyIdentity,
  179. &s_IdentityAttribute_version,
  180. &Version,
  181. &VersionCch));
  182. IFW32FALSE_EXIT(CFusionParser::ParseVersion(av, Version, VersionCch, fSyntaxValid));
  183. // An invalid version number should have been caught earlier.
  184. INTERNAL_ERROR_CHECK(fSyntaxValid);
  185. iter.Rebind(&m_Redirects);
  186. for (iter.Reset(); iter.More(); iter.Next())
  187. {
  188. IFW32FALSE_EXIT(iter->TryMap(av, NUMBER_OF(rgwchVersionBuffer), rgwchVersionBuffer, cchWritten, fMapped));
  189. if (fMapped)
  190. break;
  191. }
  192. if (fMapped)
  193. {
  194. IFW32FALSE_EXIT(
  195. ::SxspSetAssemblyIdentityAttributeValue(
  196. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  197. AssemblyIdentity,
  198. &s_IdentityAttribute_version,
  199. rgwchVersionBuffer,
  200. cchWritten));
  201. rfPolicyApplied = true;
  202. }
  203. fSuccess = TRUE;
  204. Exit:
  205. return fSuccess;
  206. }