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.

447 lines
14 KiB

  1. #include "stdinc.h"
  2. #include <setupapi.h>
  3. #include <sxsapi.h>
  4. #include <stdlib.h>
  5. #include <search.h>
  6. #include "idp.h"
  7. #include "sxsapi.h"
  8. #include "sxsapi.h"
  9. #include "sxsid.h"
  10. ASSEMBLY_IDENTITY_ATTRIBUTE
  11. SxsComposeAssemblyIdentityAttribute(
  12. PCWSTR pszNamespace, SIZE_T cchNamespace,
  13. PCWSTR pszName, SIZE_T cchName,
  14. PCWSTR pszValue, SIZE_T cchValue)
  15. {
  16. ASSEMBLY_IDENTITY_ATTRIBUTE anattribute;
  17. anattribute.Flags = 0; // reserved flags : must be 0;
  18. anattribute.NamespaceCch = cchNamespace;
  19. anattribute.NameCch = cchName;
  20. anattribute.ValueCch = cchValue;
  21. anattribute.Namespace = pszNamespace;
  22. anattribute.Name = pszName;
  23. anattribute.Value = pszValue;
  24. return anattribute;
  25. }
  26. BOOL
  27. SxsAssemblyIdentityIsAttributePresent(
  28. PCASSEMBLY_IDENTITY pAssemblyIdentity,
  29. PCWSTR pszNamespace,
  30. SIZE_T cchNamespace,
  31. PCWSTR pszName,
  32. SIZE_T cchName,
  33. BOOL & rfFound)
  34. {
  35. BOOL fSuccess = FALSE;
  36. FN_TRACE_WIN32(fSuccess);
  37. ULONG Count = 0;
  38. ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
  39. DWORD dwFindFlags;
  40. PARAMETER_CHECK(pszName != NULL);
  41. rfFound = FALSE;
  42. if ( pAssemblyIdentity == NULL)
  43. {
  44. goto Done;
  45. }
  46. // in the case of a NULL namespace, we must set the flag, too ? xiaoyuw@09/11/00
  47. dwFindFlags = SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE | SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME;
  48. Attribute = SxsComposeAssemblyIdentityAttribute(pszNamespace, cchNamespace, pszName, cchName, NULL, 0);
  49. if (pAssemblyIdentity){
  50. IFW32FALSE_EXIT(
  51. ::SxsFindAssemblyIdentityAttribute( // find attribute by "namespace" and "name"
  52. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
  53. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME |
  54. SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS,
  55. pAssemblyIdentity,
  56. &Attribute,
  57. NULL,
  58. &Count));
  59. if ( Count >0 ) { // found
  60. rfFound = TRUE;
  61. }
  62. }
  63. Done:
  64. fSuccess = TRUE;
  65. Exit:
  66. return fSuccess;
  67. }
  68. BOOL
  69. SxspSetAssemblyIdentityAttributeValue(
  70. DWORD Flags,
  71. PASSEMBLY_IDENTITY AssemblyIdentity,
  72. PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
  73. const WCHAR *Value,
  74. SIZE_T ValueCch
  75. )
  76. {
  77. BOOL fSuccess = FALSE;
  78. FN_TRACE_WIN32(fSuccess);
  79. ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
  80. DWORD FlagsToRealInsert = 0;
  81. PARAMETER_CHECK((Flags & ~(SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING)) == 0);
  82. PARAMETER_CHECK(AssemblyIdentity != NULL);
  83. PARAMETER_CHECK(AttributeReference != NULL);
  84. PARAMETER_CHECK(Value != NULL || ValueCch == 0);
  85. Attribute.Flags = 0;
  86. Attribute.Namespace = AttributeReference->Namespace;
  87. Attribute.NamespaceCch = AttributeReference->NamespaceCch;
  88. Attribute.Name = AttributeReference->Name;
  89. Attribute.NameCch = AttributeReference->NameCch;
  90. Attribute.Value = Value;
  91. Attribute.ValueCch = ValueCch;
  92. if (Flags & SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING)
  93. FlagsToRealInsert |= SXS_INSERT_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_OVERWRITE_EXISTING;
  94. IFW32FALSE_EXIT(::SxsInsertAssemblyIdentityAttribute(FlagsToRealInsert, AssemblyIdentity, &Attribute));
  95. fSuccess = TRUE;
  96. Exit:
  97. return fSuccess;
  98. }
  99. BOOL
  100. SxspSetAssemblyIdentityAttributeValue(
  101. DWORD Flags,
  102. PASSEMBLY_IDENTITY AssemblyIdentity,
  103. PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
  104. const CBaseStringBuffer &Value
  105. )
  106. {
  107. BOOL fSuccess = FALSE;
  108. FN_TRACE_WIN32(fSuccess);
  109. IFW32FALSE_EXIT(
  110. ::SxspSetAssemblyIdentityAttributeValue(
  111. Flags,
  112. AssemblyIdentity,
  113. AttributeReference,
  114. static_cast<PCWSTR>(Value),
  115. Value.Cch()));
  116. fSuccess = TRUE;
  117. Exit:
  118. return fSuccess;
  119. }
  120. /////////////////////////////////////////////////////////////////////////////
  121. // Action :
  122. // 1. if (namespace, name) is provided, remove all attributes with such (namespace, name)
  123. // 2. if (namespace, name, value), remove at most 1 attribute from assembly-identity
  124. ///////////////////////////////////////////////////////////////////////////////
  125. BOOL
  126. SxspRemoveAssemblyIdentityAttribute(
  127. DWORD Flags,
  128. PASSEMBLY_IDENTITY pAssemblyIdentity,
  129. PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference
  130. )
  131. {
  132. BOOL fSuccess = FALSE;
  133. FN_TRACE_WIN32(fSuccess);
  134. ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
  135. ULONG Ordinal;
  136. ULONG Count;
  137. DWORD dwFindAttributeFlags = 0;
  138. PARAMETER_CHECK((Flags & ~(SXSP_REMOVE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS)) == 0);
  139. PARAMETER_CHECK(pAssemblyIdentity != NULL);
  140. PARAMETER_CHECK(AttributeReference != NULL);
  141. Attribute.Flags = 0;
  142. Attribute.Namespace = AttributeReference->Namespace;
  143. Attribute.NamespaceCch = AttributeReference->NamespaceCch;
  144. Attribute.Name = AttributeReference->Name;
  145. Attribute.NameCch = AttributeReference->NameCch;
  146. dwFindAttributeFlags = SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE | SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME;
  147. // If it's OK for the attribute not to exist, set the flag in the call to find it.
  148. if (Flags & SXSP_REMOVE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS)
  149. dwFindAttributeFlags |= SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS;
  150. IFW32FALSE_EXIT(
  151. ::SxsFindAssemblyIdentityAttribute(
  152. dwFindAttributeFlags,
  153. pAssemblyIdentity,
  154. &Attribute,
  155. &Ordinal,
  156. &Count));
  157. INTERNAL_ERROR_CHECK(Count <= 1);
  158. if (Count > 0)
  159. {
  160. IFW32FALSE_EXIT(
  161. ::SxsRemoveAssemblyIdentityAttributesByOrdinal(
  162. 0, // DWORD Flags,
  163. pAssemblyIdentity,
  164. Ordinal,
  165. Count));
  166. }
  167. fSuccess = TRUE;
  168. Exit:
  169. return fSuccess;
  170. }
  171. /////////////////////////////////////////////////////////////////////////////
  172. // if no such attribure with such (namespace and name), return FALSE with
  173. // ::SetLastError(ERROR_NOT_FOUND);
  174. ///////////////////////////////////////////////////////////////////////////////
  175. BOOL
  176. SxspGetAssemblyIdentityAttributeValue(
  177. DWORD Flags,
  178. PCASSEMBLY_IDENTITY AssemblyIdentity,
  179. PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
  180. OUT PCWSTR *StringOut,
  181. OUT SIZE_T *CchOut OPTIONAL
  182. )
  183. {
  184. BOOL fSuccess = FALSE;
  185. FN_TRACE_WIN32(fSuccess);
  186. PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = NULL;
  187. ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
  188. DWORD dwLocateFlags = SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE | SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME;
  189. if (StringOut != NULL)
  190. *StringOut = NULL;
  191. if (CchOut != NULL)
  192. *CchOut = 0;
  193. PARAMETER_CHECK((Flags & ~(SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL)) == 0);
  194. PARAMETER_CHECK(AssemblyIdentity != NULL);
  195. PARAMETER_CHECK(AttributeReference != NULL);
  196. Attribute.Flags = 0;
  197. Attribute.Namespace = AttributeReference->Namespace;
  198. Attribute.NamespaceCch = AttributeReference->NamespaceCch;
  199. Attribute.Name = AttributeReference->Name;
  200. Attribute.NameCch = AttributeReference->NameCch;
  201. if (Flags & SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL)
  202. dwLocateFlags |= SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_RETURNS_NULL;
  203. IFW32FALSE_EXIT(
  204. ::SxspLocateInternalAssemblyIdentityAttribute(
  205. dwLocateFlags,
  206. AssemblyIdentity,
  207. &Attribute,
  208. &InternalAttribute,
  209. NULL));
  210. if (InternalAttribute != NULL)
  211. {
  212. if (StringOut != NULL)
  213. *StringOut = InternalAttribute->Attribute.Value;
  214. if (CchOut != NULL)
  215. *CchOut = InternalAttribute->Attribute.ValueCch;
  216. }
  217. fSuccess = TRUE;
  218. Exit:
  219. return fSuccess;
  220. }
  221. BOOL
  222. SxspGetAssemblyIdentityAttributeValue(
  223. IN DWORD Flags,
  224. IN PCASSEMBLY_IDENTITY AssemblyIdentity,
  225. PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
  226. OUT CBaseStringBuffer &Value
  227. )
  228. {
  229. BOOL fSuccess = FALSE;
  230. FN_TRACE_WIN32(fSuccess);
  231. PCWSTR String = NULL;
  232. SIZE_T Cch = 0;
  233. IFW32FALSE_EXIT(
  234. ::SxspGetAssemblyIdentityAttributeValue(
  235. Flags,
  236. AssemblyIdentity,
  237. AttributeReference,
  238. &String,
  239. &Cch));
  240. IFW32FALSE_EXIT(Value.Win32Assign(String, Cch));
  241. fSuccess = TRUE;
  242. Exit:
  243. return fSuccess;
  244. }
  245. BOOL
  246. SxspUpdateAssemblyIdentityHash(
  247. DWORD dwFlags,
  248. PASSEMBLY_IDENTITY AssemblyIdentity
  249. )
  250. {
  251. BOOL fSuccess = FALSE;
  252. FN_TRACE_WIN32(fSuccess);
  253. PARAMETER_CHECK(dwFlags == 0);
  254. PARAMETER_CHECK(AssemblyIdentity != NULL);
  255. if (AssemblyIdentity->HashDirty)
  256. {
  257. IFW32FALSE_EXIT(::SxspHashInternalAssemblyIdentityAttributes(
  258. 0,
  259. AssemblyIdentity->AttributeCount,
  260. AssemblyIdentity->AttributePointerArray,
  261. &AssemblyIdentity->Hash));
  262. AssemblyIdentity->HashDirty = FALSE;
  263. }
  264. fSuccess = TRUE;
  265. Exit:
  266. return fSuccess;
  267. }
  268. BOOL
  269. SxspEnsureAssemblyIdentityHashIsUpToDate(
  270. DWORD dwFlags,
  271. PCASSEMBLY_IDENTITY AssemblyIdentity
  272. )
  273. {
  274. BOOL fSuccess = FALSE;
  275. FN_TRACE_WIN32(fSuccess);
  276. PARAMETER_CHECK(dwFlags == 0);
  277. PARAMETER_CHECK(AssemblyIdentity != NULL);
  278. if (AssemblyIdentity->HashDirty)
  279. IFW32FALSE_EXIT(::SxspUpdateAssemblyIdentityHash(0, const_cast<PASSEMBLY_IDENTITY>(AssemblyIdentity)));
  280. fSuccess = TRUE;
  281. Exit:
  282. return fSuccess;
  283. }
  284. BOOL
  285. SxsHashAssemblyIdentity(
  286. DWORD dwFlags,
  287. PCASSEMBLY_IDENTITY pAssemblyIdentity,
  288. ULONG * pulPseudoKey
  289. )
  290. {
  291. BOOL fSuccess = FALSE;
  292. FN_TRACE_WIN32(fSuccess);
  293. ULONG ulPseudoKey;
  294. if (pulPseudoKey)
  295. *pulPseudoKey = 0;
  296. PARAMETER_CHECK(dwFlags == 0);
  297. if (pAssemblyIdentity == NULL)
  298. ulPseudoKey = 0;
  299. else
  300. {
  301. IFW32FALSE_EXIT(::SxspEnsureAssemblyIdentityHashIsUpToDate(0, pAssemblyIdentity));
  302. ulPseudoKey = pAssemblyIdentity->Hash;
  303. }
  304. if (pulPseudoKey != NULL)
  305. *pulPseudoKey = ulPseudoKey;
  306. fSuccess = TRUE;
  307. Exit:
  308. return fSuccess;
  309. }
  310. // just to find whether Equal or Not
  311. BOOL
  312. SxsAreAssemblyIdentitiesEqual(
  313. DWORD dwFlags,
  314. PCASSEMBLY_IDENTITY pAssemblyIdentity1,
  315. PCASSEMBLY_IDENTITY pAssemblyIdentity2,
  316. BOOL *EqualOut
  317. )
  318. {
  319. BOOL fSuccess = FALSE;
  320. FN_TRACE_WIN32(fSuccess);
  321. BOOL Equal = FALSE;
  322. if (EqualOut != NULL)
  323. *EqualOut = FALSE;
  324. PARAMETER_CHECK((dwFlags & ~(SXS_ARE_ASSEMBLY_IDENTITIES_EQUAL_FLAG_ALLOW_REF_TO_MATCH_DEF)) == 0);
  325. PARAMETER_CHECK(pAssemblyIdentity1 != NULL);
  326. PARAMETER_CHECK(pAssemblyIdentity2 != NULL);
  327. PARAMETER_CHECK(EqualOut != NULL);
  328. // get hash for each assembly identity
  329. IFW32FALSE_EXIT(::SxspEnsureAssemblyIdentityHashIsUpToDate(0, pAssemblyIdentity1));
  330. IFW32FALSE_EXIT(::SxspEnsureAssemblyIdentityHashIsUpToDate(0, pAssemblyIdentity2));
  331. // compare hash value of two identity; it's a quick way to determine they're not equal.
  332. if (pAssemblyIdentity2->Hash == pAssemblyIdentity1->Hash)
  333. {
  334. // Note that two identities which differ only in their internal flags are still semantically
  335. // equal.
  336. if ((pAssemblyIdentity1->Flags == pAssemblyIdentity2->Flags) &&
  337. (pAssemblyIdentity1->Hash == pAssemblyIdentity2->Hash) &&
  338. (pAssemblyIdentity1->NamespaceCount == pAssemblyIdentity2->NamespaceCount) &&
  339. (pAssemblyIdentity1->AttributeCount == pAssemblyIdentity2->AttributeCount))
  340. {
  341. if (dwFlags & SXS_ARE_ASSEMBLY_IDENTITIES_EQUAL_FLAG_ALLOW_REF_TO_MATCH_DEF)
  342. {
  343. if (((pAssemblyIdentity1->Type == ASSEMBLY_IDENTITY_TYPE_DEFINITION) ||
  344. (pAssemblyIdentity1->Type == ASSEMBLY_IDENTITY_TYPE_REFERENCE)) &&
  345. ((pAssemblyIdentity2->Type == ASSEMBLY_IDENTITY_TYPE_DEFINITION) ||
  346. (pAssemblyIdentity2->Type == ASSEMBLY_IDENTITY_TYPE_REFERENCE)))
  347. {
  348. // They match sufficiently...
  349. Equal = TRUE;
  350. }
  351. }
  352. else
  353. Equal = (pAssemblyIdentity1->Type == pAssemblyIdentity2->Type);
  354. if (Equal)
  355. {
  356. ULONG ComparisonResult = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_INVALID;
  357. // Reset our assumption...
  358. Equal = FALSE;
  359. IFW32FALSE_EXIT(
  360. ::SxspCompareAssemblyIdentityAttributeLists(
  361. 0,
  362. pAssemblyIdentity1->AttributeCount,
  363. pAssemblyIdentity1->AttributePointerArray,
  364. pAssemblyIdentity2->AttributePointerArray,
  365. &ComparisonResult));
  366. INTERNAL_ERROR_CHECK(
  367. (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_LESS_THAN) ||
  368. (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL) ||
  369. (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_GREATER_THAN));
  370. if (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL)
  371. Equal = TRUE;
  372. }
  373. }
  374. }
  375. *EqualOut = Equal;
  376. fSuccess = TRUE;
  377. Exit:
  378. return fSuccess;
  379. }