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.

437 lines
12 KiB

  1. #include <fusenetincludes.h>
  2. #include <msxml2.h>
  3. #include <sxsid.h>
  4. #include <assemblyidentity.h>
  5. #include <shlwapi.h>
  6. // ---------------------------------------------------------------------------
  7. // CreateAssemblyIdentity
  8. // ---------------------------------------------------------------------------
  9. STDAPI
  10. CreateAssemblyIdentity(
  11. LPASSEMBLY_IDENTITY *ppAssemblyId,
  12. DWORD dwFlags)
  13. {
  14. HRESULT hr = S_OK;
  15. CAssemblyIdentity *pAssemblyId = NULL;
  16. pAssemblyId = new(CAssemblyIdentity);
  17. if (!pAssemblyId)
  18. {
  19. hr = E_OUTOFMEMORY;
  20. goto exit;
  21. }
  22. hr = pAssemblyId->Init();
  23. if (FAILED(hr))
  24. {
  25. SAFERELEASE(pAssemblyId);
  26. goto exit;
  27. }
  28. exit:
  29. *ppAssemblyId = pAssemblyId;
  30. return hr;
  31. }
  32. STDAPI
  33. CreateAssemblyIdentityEx(
  34. LPASSEMBLY_IDENTITY *ppAssemblyId,
  35. DWORD dwFlags,
  36. LPWSTR wzDisplayName)
  37. {
  38. HRESULT hr = S_OK;
  39. CAssemblyIdentity *pAssemblyId = NULL;
  40. pAssemblyId = new(CAssemblyIdentity);
  41. if (!pAssemblyId)
  42. {
  43. hr = E_OUTOFMEMORY;
  44. goto exit;
  45. }
  46. hr = pAssemblyId->Init();
  47. if (FAILED(hr))
  48. {
  49. SAFERELEASE(pAssemblyId);
  50. goto exit;
  51. }
  52. if (wzDisplayName)
  53. {
  54. LPWSTR pwzStart, pwzEnd;
  55. CString Temp[4];
  56. CString sDirName;
  57. int i=0;
  58. sDirName.Assign(wzDisplayName);
  59. pwzStart = sDirName._pwz;
  60. pwzEnd = sDirName._pwz;
  61. while (pwzEnd = StrChr(pwzEnd, L'_'))
  62. {
  63. *pwzEnd = L'\0';
  64. Temp[i++].Assign(pwzStart);
  65. pwzStart = ++pwzEnd;
  66. }
  67. pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE,
  68. (LPCOLESTR)pwzStart, lstrlen(pwzStart) + 1);
  69. pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION,
  70. (LPCOLESTR)Temp[3]._pwz, lstrlen(Temp[3]._pwz) + 1);
  71. pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN,
  72. (LPCOLESTR)Temp[2]._pwz, lstrlen(Temp[2]._pwz) + 1);
  73. pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  74. (LPCOLESTR)Temp[1]._pwz, lstrlen(Temp[1]._pwz) + 1);
  75. pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE,
  76. (LPCOLESTR)Temp[0]._pwz, lstrlen(Temp[0]._pwz) + 1);
  77. }
  78. exit:
  79. *ppAssemblyId = pAssemblyId;
  80. return hr;
  81. }
  82. // ---------------------------------------------------------------------------
  83. // CloneAssemblyIdentity
  84. // ---------------------------------------------------------------------------
  85. STDAPI
  86. CloneAssemblyIdentity(
  87. LPASSEMBLY_IDENTITY pSrcAssemblyId,
  88. LPASSEMBLY_IDENTITY *ppDestAssemblyId)
  89. {
  90. HRESULT hr = S_OK;
  91. CAssemblyIdentity *pAssemblyId = NULL;
  92. if (pSrcAssemblyId == NULL || ppDestAssemblyId == NULL)
  93. {
  94. hr = E_INVALIDARG;
  95. goto exit;
  96. }
  97. *ppDestAssemblyId = NULL;
  98. if (FAILED(hr = CreateAssemblyIdentity((LPASSEMBLY_IDENTITY*) &pAssemblyId, 0)))
  99. goto exit;
  100. if (!SxsDuplicateAssemblyIdentity(0, (static_cast<CAssemblyIdentity*> (pSrcAssemblyId))->_pId,
  101. &(pAssemblyId->_pId)))
  102. {
  103. DWORD dw = ::GetLastError();
  104. hr = HRESULT_FROM_WIN32(dw);
  105. goto exit;
  106. }
  107. *ppDestAssemblyId = pAssemblyId;
  108. exit:
  109. return hr;
  110. }
  111. // ---------------------------------------------------------------------------
  112. // ctor
  113. // ---------------------------------------------------------------------------
  114. CAssemblyIdentity::CAssemblyIdentity()
  115. : _dwSig('TNDI'), _cRef(1), _hr(S_OK), _pId(NULL)
  116. {
  117. }
  118. // ---------------------------------------------------------------------------
  119. // dtor
  120. // ---------------------------------------------------------------------------
  121. CAssemblyIdentity::~CAssemblyIdentity()
  122. {
  123. SxsDestroyAssemblyIdentity(_pId);
  124. }
  125. // ---------------------------------------------------------------------------
  126. // Init
  127. // ---------------------------------------------------------------------------
  128. HRESULT CAssemblyIdentity::Init()
  129. {
  130. if (!SxsCreateAssemblyIdentity(0, ASSEMBLY_IDENTITY_TYPE_DEFINITION, &_pId, 0, NULL))
  131. {
  132. DWORD dw = ::GetLastError();
  133. _hr = HRESULT_FROM_WIN32(dw);
  134. }
  135. else
  136. _hr = S_OK;
  137. return _hr;
  138. }
  139. // ---------------------------------------------------------------------------
  140. // SetAttribute
  141. // ---------------------------------------------------------------------------
  142. HRESULT CAssemblyIdentity::SetAttribute(LPCOLESTR pwzName,
  143. LPCOLESTR pwzValue, DWORD ccValue)
  144. {
  145. DWORD ccName = lstrlen(pwzName);
  146. SXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttrRef;
  147. AttrRef.Namespace = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE;
  148. AttrRef.NamespaceCch = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE_CCH;
  149. AttrRef.Name = pwzName;
  150. AttrRef.NameCch = ccName;
  151. // BUGBUG: should allow overwrite or not?
  152. if (!SxspSetAssemblyIdentityAttributeValue(
  153. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  154. _pId, &AttrRef, pwzValue, ccValue))
  155. {
  156. DWORD dw = ::GetLastError();
  157. _hr = HRESULT_FROM_WIN32(dw);
  158. }
  159. else
  160. _hr = S_OK;
  161. return _hr;
  162. }
  163. // ---------------------------------------------------------------------------
  164. // GetAttribute
  165. // ---------------------------------------------------------------------------
  166. HRESULT CAssemblyIdentity::GetAttribute(LPCOLESTR pwzName,
  167. LPOLESTR *ppwzValue, LPDWORD pccValue)
  168. {
  169. LPWSTR pwzValue = NULL;
  170. PCWSTR pwzStringOut = NULL;
  171. DWORD ccStringOut = 0;
  172. DWORD ccName = lstrlen(pwzName);
  173. SXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttrRef;
  174. AttrRef.Namespace = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE;
  175. AttrRef.NamespaceCch = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE_CCH;
  176. AttrRef.Name = pwzName;
  177. AttrRef.NameCch = ccName;
  178. if (!SxspGetAssemblyIdentityAttributeValue(0, _pId, &AttrRef, &pwzStringOut, &ccStringOut))
  179. {
  180. DWORD dw = ::GetLastError();
  181. _hr = HRESULT_FROM_WIN32(dw);
  182. goto exit;
  183. }
  184. pwzValue = WSTRDupDynamic(pwzStringOut);
  185. if (!pwzValue)
  186. {
  187. _hr = E_OUTOFMEMORY;
  188. goto exit;
  189. }
  190. _hr = S_OK;
  191. *ppwzValue = pwzValue;
  192. *pccValue = ccStringOut;
  193. exit:
  194. return _hr;
  195. }
  196. // ---------------------------------------------------------------------------
  197. // IsEqual
  198. // ---------------------------------------------------------------------------
  199. HRESULT CAssemblyIdentity::IsEqual (IAssemblyIdentity *pAssemblyId)
  200. {
  201. LPWSTR pwzBuf;
  202. DWORD ccBuf;
  203. CString sLang1, sVersion1, sToken1, sName1, sArch1;
  204. CString sLang2, sVersion2, sToken2, sName2, sArch2;
  205. // Compare architectures
  206. if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE, &pwzBuf, &ccBuf))))
  207. goto exit;
  208. sArch1.TakeOwnership(pwzBuf, ccBuf);
  209. if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE, &pwzBuf, &ccBuf))))
  210. goto exit;
  211. sArch2.TakeOwnership(pwzBuf, ccBuf);
  212. if (StrCmp (sArch1._pwz, sArch2._pwz))
  213. {
  214. _hr = S_FALSE;
  215. goto exit;
  216. }
  217. // Compare names
  218. if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf))))
  219. goto exit;
  220. sName1.TakeOwnership(pwzBuf, ccBuf);
  221. if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf))))
  222. goto exit;
  223. sName2.TakeOwnership(pwzBuf, ccBuf);
  224. if (StrCmp (sName1._pwz, sName2._pwz))
  225. {
  226. _hr = S_FALSE;
  227. goto exit;
  228. }
  229. // Compare Public Key Tokens
  230. if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf))))
  231. goto exit;
  232. sToken1.TakeOwnership(pwzBuf, ccBuf);
  233. if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf))))
  234. goto exit;
  235. sToken2.TakeOwnership(pwzBuf, ccBuf);
  236. if (StrCmp (sToken1._pwz, sToken2._pwz))
  237. {
  238. _hr = S_FALSE;
  239. goto exit;
  240. }
  241. // Compare Versions
  242. if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION, &pwzBuf, &ccBuf))))
  243. goto exit;
  244. sVersion1.TakeOwnership(pwzBuf, ccBuf);
  245. if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION, &pwzBuf, &ccBuf))))
  246. goto exit;
  247. sVersion2.TakeOwnership(pwzBuf, ccBuf);
  248. if (StrCmp (sVersion1._pwz, sVersion2._pwz))
  249. {
  250. _hr = S_FALSE;
  251. goto exit;
  252. }
  253. // Compare Languages
  254. if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzBuf, &ccBuf))))
  255. goto exit;
  256. sLang1.TakeOwnership(pwzBuf, ccBuf);
  257. if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzBuf, &ccBuf))))
  258. goto exit;
  259. sLang2.TakeOwnership(pwzBuf, ccBuf);
  260. if (StrCmp (sLang1._pwz, sLang2._pwz))
  261. {
  262. _hr = S_FALSE;
  263. goto exit;
  264. }
  265. _hr = S_OK;
  266. exit:
  267. return _hr;
  268. }
  269. #define WZ_WILDCARDSTRING L"*"
  270. // ---------------------------------------------------------------------------
  271. // GetDisplayName
  272. // ---------------------------------------------------------------------------
  273. HRESULT CAssemblyIdentity::GetDisplayName(DWORD dwFlags, LPOLESTR *ppwzDisplayName, LPDWORD pccDisplayName)
  274. {
  275. LPWSTR rpwzAttrNames[5] =
  276. {
  277. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE,
  278. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  279. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN,
  280. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION,
  281. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE,
  282. };
  283. LPWSTR pwzBuf = NULL;
  284. DWORD ccBuf = 0;
  285. CString sDisplayName;
  286. for (int i = 0; i < 5; i++)
  287. {
  288. CString sBuffer;
  289. if (FAILED(_hr = GetAttribute(rpwzAttrNames[i], &pwzBuf, &ccBuf))
  290. && _hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
  291. goto exit;
  292. // append anyway to keep the number of underscore constant
  293. if (i)
  294. sDisplayName.Append(L"_");
  295. if (dwFlags == ASMID_DISPLAYNAME_WILDCARDED
  296. && _hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
  297. {
  298. sDisplayName.Append(WZ_WILDCARDSTRING);
  299. _hr = S_OK;
  300. }
  301. else if (_hr == S_OK)
  302. {
  303. sBuffer.TakeOwnership(pwzBuf, ccBuf);
  304. sDisplayName.Append(sBuffer);
  305. }
  306. }
  307. *ppwzDisplayName = sDisplayName._pwz;
  308. *pccDisplayName = sDisplayName._cc;
  309. sDisplayName.ReleaseOwnership();
  310. exit:
  311. return _hr;
  312. }
  313. // IUnknown Boilerplate
  314. // ---------------------------------------------------------------------------
  315. // CAssemblyIdentity::QI
  316. // ---------------------------------------------------------------------------
  317. STDMETHODIMP
  318. CAssemblyIdentity::QueryInterface(REFIID riid, void** ppvObj)
  319. {
  320. if ( IsEqualIID(riid, IID_IUnknown)
  321. || IsEqualIID(riid, IID_IAssemblyIdentity)
  322. )
  323. {
  324. *ppvObj = static_cast<IAssemblyIdentity*> (this);
  325. AddRef();
  326. return S_OK;
  327. }
  328. else
  329. {
  330. *ppvObj = NULL;
  331. return E_NOINTERFACE;
  332. }
  333. }
  334. // ---------------------------------------------------------------------------
  335. // CAssemblyIdentity::AddRef
  336. // ---------------------------------------------------------------------------
  337. STDMETHODIMP_(ULONG)
  338. CAssemblyIdentity::AddRef()
  339. {
  340. return InterlockedIncrement ((LONG*) &_cRef);
  341. }
  342. // ---------------------------------------------------------------------------
  343. // CAssemblyIdentity::Release
  344. // ---------------------------------------------------------------------------
  345. STDMETHODIMP_(ULONG)
  346. CAssemblyIdentity::Release()
  347. {
  348. ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
  349. if (!lRet)
  350. delete this;
  351. return lRet;
  352. }