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.

304 lines
9.4 KiB

  1. #include <fusenetincludes.h>
  2. #include <assemblycacheenum.h>
  3. #include <assemblycache.h>
  4. #include "macros.h"
  5. // ---------------------------------------------------------------------------
  6. // CreateAssemblyCacheEnum
  7. // ---------------------------------------------------------------------------
  8. STDAPI
  9. CreateAssemblyCacheEnum(
  10. LPASSEMBLY_CACHE_ENUM *ppAssemblyCacheEnum,
  11. LPASSEMBLY_IDENTITY pAssemblyIdentity,
  12. DWORD dwFlags)
  13. {
  14. HRESULT hr = S_OK;
  15. MAKE_ERROR_MACROS_STATIC(hr);
  16. CAssemblyCacheEnum *pCacheEnum = NULL;
  17. // dwFlags is checked later in Init()
  18. IF_FALSE_EXIT((ppAssemblyCacheEnum != NULL && pAssemblyIdentity != NULL), E_INVALIDARG);
  19. *ppAssemblyCacheEnum = NULL;
  20. pCacheEnum = new(CAssemblyCacheEnum);
  21. IF_ALLOC_FAILED_EXIT(pCacheEnum);
  22. hr = pCacheEnum->Init(pAssemblyIdentity, dwFlags);
  23. if (FAILED(hr) || hr == S_FALSE)
  24. {
  25. SAFERELEASE(pCacheEnum);
  26. goto exit;
  27. }
  28. *ppAssemblyCacheEnum = static_cast<IAssemblyCacheEnum*> (pCacheEnum);
  29. exit:
  30. return hr;
  31. }
  32. // ---------------------------------------------------------------------------
  33. // ctor
  34. // ---------------------------------------------------------------------------
  35. CCacheEntry::CCacheEntry()
  36. : _dwSig('tnec'), _hr(S_OK), _pwzDisplayName(NULL), _pAsmCache(NULL)
  37. {}
  38. // ---------------------------------------------------------------------------
  39. // dtor
  40. // ---------------------------------------------------------------------------
  41. CCacheEntry::~CCacheEntry()
  42. {
  43. SAFEDELETEARRAY(_pwzDisplayName);
  44. SAFERELEASE(_pAsmCache);
  45. }
  46. // ---------------------------------------------------------------------------
  47. // CCacheEntry::GetAsmCache
  48. // ---------------------------------------------------------------------------
  49. IAssemblyCacheImport* CCacheEntry::GetAsmCache()
  50. {
  51. LPASSEMBLY_IDENTITY pAsmId = NULL;
  52. IAssemblyCacheImport* pAsmCache = NULL;
  53. IF_NULL_EXIT(_pwzDisplayName, E_UNEXPECTED); // if _pwzDisplayName == NULL : it is wrong
  54. if (_pAsmCache == NULL)
  55. {
  56. IF_FAILED_EXIT(CreateAssemblyIdentityEx(&pAsmId, 0, _pwzDisplayName));
  57. IF_FAILED_EXIT(CreateAssemblyCacheImport(&_pAsmCache, pAsmId, CACHEIMP_CREATE_RETRIEVE));
  58. }
  59. pAsmCache = _pAsmCache;
  60. // it's possible that CreateAssemblyCacheImport returns S_FALSE and set _pAsmCache == NULL
  61. if (pAsmCache)
  62. pAsmCache->AddRef();
  63. exit:
  64. SAFERELEASE(pAsmId);
  65. return pAsmCache;
  66. }
  67. // ---------------------------------------------------------------------------
  68. // ctor
  69. // ---------------------------------------------------------------------------
  70. CAssemblyCacheEnum::CAssemblyCacheEnum()
  71. : _dwSig('mnec'), _cRef(1), _hr(S_OK),_current(NULL)
  72. {}
  73. // ---------------------------------------------------------------------------
  74. // dtor
  75. // ---------------------------------------------------------------------------
  76. CAssemblyCacheEnum::~CAssemblyCacheEnum()
  77. {
  78. // Free all the list cache entries
  79. CCacheEntry* pEntry = NULL;
  80. LISTNODE pos = _listCacheEntry.GetHeadPosition();
  81. while (pos && (pEntry = _listCacheEntry.GetNext(pos)))
  82. delete pEntry;
  83. // Free all the list nodes - this is done in list's dtor
  84. //_listCacheEntry.RemoveAll();
  85. }
  86. // NOTENOTE: because of the lazy init of the list of cache import, app dirs/files can be deleted by the time cacheenum gets to them
  87. // ---------------------------------------------------------------------------
  88. // CAssemblyCacheEnum::Init
  89. // return: S_OK - found at least a version
  90. // S_FALSE - not found any version
  91. // E_*
  92. // ---------------------------------------------------------------------------
  93. HRESULT CAssemblyCacheEnum::Init(LPASSEMBLY_IDENTITY pAsmId, DWORD dwFlag)
  94. {
  95. HANDLE hFind = INVALID_HANDLE_VALUE;
  96. WIN32_FIND_DATA fdAppDir;
  97. DWORD dwLastError = ERROR_SUCCESS;
  98. BOOL fFound = FALSE;
  99. LPWSTR pwzSearchDisplayName = NULL;
  100. DWORD dwCC = 0;
  101. CString sDisplayName;
  102. CString sSearchPath;
  103. CAssemblyCache *pAssemblyCache = NULL;
  104. CCacheEntry* pEntry = NULL;
  105. // BUGBUG: enable searching for all different cache status with dwFlag
  106. IF_FALSE_EXIT((dwFlag == CACHEENUM_RETRIEVE_ALL || dwFlag == CACHEENUM_RETRIEVE_VISIBLE), E_INVALIDARG);
  107. IF_FAILED_EXIT(pAsmId->GetDisplayName(ASMID_DISPLAYNAME_WILDCARDED, &pwzSearchDisplayName, &dwCC));
  108. sDisplayName.TakeOwnership(pwzSearchDisplayName, dwCC);
  109. // notenote: possibly modify assemblycache so that _sRootDir and IsStatus() can be use without creating an instance
  110. pAssemblyCache = new(CAssemblyCache);
  111. IF_ALLOC_FAILED_EXIT(pAssemblyCache);
  112. IF_FAILED_EXIT(pAssemblyCache->Init(NULL, ASSEMBLY_CACHE_TYPE_APP | ASSEMBLY_CACHE_TYPE_IMPORT));
  113. IF_FAILED_EXIT(sSearchPath.Assign(pAssemblyCache->_sRootDir));
  114. IF_FAILED_EXIT(sSearchPath.Append(sDisplayName));
  115. hFind = FindFirstFileEx(sSearchPath._pwz, FindExInfoStandard, &fdAppDir, FindExSearchLimitToDirectories, NULL, 0);
  116. IF_TRUE_EXIT(hFind == INVALID_HANDLE_VALUE, S_FALSE);
  117. while (dwLastError != ERROR_NO_MORE_FILES)
  118. {
  119. // ???? check file attribute to see if it's a directory? needed only if the file system does not support the filter...
  120. if (dwFlag == CACHEENUM_RETRIEVE_ALL ||
  121. (dwFlag == CACHEENUM_RETRIEVE_VISIBLE && CAssemblyCache::IsStatus(fdAppDir.cFileName, CAssemblyCache::VISIBLE)))
  122. {
  123. fFound = TRUE;
  124. IF_FAILED_EXIT(sDisplayName.Assign(fdAppDir.cFileName));
  125. pEntry = new(CCacheEntry);
  126. IF_ALLOC_FAILED_EXIT(pEntry);
  127. // store a copy of the displayname
  128. sDisplayName.ReleaseOwnership(&(pEntry->_pwzDisplayName));
  129. // add cache entry to the list
  130. _listCacheEntry.AddHead(pEntry); // AddSorted() instead?
  131. pEntry = NULL;
  132. }
  133. if (!FindNextFile(hFind, &fdAppDir))
  134. {
  135. dwLastError = GetLastError();
  136. continue;
  137. }
  138. }
  139. // BUGBUG: propagate the error if findnext fails != ERROR_NO_MORE_FILES
  140. if (fFound)
  141. {
  142. _current = _listCacheEntry.GetHeadPosition();
  143. _hr = S_OK;
  144. }
  145. else
  146. _hr = S_FALSE;
  147. exit:
  148. if (hFind != INVALID_HANDLE_VALUE)
  149. {
  150. if (!FindClose(hFind))
  151. {
  152. // can return 0, even when there's an error.
  153. DWORD dw = GetLastError();
  154. _hr = dw ? HRESULT_FROM_WIN32(dw) : E_FAIL;
  155. }
  156. }
  157. SAFERELEASE(pAssemblyCache);
  158. return _hr;
  159. }
  160. // ---------------------------------------------------------------------------
  161. // CAssemblyCacheEnum::GetNext
  162. // ---------------------------------------------------------------------------
  163. HRESULT CAssemblyCacheEnum::GetNext(IAssemblyCacheImport** ppAsmCache)
  164. {
  165. CCacheEntry* pEntry = NULL;
  166. IF_NULL_EXIT(ppAsmCache, E_INVALIDARG);
  167. *ppAsmCache = NULL;
  168. IF_TRUE_EXIT(_current == NULL, S_FALSE); // S_FALSE == no more
  169. if (pEntry = _listCacheEntry.GetNext(_current))
  170. {
  171. // note: this can return NULL
  172. // *ppAsmCache is AddRef-ed
  173. *ppAsmCache = pEntry->GetAsmCache();
  174. }
  175. else
  176. // this is wrong
  177. _hr = E_UNEXPECTED;
  178. exit:
  179. return _hr;
  180. }
  181. // ---------------------------------------------------------------------------
  182. // CAssemblyCacheEnum::Reset
  183. // ---------------------------------------------------------------------------
  184. HRESULT CAssemblyCacheEnum::Reset()
  185. {
  186. _current = _listCacheEntry.GetHeadPosition();
  187. return S_OK;
  188. }
  189. // ---------------------------------------------------------------------------
  190. // CAssemblyCacheEnum::GetCount
  191. // ---------------------------------------------------------------------------
  192. HRESULT CAssemblyCacheEnum::GetCount(LPDWORD pdwCount)
  193. {
  194. if (pdwCount == NULL)
  195. _hr = E_INVALIDARG;
  196. else
  197. {
  198. // BUGBUG: platform-dependent: DWORD converting from int, check overflow
  199. *pdwCount = (DWORD) _listCacheEntry.GetCount();
  200. _hr = S_OK;
  201. }
  202. return _hr;
  203. }
  204. // IUnknown methods
  205. // ---------------------------------------------------------------------------
  206. // CAssemblyCacheEnum::QI
  207. // ---------------------------------------------------------------------------
  208. STDMETHODIMP
  209. CAssemblyCacheEnum::QueryInterface(REFIID riid, void** ppvObj)
  210. {
  211. if ( IsEqualIID(riid, IID_IUnknown)
  212. || IsEqualIID(riid, IID_IAssemblyCacheEnum)
  213. )
  214. {
  215. *ppvObj = static_cast<IAssemblyCacheEnum*> (this);
  216. AddRef();
  217. return S_OK;
  218. }
  219. else
  220. {
  221. *ppvObj = NULL;
  222. return E_NOINTERFACE;
  223. }
  224. }
  225. // ---------------------------------------------------------------------------
  226. // CAssemblyCacheEnum::AddRef
  227. // ---------------------------------------------------------------------------
  228. STDMETHODIMP_(ULONG)
  229. CAssemblyCacheEnum::AddRef()
  230. {
  231. return InterlockedIncrement ((LONG*) &_cRef);
  232. }
  233. // ---------------------------------------------------------------------------
  234. // CAssemblyCacheEnum::Release
  235. // ---------------------------------------------------------------------------
  236. STDMETHODIMP_(ULONG)
  237. CAssemblyCacheEnum::Release()
  238. {
  239. ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
  240. if (!lRet)
  241. delete this;
  242. return lRet;
  243. }