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

#include <fusenetincludes.h>
#include <assemblycacheenum.h>
#include <assemblycache.h>
#include "macros.h"
// ---------------------------------------------------------------------------
// CreateAssemblyCacheEnum
// ---------------------------------------------------------------------------
STDAPI
CreateAssemblyCacheEnum(
LPASSEMBLY_CACHE_ENUM *ppAssemblyCacheEnum,
LPASSEMBLY_IDENTITY pAssemblyIdentity,
DWORD dwFlags)
{
HRESULT hr = S_OK;
MAKE_ERROR_MACROS_STATIC(hr);
CAssemblyCacheEnum *pCacheEnum = NULL;
// dwFlags is checked later in Init()
IF_FALSE_EXIT((ppAssemblyCacheEnum != NULL && pAssemblyIdentity != NULL), E_INVALIDARG);
*ppAssemblyCacheEnum = NULL;
pCacheEnum = new(CAssemblyCacheEnum);
IF_ALLOC_FAILED_EXIT(pCacheEnum);
hr = pCacheEnum->Init(pAssemblyIdentity, dwFlags);
if (FAILED(hr) || hr == S_FALSE)
{
SAFERELEASE(pCacheEnum);
goto exit;
}
*ppAssemblyCacheEnum = static_cast<IAssemblyCacheEnum*> (pCacheEnum);
exit:
return hr;
}
// ---------------------------------------------------------------------------
// ctor
// ---------------------------------------------------------------------------
CCacheEntry::CCacheEntry()
: _dwSig('tnec'), _hr(S_OK), _pwzDisplayName(NULL), _pAsmCache(NULL)
{}
// ---------------------------------------------------------------------------
// dtor
// ---------------------------------------------------------------------------
CCacheEntry::~CCacheEntry()
{
SAFEDELETEARRAY(_pwzDisplayName);
SAFERELEASE(_pAsmCache);
}
// ---------------------------------------------------------------------------
// CCacheEntry::GetAsmCache
// ---------------------------------------------------------------------------
IAssemblyCacheImport* CCacheEntry::GetAsmCache()
{
LPASSEMBLY_IDENTITY pAsmId = NULL;
IAssemblyCacheImport* pAsmCache = NULL;
IF_NULL_EXIT(_pwzDisplayName, E_UNEXPECTED); // if _pwzDisplayName == NULL : it is wrong
if (_pAsmCache == NULL)
{
IF_FAILED_EXIT(CreateAssemblyIdentityEx(&pAsmId, 0, _pwzDisplayName));
IF_FAILED_EXIT(CreateAssemblyCacheImport(&_pAsmCache, pAsmId, CACHEIMP_CREATE_RETRIEVE));
}
pAsmCache = _pAsmCache;
// it's possible that CreateAssemblyCacheImport returns S_FALSE and set _pAsmCache == NULL
if (pAsmCache)
pAsmCache->AddRef();
exit:
SAFERELEASE(pAsmId);
return pAsmCache;
}
// ---------------------------------------------------------------------------
// ctor
// ---------------------------------------------------------------------------
CAssemblyCacheEnum::CAssemblyCacheEnum()
: _dwSig('mnec'), _cRef(1), _hr(S_OK),_current(NULL)
{}
// ---------------------------------------------------------------------------
// dtor
// ---------------------------------------------------------------------------
CAssemblyCacheEnum::~CAssemblyCacheEnum()
{
// Free all the list cache entries
CCacheEntry* pEntry = NULL;
LISTNODE pos = _listCacheEntry.GetHeadPosition();
while (pos && (pEntry = _listCacheEntry.GetNext(pos)))
delete pEntry;
// Free all the list nodes - this is done in list's dtor
//_listCacheEntry.RemoveAll();
}
// 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
// ---------------------------------------------------------------------------
// CAssemblyCacheEnum::Init
// return: S_OK - found at least a version
// S_FALSE - not found any version
// E_*
// ---------------------------------------------------------------------------
HRESULT CAssemblyCacheEnum::Init(LPASSEMBLY_IDENTITY pAsmId, DWORD dwFlag)
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA fdAppDir;
DWORD dwLastError = ERROR_SUCCESS;
BOOL fFound = FALSE;
LPWSTR pwzSearchDisplayName = NULL;
DWORD dwCC = 0;
CString sDisplayName;
CString sSearchPath;
CAssemblyCache *pAssemblyCache = NULL;
CCacheEntry* pEntry = NULL;
// BUGBUG: enable searching for all different cache status with dwFlag
IF_FALSE_EXIT((dwFlag == CACHEENUM_RETRIEVE_ALL || dwFlag == CACHEENUM_RETRIEVE_VISIBLE), E_INVALIDARG);
IF_FAILED_EXIT(pAsmId->GetDisplayName(ASMID_DISPLAYNAME_WILDCARDED, &pwzSearchDisplayName, &dwCC));
sDisplayName.TakeOwnership(pwzSearchDisplayName, dwCC);
// notenote: possibly modify assemblycache so that _sRootDir and IsStatus() can be use without creating an instance
pAssemblyCache = new(CAssemblyCache);
IF_ALLOC_FAILED_EXIT(pAssemblyCache);
IF_FAILED_EXIT(pAssemblyCache->Init(NULL, ASSEMBLY_CACHE_TYPE_APP | ASSEMBLY_CACHE_TYPE_IMPORT));
IF_FAILED_EXIT(sSearchPath.Assign(pAssemblyCache->_sRootDir));
IF_FAILED_EXIT(sSearchPath.Append(sDisplayName));
hFind = FindFirstFileEx(sSearchPath._pwz, FindExInfoStandard, &fdAppDir, FindExSearchLimitToDirectories, NULL, 0);
IF_TRUE_EXIT(hFind == INVALID_HANDLE_VALUE, S_FALSE);
while (dwLastError != ERROR_NO_MORE_FILES)
{
// ???? check file attribute to see if it's a directory? needed only if the file system does not support the filter...
if (dwFlag == CACHEENUM_RETRIEVE_ALL ||
(dwFlag == CACHEENUM_RETRIEVE_VISIBLE && CAssemblyCache::IsStatus(fdAppDir.cFileName, CAssemblyCache::VISIBLE)))
{
fFound = TRUE;
IF_FAILED_EXIT(sDisplayName.Assign(fdAppDir.cFileName));
pEntry = new(CCacheEntry);
IF_ALLOC_FAILED_EXIT(pEntry);
// store a copy of the displayname
sDisplayName.ReleaseOwnership(&(pEntry->_pwzDisplayName));
// add cache entry to the list
_listCacheEntry.AddHead(pEntry); // AddSorted() instead?
pEntry = NULL;
}
if (!FindNextFile(hFind, &fdAppDir))
{
dwLastError = GetLastError();
continue;
}
}
// BUGBUG: propagate the error if findnext fails != ERROR_NO_MORE_FILES
if (fFound)
{
_current = _listCacheEntry.GetHeadPosition();
_hr = S_OK;
}
else
_hr = S_FALSE;
exit:
if (hFind != INVALID_HANDLE_VALUE)
{
if (!FindClose(hFind))
{
// can return 0, even when there's an error.
DWORD dw = GetLastError();
_hr = dw ? HRESULT_FROM_WIN32(dw) : E_FAIL;
}
}
SAFERELEASE(pAssemblyCache);
return _hr;
}
// ---------------------------------------------------------------------------
// CAssemblyCacheEnum::GetNext
// ---------------------------------------------------------------------------
HRESULT CAssemblyCacheEnum::GetNext(IAssemblyCacheImport** ppAsmCache)
{
CCacheEntry* pEntry = NULL;
IF_NULL_EXIT(ppAsmCache, E_INVALIDARG);
*ppAsmCache = NULL;
IF_TRUE_EXIT(_current == NULL, S_FALSE); // S_FALSE == no more
if (pEntry = _listCacheEntry.GetNext(_current))
{
// note: this can return NULL
// *ppAsmCache is AddRef-ed
*ppAsmCache = pEntry->GetAsmCache();
}
else
// this is wrong
_hr = E_UNEXPECTED;
exit:
return _hr;
}
// ---------------------------------------------------------------------------
// CAssemblyCacheEnum::Reset
// ---------------------------------------------------------------------------
HRESULT CAssemblyCacheEnum::Reset()
{
_current = _listCacheEntry.GetHeadPosition();
return S_OK;
}
// ---------------------------------------------------------------------------
// CAssemblyCacheEnum::GetCount
// ---------------------------------------------------------------------------
HRESULT CAssemblyCacheEnum::GetCount(LPDWORD pdwCount)
{
if (pdwCount == NULL)
_hr = E_INVALIDARG;
else
{
// BUGBUG: platform-dependent: DWORD converting from int, check overflow
*pdwCount = (DWORD) _listCacheEntry.GetCount();
_hr = S_OK;
}
return _hr;
}
// IUnknown methods
// ---------------------------------------------------------------------------
// CAssemblyCacheEnum::QI
// ---------------------------------------------------------------------------
STDMETHODIMP
CAssemblyCacheEnum::QueryInterface(REFIID riid, void** ppvObj)
{
if ( IsEqualIID(riid, IID_IUnknown)
|| IsEqualIID(riid, IID_IAssemblyCacheEnum)
)
{
*ppvObj = static_cast<IAssemblyCacheEnum*> (this);
AddRef();
return S_OK;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
}
// ---------------------------------------------------------------------------
// CAssemblyCacheEnum::AddRef
// ---------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CAssemblyCacheEnum::AddRef()
{
return InterlockedIncrement ((LONG*) &_cRef);
}
// ---------------------------------------------------------------------------
// CAssemblyCacheEnum::Release
// ---------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CAssemblyCacheEnum::Release()
{
ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
if (!lRet)
delete this;
return lRet;
}