Leaked source code of windows server 2003
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.

306 lines
7.8 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation
  3. */
  4. #include "stdinc.h"
  5. #include "fusionparser.h"
  6. #include "policystatement.h"
  7. #include "sxsid.h"
  8. BOOL
  9. CPolicyStatementRedirect::Initialize(
  10. const CBaseStringBuffer &rbuffFromVersionRange,
  11. const CBaseStringBuffer &rbuffToVersion,
  12. bool &rfValid
  13. )
  14. {
  15. FN_PROLOG_WIN32
  16. PCWSTR pszDash;
  17. CStringBuffer buffTemp;
  18. ASSEMBLY_VERSION avFromMin = { 0 };
  19. ASSEMBLY_VERSION avFromMax = { 0 };
  20. ASSEMBLY_VERSION avTo = { 0 };
  21. bool fValid;
  22. rfValid = false;
  23. // let's see if we have a singleton or a range...
  24. pszDash = ::wcschr(rbuffFromVersionRange, L'-');
  25. if (pszDash == NULL)
  26. {
  27. // It must be a singleton. Parse it.
  28. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMin, rbuffFromVersionRange, rbuffFromVersionRange.Cch(), fValid));
  29. if (fValid)
  30. avFromMax = avFromMin;
  31. }
  32. else
  33. {
  34. SIZE_T cchFirstSegment = static_cast<SIZE_T>(pszDash - rbuffFromVersionRange);
  35. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMin, rbuffFromVersionRange, cchFirstSegment, fValid));
  36. if (fValid)
  37. {
  38. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMax, pszDash + 1, rbuffFromVersionRange.Cch() - (cchFirstSegment + 1), fValid));
  39. if (avFromMin > avFromMax)
  40. fValid = false;
  41. }
  42. }
  43. if (fValid)
  44. IFW32FALSE_EXIT(CFusionParser::ParseVersion(avTo, rbuffToVersion, rbuffToVersion.Cch(), fValid));
  45. if (fValid)
  46. {
  47. // Everything parsed OK. We keep the binary/numeric form of the from range so that we can do
  48. // fast comparisons, but we keep the string of the to version because assembly identity attributes
  49. // are stored as strings.
  50. IFW32FALSE_EXIT(m_NewVersion.Win32Assign(rbuffToVersion));
  51. m_avFromMin = avFromMin;
  52. m_avFromMax = avFromMax;
  53. rfValid = true;
  54. }
  55. #if DBG
  56. if (rfValid)
  57. {
  58. FusionpDbgPrintEx(FUSION_DBG_LEVEL_BINDING,
  59. "SXS: %s New redirection found: %d.%d.%d.%d-%d.%d.%d.%d to %ls\n",
  60. __FUNCTION__,
  61. m_avFromMin.Major, m_avFromMin.Minor, m_avFromMin.Revision, m_avFromMin.Build,
  62. m_avFromMax.Major, m_avFromMax.Minor, m_avFromMax.Revision, m_avFromMax.Build,
  63. static_cast<PCWSTR>(m_NewVersion));
  64. }
  65. else
  66. {
  67. FusionpDbgPrintEx(FUSION_DBG_LEVEL_BINDING,
  68. "SXS: %s Rejecting redirection strings '%ls' -> '%ls'\n",
  69. static_cast<PCWSTR>(rbuffFromVersionRange),
  70. static_cast<PCWSTR>(rbuffToVersion));
  71. }
  72. #endif
  73. FN_EPILOG
  74. }
  75. BOOL
  76. CPolicyStatementRedirect::TryMap(
  77. const ASSEMBLY_VERSION &rav,
  78. CBaseStringBuffer &TargetVersion,
  79. bool &rfMapped
  80. )
  81. {
  82. FN_PROLOG_WIN32
  83. rfMapped = false;
  84. if ((rav >= m_avFromMin) &&
  85. (rav <= m_avFromMax))
  86. {
  87. IFW32FALSE_EXIT(TargetVersion.Win32Assign(m_NewVersion));
  88. rfMapped = true;
  89. }
  90. FN_EPILOG
  91. }
  92. BOOL
  93. CPolicyStatementRedirect::CheckForOverlap(
  94. const CPolicyStatementRedirect &rRedirect,
  95. bool &rfOverlaps
  96. )
  97. {
  98. FN_PROLOG_WIN32
  99. rfOverlaps = false;
  100. // we can assume that the other redirect is well formed (min <= max)
  101. if (((rRedirect.m_avFromMax >= m_avFromMin) &&
  102. (rRedirect.m_avFromMax <= m_avFromMax)) ||
  103. ((rRedirect.m_avFromMin <= m_avFromMax) &&
  104. (rRedirect.m_avFromMin >= m_avFromMin)))
  105. {
  106. rfOverlaps = true;
  107. }
  108. FN_EPILOG
  109. }
  110. //
  111. // Implementation of CPolicyStatement
  112. //
  113. BOOL
  114. CPolicyStatement::Initialize()
  115. {
  116. return TRUE;
  117. }
  118. BOOL
  119. CPolicyStatement::AddRedirect(
  120. const CBaseStringBuffer &rbuffFromVersion,
  121. const CBaseStringBuffer &rbuffToVersion,
  122. bool &rfValid
  123. )
  124. {
  125. BOOL fSuccess = FALSE;
  126. FN_TRACE_WIN32(fSuccess);
  127. CPolicyStatementRedirect *Redirect = NULL;
  128. CDequeIterator<CPolicyStatementRedirect, FIELD_OFFSET(CPolicyStatementRedirect, m_leLinks)> iter;
  129. bool fOverlaps;
  130. bool fValid = false;
  131. rfValid = false;
  132. // NTRAID#NTBUG9 - 591010 - 2002/03/30 - mgrier - switch to using smart pointer
  133. IFALLOCFAILED_EXIT(Redirect = new CPolicyStatementRedirect);
  134. IFW32FALSE_EXIT(Redirect->Initialize(rbuffFromVersion, rbuffToVersion, fValid));
  135. if (fValid)
  136. {
  137. iter.Rebind(&m_Redirects);
  138. for (iter.Reset(); iter.More(); iter.Next())
  139. {
  140. IFW32FALSE_EXIT(iter->CheckForOverlap(*Redirect, fOverlaps));
  141. if (fOverlaps)
  142. {
  143. fValid = false;
  144. break;
  145. }
  146. }
  147. iter.Unbind();
  148. }
  149. if (fValid)
  150. {
  151. // Looks good; add it!
  152. m_Redirects.AddToTail(Redirect);
  153. Redirect = NULL;
  154. rfValid = true;
  155. }
  156. // NTRAID#NTBUG9 - 591010 - 2002/03/30 - mgrier - Once Redirect is a smart pointer, switch
  157. // the function epilog to FN_EPILOG
  158. fSuccess = TRUE;
  159. Exit:
  160. if (Redirect != NULL)
  161. FUSION_DELETE_SINGLETON(Redirect);
  162. return fSuccess;
  163. }
  164. BOOL
  165. CPolicyStatement::ApplyPolicy(
  166. PASSEMBLY_IDENTITY AssemblyIdentity,
  167. bool &rfPolicyApplied
  168. )
  169. {
  170. FN_PROLOG_WIN32
  171. PCWSTR Version = NULL;
  172. SIZE_T VersionCch = 0;
  173. CSmallStringBuffer VersionBuffer;
  174. SIZE_T cchWritten = 0;
  175. CDequeIterator<CPolicyStatementRedirect, FIELD_OFFSET(CPolicyStatementRedirect, m_leLinks)> iter;
  176. ASSEMBLY_VERSION av;
  177. bool fSyntaxValid;
  178. bool fMapped = false;
  179. #if DBG
  180. PCWSTR Name = NULL;
  181. SIZE_T NameCch = 0;
  182. #endif
  183. rfPolicyApplied = false;
  184. PARAMETER_CHECK(AssemblyIdentity != NULL);
  185. IFW32FALSE_EXIT(
  186. ::SxspGetAssemblyIdentityAttributeValue(
  187. 0,
  188. AssemblyIdentity,
  189. &s_IdentityAttribute_version,
  190. &Version,
  191. &VersionCch));
  192. #if DBG
  193. IFW32FALSE_EXIT(
  194. ::SxspGetAssemblyIdentityAttributeValue(
  195. 0,
  196. AssemblyIdentity,
  197. &s_IdentityAttribute_name,
  198. &Name,
  199. &NameCch));
  200. #endif
  201. IFW32FALSE_EXIT(CFusionParser::ParseVersion(av, Version, VersionCch, fSyntaxValid));
  202. // An invalid version number should have been caught earlier.
  203. INTERNAL_ERROR_CHECK(fSyntaxValid);
  204. iter.Rebind(&m_Redirects);
  205. for (iter.Reset(); iter.More(); iter.Next())
  206. {
  207. IFW32FALSE_EXIT(iter->TryMap(av, VersionBuffer, fMapped));
  208. if (fMapped)
  209. {
  210. FusionpDbgPrintEx(
  211. FUSION_DBG_LEVEL_BINDING,
  212. "SXS: %s Intermediate redirection : %d.%d.%d.%d to %ls\n",
  213. __FUNCTION__,
  214. av.Major, av.Minor, av.Revision, av.Build,
  215. static_cast<PCWSTR>(VersionBuffer));
  216. break;
  217. }
  218. }
  219. if (fMapped)
  220. {
  221. #if DBG
  222. FusionpDbgPrintEx(
  223. FUSION_DBG_LEVEL_BINDING,
  224. "SXS: %s Final version redirection for %.*ls was from '%.*ls' to '%ls'\n",
  225. __FUNCTION__,
  226. NameCch, Name,
  227. VersionCch, Version,
  228. static_cast<PCWSTR>(VersionBuffer));
  229. #endif
  230. IFW32FALSE_EXIT(
  231. ::SxspSetAssemblyIdentityAttributeValue(
  232. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  233. AssemblyIdentity,
  234. &s_IdentityAttribute_version,
  235. VersionBuffer,
  236. VersionBuffer.Cch()));
  237. rfPolicyApplied = true;
  238. }
  239. #if DBG
  240. else
  241. {
  242. FusionpDbgPrintEx(
  243. FUSION_DBG_LEVEL_BINDING,
  244. "SXS: %s No redirections for '%.*ls' found\n",
  245. __FUNCTION__,
  246. NameCch, Name);
  247. }
  248. #endif
  249. FN_EPILOG
  250. }