438 lines
12 KiB
C++
438 lines
12 KiB
C++
#include <fusenetincludes.h>
|
|
#include <msxml2.h>
|
|
#include <sxsid.h>
|
|
#include <assemblyidentity.h>
|
|
#include <shlwapi.h>
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CreateAssemblyIdentity
|
|
// ---------------------------------------------------------------------------
|
|
STDAPI
|
|
CreateAssemblyIdentity(
|
|
LPASSEMBLY_IDENTITY *ppAssemblyId,
|
|
DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CAssemblyIdentity *pAssemblyId = NULL;
|
|
|
|
pAssemblyId = new(CAssemblyIdentity);
|
|
if (!pAssemblyId)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
hr = pAssemblyId->Init();
|
|
if (FAILED(hr))
|
|
{
|
|
SAFERELEASE(pAssemblyId);
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
*ppAssemblyId = pAssemblyId;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDAPI
|
|
CreateAssemblyIdentityEx(
|
|
LPASSEMBLY_IDENTITY *ppAssemblyId,
|
|
DWORD dwFlags,
|
|
LPWSTR wzDisplayName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CAssemblyIdentity *pAssemblyId = NULL;
|
|
|
|
pAssemblyId = new(CAssemblyIdentity);
|
|
if (!pAssemblyId)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
hr = pAssemblyId->Init();
|
|
if (FAILED(hr))
|
|
{
|
|
SAFERELEASE(pAssemblyId);
|
|
goto exit;
|
|
}
|
|
|
|
if (wzDisplayName)
|
|
{
|
|
LPWSTR pwzStart, pwzEnd;
|
|
CString Temp[4];
|
|
CString sDirName;
|
|
int i=0;
|
|
|
|
sDirName.Assign(wzDisplayName);
|
|
pwzStart = sDirName._pwz;
|
|
pwzEnd = sDirName._pwz;
|
|
|
|
while (pwzEnd = StrChr(pwzEnd, L'_'))
|
|
{
|
|
*pwzEnd = L'\0';
|
|
Temp[i++].Assign(pwzStart);
|
|
pwzStart = ++pwzEnd;
|
|
}
|
|
pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE,
|
|
(LPCOLESTR)pwzStart, lstrlen(pwzStart) + 1);
|
|
pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION,
|
|
(LPCOLESTR)Temp[3]._pwz, lstrlen(Temp[3]._pwz) + 1);
|
|
pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN,
|
|
(LPCOLESTR)Temp[2]._pwz, lstrlen(Temp[2]._pwz) + 1);
|
|
pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
|
|
(LPCOLESTR)Temp[1]._pwz, lstrlen(Temp[1]._pwz) + 1);
|
|
pAssemblyId->SetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE,
|
|
(LPCOLESTR)Temp[0]._pwz, lstrlen(Temp[0]._pwz) + 1);
|
|
}
|
|
|
|
exit:
|
|
|
|
*ppAssemblyId = pAssemblyId;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CloneAssemblyIdentity
|
|
// ---------------------------------------------------------------------------
|
|
STDAPI
|
|
CloneAssemblyIdentity(
|
|
LPASSEMBLY_IDENTITY pSrcAssemblyId,
|
|
LPASSEMBLY_IDENTITY *ppDestAssemblyId)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CAssemblyIdentity *pAssemblyId = NULL;
|
|
|
|
if (pSrcAssemblyId == NULL || ppDestAssemblyId == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
*ppDestAssemblyId = NULL;
|
|
|
|
if (FAILED(hr = CreateAssemblyIdentity((LPASSEMBLY_IDENTITY*) &pAssemblyId, 0)))
|
|
goto exit;
|
|
|
|
if (!SxsDuplicateAssemblyIdentity(0, (static_cast<CAssemblyIdentity*> (pSrcAssemblyId))->_pId,
|
|
&(pAssemblyId->_pId)))
|
|
{
|
|
DWORD dw = ::GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dw);
|
|
goto exit;
|
|
}
|
|
|
|
*ppDestAssemblyId = pAssemblyId;
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ctor
|
|
// ---------------------------------------------------------------------------
|
|
CAssemblyIdentity::CAssemblyIdentity()
|
|
: _dwSig('TNDI'), _cRef(1), _hr(S_OK), _pId(NULL)
|
|
{
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// dtor
|
|
// ---------------------------------------------------------------------------
|
|
CAssemblyIdentity::~CAssemblyIdentity()
|
|
{
|
|
SxsDestroyAssemblyIdentity(_pId);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Init
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CAssemblyIdentity::Init()
|
|
{
|
|
if (!SxsCreateAssemblyIdentity(0, ASSEMBLY_IDENTITY_TYPE_DEFINITION, &_pId, 0, NULL))
|
|
{
|
|
DWORD dw = ::GetLastError();
|
|
_hr = HRESULT_FROM_WIN32(dw);
|
|
}
|
|
else
|
|
_hr = S_OK;
|
|
|
|
return _hr;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// SetAttribute
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CAssemblyIdentity::SetAttribute(LPCOLESTR pwzName,
|
|
LPCOLESTR pwzValue, DWORD ccValue)
|
|
{
|
|
DWORD ccName = lstrlen(pwzName);
|
|
|
|
SXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttrRef;
|
|
|
|
AttrRef.Namespace = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE;
|
|
AttrRef.NamespaceCch = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE_CCH;
|
|
AttrRef.Name = pwzName;
|
|
AttrRef.NameCch = ccName;
|
|
|
|
// BUGBUG: should allow overwrite or not?
|
|
if (!SxspSetAssemblyIdentityAttributeValue(
|
|
SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
|
|
_pId, &AttrRef, pwzValue, ccValue))
|
|
{
|
|
DWORD dw = ::GetLastError();
|
|
_hr = HRESULT_FROM_WIN32(dw);
|
|
}
|
|
else
|
|
_hr = S_OK;
|
|
|
|
return _hr;
|
|
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// GetAttribute
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CAssemblyIdentity::GetAttribute(LPCOLESTR pwzName,
|
|
LPOLESTR *ppwzValue, LPDWORD pccValue)
|
|
{
|
|
LPWSTR pwzValue = NULL;
|
|
PCWSTR pwzStringOut = NULL;
|
|
DWORD ccStringOut = 0;
|
|
DWORD ccName = lstrlen(pwzName);
|
|
|
|
SXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttrRef;
|
|
|
|
AttrRef.Namespace = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE;
|
|
AttrRef.NamespaceCch = SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE_CCH;
|
|
AttrRef.Name = pwzName;
|
|
AttrRef.NameCch = ccName;
|
|
|
|
if (!SxspGetAssemblyIdentityAttributeValue(0, _pId, &AttrRef, &pwzStringOut, &ccStringOut))
|
|
{
|
|
DWORD dw = ::GetLastError();
|
|
_hr = HRESULT_FROM_WIN32(dw);
|
|
goto exit;
|
|
}
|
|
|
|
pwzValue = WSTRDupDynamic(pwzStringOut);
|
|
if (!pwzValue)
|
|
{
|
|
_hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
_hr = S_OK;
|
|
|
|
*ppwzValue = pwzValue;
|
|
*pccValue = ccStringOut;
|
|
|
|
exit:
|
|
|
|
return _hr;
|
|
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// IsEqual
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CAssemblyIdentity::IsEqual (IAssemblyIdentity *pAssemblyId)
|
|
{
|
|
LPWSTR pwzBuf;
|
|
DWORD ccBuf;
|
|
CString sLang1, sVersion1, sToken1, sName1, sArch1;
|
|
CString sLang2, sVersion2, sToken2, sName2, sArch2;
|
|
|
|
// Compare architectures
|
|
if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sArch1.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sArch2.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (StrCmp (sArch1._pwz, sArch2._pwz))
|
|
{
|
|
_hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Compare names
|
|
if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sName1.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sName2.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (StrCmp (sName1._pwz, sName2._pwz))
|
|
{
|
|
_hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Compare Public Key Tokens
|
|
if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sToken1.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sToken2.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (StrCmp (sToken1._pwz, sToken2._pwz))
|
|
{
|
|
_hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Compare Versions
|
|
if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sVersion1.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sVersion2.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (StrCmp (sVersion1._pwz, sVersion2._pwz))
|
|
{
|
|
_hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// Compare Languages
|
|
if (FAILED(_hr = (pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sLang1.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (FAILED(_hr = (GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzBuf, &ccBuf))))
|
|
goto exit;
|
|
sLang2.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
if (StrCmp (sLang1._pwz, sLang2._pwz))
|
|
{
|
|
_hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
_hr = S_OK;
|
|
exit:
|
|
|
|
return _hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define WZ_WILDCARDSTRING L"*"
|
|
// ---------------------------------------------------------------------------
|
|
// GetDisplayName
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CAssemblyIdentity::GetDisplayName(DWORD dwFlags, LPOLESTR *ppwzDisplayName, LPDWORD pccDisplayName)
|
|
{
|
|
LPWSTR rpwzAttrNames[5] =
|
|
{
|
|
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE,
|
|
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
|
|
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN,
|
|
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION,
|
|
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE,
|
|
};
|
|
|
|
LPWSTR pwzBuf = NULL;
|
|
DWORD ccBuf = 0;
|
|
|
|
CString sDisplayName;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
CString sBuffer;
|
|
if (FAILED(_hr = GetAttribute(rpwzAttrNames[i], &pwzBuf, &ccBuf))
|
|
&& _hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
|
|
goto exit;
|
|
|
|
// append anyway to keep the number of underscore constant
|
|
if (i)
|
|
sDisplayName.Append(L"_");
|
|
|
|
if (dwFlags == ASMID_DISPLAYNAME_WILDCARDED
|
|
&& _hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
|
|
{
|
|
sDisplayName.Append(WZ_WILDCARDSTRING);
|
|
|
|
_hr = S_OK;
|
|
}
|
|
else if (_hr == S_OK)
|
|
{
|
|
sBuffer.TakeOwnership(pwzBuf, ccBuf);
|
|
|
|
sDisplayName.Append(sBuffer);
|
|
}
|
|
}
|
|
|
|
*ppwzDisplayName = sDisplayName._pwz;
|
|
*pccDisplayName = sDisplayName._cc;
|
|
|
|
sDisplayName.ReleaseOwnership();
|
|
|
|
exit:
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// IUnknown Boilerplate
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CAssemblyIdentity::QI
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CAssemblyIdentity::QueryInterface(REFIID riid, void** ppvObj)
|
|
{
|
|
if ( IsEqualIID(riid, IID_IUnknown)
|
|
|| IsEqualIID(riid, IID_IAssemblyIdentity)
|
|
)
|
|
{
|
|
*ppvObj = static_cast<IAssemblyIdentity*> (this);
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CAssemblyIdentity::AddRef
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CAssemblyIdentity::AddRef()
|
|
{
|
|
return InterlockedIncrement ((LONG*) &_cRef);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CAssemblyIdentity::Release
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CAssemblyIdentity::Release()
|
|
{
|
|
ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
|
|
if (!lRet)
|
|
delete this;
|
|
return lRet;
|
|
}
|
|
|