Exemple #1
0
HRESULT GetDLDirsFromName(IAssemblyName *pName, LPWSTR pszParentDir, LPWSTR pszSubDirName)
{
    HRESULT hr = S_OK;
    LPWSTR  pwzCodebaseURL=NULL;
    FILETIME ftLastMod;
    DWORD   cb=0;

    ASSERT(pName && pszParentDir && pszSubDirName);

    if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CODEBASE_URL,
        (LPBYTE*) &pwzCodebaseURL, &(cb = 0))))
        goto exit;

    hr = GetDLParentDir(pwzCodebaseURL, pszParentDir);

    if(FAILED(hr = pName->GetProperty(ASM_NAME_CODEBASE_LASTMOD,
        &ftLastMod, &(cb = sizeof(FILETIME)))))
        goto exit;

    GetDLAsmDir(&ftLastMod, pszSubDirName);

exit :
    SAFEDELETE(pwzCodebaseURL);
    return hr;
}
// ---------------------------------------------------------------------------
// CCache::TransCacheEntryFromName
// create transport entry from name
//---------------------------------------------------------------------------
HRESULT CCache::TransCacheEntryFromName(IAssemblyName *pName, 
    DWORD dwFlags, CTransCache **ppTransCache)
{    
    HRESULT hr;
    DWORD cb, dwCacheId = 0;
    TRANSCACHEINFO *pTCInfo = 0;
    CTransCache *pTransCache = NULL;

    _ASSERTE(pName);

    // Get the correct cache index.
    if(FAILED(hr = ResolveCacheIndex(pName, dwFlags, &dwCacheId)))
        goto exit;

    // Construct new CTransCache object.
    if(FAILED(hr = CreateTransCacheEntry(dwCacheId, &pTransCache)))
        goto exit;

    // Cast base info ptr to TRANSCACHEINFO ptr
    pTCInfo = (TRANSCACHEINFO*) pTransCache->_pInfo;
        
    // Downcased text name from target
    hr = NameObjGetWrapper(pName, ASM_NAME_NAME, (LPBYTE*) &pTCInfo->pwzName, &(cb = 0));

    if (SUCCEEDED(hr)) {
        for (DWORD i=0; i<4; i++) {
            cb = sizeof(WORD);
            hr = pName->GetProperty(ASM_NAME_MAJOR_VERSION+i, &(pTCInfo->wVers[i]), &cb);
            if (FAILED(hr)) {
                goto exit;
            }
        }
    }

    if (SUCCEEDED(hr)) {
        hr = NameObjGetWrapper(pName, ASM_NAME_CULTURE, (LPBYTE*) &pTCInfo->pwzCulture, &cb);
    }

    if (SUCCEEDED(hr)) {
        hr = NameObjGetWrapper(pName, ASM_NAME_PUBLIC_KEY_TOKEN, &pTCInfo->blobPKT.pBlobData, &pTCInfo->blobPKT.cbSize);
    }

    if (SUCCEEDED(hr)) {
        hr = NameObjGetWrapper(pName, ASM_NAME_SIGNATURE_BLOB, &pTCInfo->blobSignature.pBlobData, &pTCInfo->blobSignature.cbSize);
    }

    if (SUCCEEDED(hr)) {
        hr = NameObjGetWrapper(pName, ASM_NAME_MVID, &pTCInfo->blobMVID.pBlobData, &pTCInfo->blobMVID.cbSize);
    }
    
    if (SUCCEEDED(hr)) {
        hr = NameObjGetWrapper(pName, ASM_NAME_CODEBASE_URL, (LPBYTE*) &pTCInfo->pwzCodebaseURL, &(cb = 0));
    }

    if (SUCCEEDED(hr)) {
        hr = pName->GetProperty(ASM_NAME_CODEBASE_LASTMOD, &pTCInfo->ftLastModified, &(cb = sizeof(FILETIME)));
    }

    if(SUCCEEDED(hr)) {
        CAssemblyName   *pCName = static_cast<CAssemblyName*>(pName); // dynamic_cast
        DWORD           dwSize = 0;

        // Returns S_OK if no modifier exists
        hr = pCName->GetPathModifier(NULL, &dwSize);
        
        if(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
            pTCInfo->pwzPathModifier = NEW(WCHAR[dwSize]);
            if(!pTCInfo->pwzPathModifier) {
                hr = E_OUTOFMEMORY;
                goto exit;
            }

            hr = pCName->GetPathModifier(pTCInfo->pwzPathModifier, &dwSize);
        }
    }

    if (SUCCEEDED(hr)) {
        if(pTCInfo->pwzName && (lstrlenW(pTCInfo->pwzName) >= MAX_PATH) )
            hr = FUSION_E_INVALID_NAME;  // name is too long; this is an error.
    }

    if (SUCCEEDED(hr)) {
        CAssemblyName   *pCName = static_cast<CAssemblyName*>(pName); // dynamic_cast
        pTCInfo->fLegacyAssembly = pCName->IsLegacyAssembly();

        hr = pName->GetProperty(ASM_NAME_ARCHITECTURE, (LPBYTE) &pTCInfo->dwAsmImageType, &(cb = sizeof(DWORD)));
     }

exit:
    if (SUCCEEDED(hr))
    {
        *ppTransCache = pTransCache;
    }
    else
    {
        SAFERELEASE(pTransCache);
    }
    return hr;
}
Exemple #3
0
HRESULT GetCacheDirsFromName(IAssemblyName *pName,
    DWORD dwFlags, LPWSTR pszParentDirName, LPWSTR pszSubDirName)
{
    HRESULT hr = S_OK;
    DWORD   dwVerHigh=0;
    DWORD   dwVerLow=0;
    LPWSTR  pszTextName=NULL;
    DWORD   cb=0;
    PBYTE   pPKT=NULL;
    PBYTE   pCustom=NULL;
    DWORD   cbCustom=0;
    DWORD   cbPKT=0;
    LPWSTR  wzCulture=NULL;
    LPWSTR  szProp=NULL;

    ASSERT(pName && dwFlags && pszParentDirName && pszSubDirName);

    if( (dwFlags & ASM_CACHE_GAC) || (dwFlags & ASM_CACHE_ZAP) )
    {
        if (FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_NAME,
                (LPBYTE*) &pszTextName, &(cb = 0))))
            goto exit;

        if(cb > MAX_PATH)
        {
            hr = HRESULT_FROM_WIN32(FUSION_E_INVALID_NAME);
            goto exit;
        }

        StrCpy(pszParentDirName, pszTextName);

        // Version
        if(FAILED(hr = pName->GetVersion(&dwVerHigh, &dwVerLow)))
            goto exit;

        // Culture
        if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CULTURE, (LPBYTE*) &wzCulture, &cb)))
            goto exit;

        // PublicKeyToken
        if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_PUBLIC_KEY_TOKEN, &pPKT, &cbPKT)))
            goto exit;

        if (dwFlags & ASM_CACHE_ZAP)
        {
            if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CUSTOM, 
                            &pCustom, &(cbCustom = 0))))
                goto exit;
        }

        hr = GetAsmDir(pszSubDirName, dwFlags, dwVerHigh, dwVerLow, 
                        wzCulture, pPKT, cbPKT, 
                        pCustom, cbCustom);


    }
    else if (dwFlags & ASM_CACHE_DOWNLOAD)
    {
        GetDLDirsFromName(pName, pszParentDirName, pszSubDirName);
    }

exit:

    SAFEDELETE(szProp);
    SAFEDELETE(wzCulture);
    SAFEDELETE(pPKT);
    SAFEDELETE(pCustom);
    SAFEDELETE(pszTextName);

    return hr;
}
Exemple #4
0
HRESULT GetFusionInfo(CTransCache *pTC, LPWSTR pszAsmDir)
{
    HRESULT hr = S_OK;
    WCHAR   wzFilePath[MAX_PATH+1];
    DWORD  cbSize=0;
    PBYTE pMVID=NULL;
    DWORD dwAttrib;
    DWORD cb;
    IAssemblyName *pName=NULL;
    LPWSTR pszBuf=NULL;
    BOOL bMVIDFailed=FALSE;
    BOOL bCustomFailed=FALSE;
    BOOL bURLFailed=FALSE;
    BOOL bDispNameFailed=FALSE;
    HINI hIni=NULL;
    TRANSCACHEINFO *pTCInfo = NULL;

    ASSERT(pszAsmDir || (pTC && pTC->_pInfo->pwzPath));

    pszBuf = NEW(WCHAR[MAX_URL_LENGTH+1]);
    if (!pszBuf)
    {
        hr = E_OUTOFMEMORY;
        goto exit;
    }

    if(pTC && pTC->_pInfo->pwzPath)
    {  
        // if there is path is transprtCache obj use it. else use second param pszAsmDir
        wnsprintf(wzFilePath, MAX_PATH, L"%s", pTC->_pInfo->pwzPath);
    }
    else
    {
        wnsprintf(wzFilePath, MAX_PATH, L"%s", pszAsmDir);
    }

    if((dwAttrib = GetFileAttributes(wzFilePath)) == (DWORD) -1)
    {
        hr = E_FAIL;
        goto exit;
    }

    if(!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
    {
        // looks manifestFilePath is passed in. knock-off the filename.
        LPWSTR pszTemp = PathFindFileName(wzFilePath);
        if(pszTemp > wzFilePath)
        {
            *(pszTemp-1) = L'\0';
        }
    }
    // else we have assembly dir;

    wnsprintf(wzFilePath, MAX_PATH, L"%s\\%s", wzFilePath, g_FusionInfoFile);

    if ((hIni = PAL_IniCreate()) == NULL)
    {
        hr = FusionpHresultFromLastError();
        goto exit;
    }

    if (!PAL_IniLoad(hIni, wzFilePath))
    {
        hr = FusionpHresultFromLastError();
        goto exit;
    }

#define _ReadString(section, key, buf, size) PAL_IniReadString(hIni, section, key, buf, size)

    pTCInfo = (TRANSCACHEINFO*) pTC->_pInfo;

    cbSize = _ReadString(ASSEMBLY_INFO_STRING, MVID_KEY_STRING, pszBuf, MAX_URL_LENGTH);

    if(cbSize == MVID_LENGTH*2)
    {
        pMVID = NEW(BYTE[MVID_LENGTH]);
        if (!pMVID)
        {
            hr = E_OUTOFMEMORY;
            goto exit;
        }

        CParseUtils::UnicodeHexToBin(pszBuf, MVID_LENGTH*2, (LPBYTE) pMVID);

        SAFEDELETEARRAY(pTCInfo->blobMVID.pBlobData);
        pTCInfo->blobMVID.pBlobData = pMVID;
        pTCInfo->blobMVID.cbSize = MVID_LENGTH;
        pMVID = NULL;
    }
    else
        bMVIDFailed = TRUE;

    if(pTC->GetCacheType() & ASM_CACHE_ZAP)
    {
        cbSize = _ReadString(ASSEMBLY_INFO_STRING, CUSTOM_BLOB_STRING, pszBuf, MAX_URL_LENGTH);

        if(cbSize)
        {
            SAFEDELETEARRAY(pTCInfo->blobCustom.pBlobData);
            pTCInfo->blobCustom.pBlobData = (PBYTE) WSTRDupDynamic(pszBuf);
            if (!pTCInfo->blobCustom.pBlobData)
            {
                hr = E_OUTOFMEMORY;
                goto exit;
            }
            pTCInfo->blobCustom.cbSize = (cbSize + 1) * sizeof(WCHAR) ;
        }
        else
            bCustomFailed = TRUE;

    }
    else
    {
        cbSize = _ReadString(ASSEMBLY_INFO_STRING, URL_STRING, pszBuf, MAX_URL_LENGTH);

        if(cbSize)
        {
            SAFEDELETEARRAY(pTCInfo->pwzCodebaseURL);
            pTCInfo->pwzCodebaseURL = WSTRDupDynamic(pszBuf);

            if (!pTCInfo->pwzCodebaseURL)
            {
                hr = E_OUTOFMEMORY;
                goto exit;
            }
        }
        else
            bURLFailed = TRUE;

        if(pTC->GetCacheType() & ASM_CACHE_DOWNLOAD)
        {
            cbSize = _ReadString(ASSEMBLY_INFO_STRING, DISPLAY_NAME_STRING, pszBuf, MAX_URL_LENGTH);

            if(cbSize)
            {
                if (FAILED(hr = CreateAssemblyNameObject(&pName, pszBuf, CANOF_PARSE_DISPLAY_NAME, 0)))
                    goto exit;

                SAFEDELETEARRAY(pTCInfo->pwzName);

                if (FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_NAME,
                        (LPBYTE*) &pTCInfo->pwzName, &(cb = 0))))
                    goto exit;

                // Version
                if(FAILED(hr = pName->GetVersion(&pTCInfo->dwVerHigh, &pTCInfo->dwVerLow)))
                    goto exit;

                SAFEDELETEARRAY(pTCInfo->pwzCulture);

                // Culture
                if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CULTURE,
                    (LPBYTE*) &pTCInfo->pwzCulture, &cb))
                        || (pTCInfo->pwzCulture && !_wcslwr(pTCInfo->pwzCulture)))
                    goto exit;

                SAFEDELETEARRAY(pTCInfo->blobPKT.pBlobData);

                // PublicKeyToken
                if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_PUBLIC_KEY_TOKEN, 
                    &pTCInfo->blobPKT.pBlobData, &pTCInfo->blobPKT.cbSize)))
                    goto exit;
            }
            else
                bDispNameFailed = TRUE;
        }
    }

exit:

    SAFEDELETEARRAY(pszBuf);
    SAFEDELETEARRAY(pMVID);
    SAFERELEASE(pName);

    if(SUCCEEDED(hr))
    {
        if(bMVIDFailed || bCustomFailed)
            hr = E_FAIL;
        else if(bDispNameFailed || bURLFailed)
            hr = S_FALSE;
    }

    return hr;
}
Exemple #5
0
HRESULT StoreFusionInfo(IAssemblyName *pName, LPWSTR pszDir, DWORD *pdwFileSizeLow)
{
    HRESULT hr = S_OK;
    WCHAR  pszFilePath[MAX_PATH+1];
    PBYTE  pMVID=NULL;
    PBYTE  pCustom=NULL;
    LPWSTR pszCustomString=NULL;
    LPWSTR pszURL=NULL;
    LPWSTR pszDisplayName=NULL;
    DWORD  cbSize=0;
    BOOL fRet = FALSE;
    DWORD  dwSize;
    LPWSTR pszBuf=NULL;
    HINI hIni=NULL;

    if(( lstrlenW(pszDir) + lstrlenW(g_FusionInfoFile) + 1) >= MAX_PATH)
    {
        hr = HRESULT_FROM_WIN32(FUSION_E_INVALID_NAME);
        goto exit;
    }

    StrCpy(pszFilePath, pszDir);
    PathAddBackslash(pszFilePath);
    StrCat(pszFilePath, g_FusionInfoFile);

    if ((hIni = PAL_IniCreate()) == NULL)
    {
        hr = FusionpHresultFromLastError();
        goto exit;
    }

#define _WriteString(section, key, value) PAL_IniWriteString(hIni, section, key, value)

    pszBuf = NEW(WCHAR[MAX_URL_LENGTH+1]);
    if (!pszBuf)
    {
        hr = E_OUTOFMEMORY;
        goto exit;
    }

    cbSize = 0;
    if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_MVID, 
            &pMVID, &cbSize)))
        goto exit;

    if(cbSize && (cbSize == MVID_LENGTH))
    {
        CParseUtils::BinToUnicodeHex(pMVID, cbSize, pszBuf);

        pszBuf[MVID_LENGTH*2] = L'\0';

        fRet = _WriteString(ASSEMBLY_INFO_STRING, MVID_KEY_STRING, pszBuf);
        if (!fRet)
        {
            hr = FusionpHresultFromLastError();
            goto exit;
        }
    }

    cbSize = 0;
    if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CUSTOM, 
            &pCustom, &cbSize)))
        goto exit;

    if(cbSize)
    {
        pszCustomString = (LPWSTR) pCustom;
        fRet = _WriteString(ASSEMBLY_INFO_STRING, CUSTOM_BLOB_STRING, pszCustomString);
        if (!fRet)
        {
            hr = FusionpHresultFromLastError();
            goto exit;
        }
    }
    else
    {
        // if there is no Custom Blob try storing URL.
        cbSize = 0;
        if(FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CODEBASE_URL, (LPBYTE*) &pszURL, &cbSize)))
            goto exit;

        if(cbSize)
        {
            fRet = _WriteString(ASSEMBLY_INFO_STRING, URL_STRING, pszURL);
            if (!fRet)
            {
                hr = FusionpHresultFromLastError();
                goto exit;
            }
        }

        dwSize = 0;
        hr = pName->GetDisplayName(NULL, &dwSize, 0);
        if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
            ASSERT(0);
            hr = E_UNEXPECTED;
            goto exit;
        }

        pszDisplayName = NEW(WCHAR[dwSize]);
        if (!pszDisplayName) {
            hr = E_OUTOFMEMORY;
            goto exit;
        }

        hr = pName->GetDisplayName(pszDisplayName, &dwSize, 0);
        if (FAILED(hr)) {
            goto exit;
        }

        cbSize = dwSize * sizeof(WCHAR);
        if(cbSize)
        {
            fRet = _WriteString(ASSEMBLY_INFO_STRING, DISPLAY_NAME_STRING, pszDisplayName);
            if (!fRet)
            {
                hr = FusionpHresultFromLastError();
                goto exit;
            }
        }
    }

    if (!PAL_IniSave(hIni, pszFilePath, TRUE))
    {
        hr = FusionpHresultFromLastError();
        goto exit;        
    }

    {
        DWORD dwSizeHigh=0;
        *pdwFileSizeLow = 512; // hard-code info file size.

        hr = GetFileSizeRoundedToCluster(INVALID_HANDLE_VALUE, pdwFileSizeLow, &dwSizeHigh);
    }

exit:

    if (hIni != NULL)
        PAL_IniClose(hIni);

    SAFEDELETEARRAY(pszBuf);
    SAFEDELETEARRAY(pszDisplayName);
    SAFEDELETEARRAY(pMVID);
    SAFEDELETEARRAY(pCustom);
    SAFEDELETEARRAY(pszURL);

    return hr;
}
Exemple #6
0
// ---------------------------------------------------------------------------
// CCache::TransCacheEntryFromName
// create transport entry from name
//---------------------------------------------------------------------------
HRESULT CCache::TransCacheEntryFromName(IAssemblyName *pName, 
    DWORD dwFlags, CTransCache **ppTransCache)
{    
    HRESULT hr;
    DWORD cb, dwCacheId = 0;
    TRANSCACHEINFO *pTCInfo = 0;
    CTransCache *pTransCache = NULL;
            
    // Get the correct cache index.
    if(FAILED(hr = ResolveCacheIndex(pName, dwFlags, &dwCacheId)))
        goto exit;

    // Construct new CTransCache object.
    if(FAILED(hr = CreateTransCacheEntry(dwCacheId, &pTransCache)))
        goto exit;

    // Cast base info ptr to TRANSCACHEINFO ptr
    pTCInfo = (TRANSCACHEINFO*) pTransCache->_pInfo;
        
    // Downcased text name from target
    if (FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_NAME,
            (LPBYTE*) &pTCInfo->pwzName, &(cb = 0)))
    
        // Version
        || FAILED(hr = pName->GetVersion(&pTCInfo->dwVerHigh, &pTCInfo->dwVerLow))

        // Culture
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CULTURE,
            (LPBYTE*) &pTCInfo->pwzCulture, &cb))
                || (pTCInfo->pwzCulture && !_wcslwr(pTCInfo->pwzCulture))

        // PublicKeyToken
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_PUBLIC_KEY_TOKEN, 
            &pTCInfo->blobPKT.pBlobData, &pTCInfo->blobPKT.cbSize))

        // Custom
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CUSTOM, 
            &pTCInfo->blobCustom.pBlobData, &pTCInfo->blobCustom.cbSize))

        // MVID
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_MVID, 
            &pTCInfo->blobMVID.pBlobData, &pTCInfo->blobMVID.cbSize))

        // Codebase url if any from target
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CODEBASE_URL, 
            (LPBYTE*) &pTCInfo->pwzCodebaseURL, &(cb = 0)))

        || FAILED(hr = pName->GetProperty(ASM_NAME_CODEBASE_LASTMOD,
            &pTCInfo->ftLastModified, &(cb = sizeof(FILETIME)))))

    {
        goto exit;
    }


    if(pTCInfo->pwzName && (lstrlen(pTCInfo->pwzName) >= MAX_PATH) )
        hr = FUSION_E_INVALID_NAME;  // name is too long; this is an error.

exit:
    if (SUCCEEDED(hr))
    {
        *ppTransCache = pTransCache;
    }
    else
    {
        SAFERELEASE(pTransCache);
    }
    return hr;
}
Exemple #7
0
// ---------------------------------------------------------------------------
// CCache::InsertTransCacheEntry
//---------------------------------------------------------------------------
HRESULT CCache::InsertTransCacheEntry(IAssemblyName *pName,
    LPTSTR szPath, DWORD dwKBSize, DWORD dwFlags,
    DWORD dwCommitFlags, DWORD dwPinBits, CTransCache **ppTransCache)
{
    HRESULT hr;
    DWORD cb, dwCacheId;
    TRANSCACHEINFO *pTCInfo = NULL;
    CTransCache *pTransCache = NULL;
    LPWSTR pwzCodebaseUrl = NULL;
    WCHAR pwzCanonicalized[MAX_URL_LENGTH];
    
    
    // Determine which cache index to insert to.
    if (FAILED(hr = ResolveCacheIndex(pName, dwFlags, &dwCacheId)))
        goto exit;

    // Construct new CTransCache object.
    if(FAILED(hr = CreateTransCacheEntry(dwCacheId, &pTransCache)))
        goto exit;
    

    // Cast pTransCache base info ptr to TRANSCACHEINFO ptr
    pTCInfo = (TRANSCACHEINFO*) pTransCache->_pInfo;
    
    // Downcased text name from target
    if (FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_NAME,
            (LPBYTE*) &pTCInfo->pwzName, &(cb = 0))) 
    
        // Version
        || FAILED(hr = pName->GetVersion(&pTCInfo->dwVerHigh, &pTCInfo->dwVerLow))

        // Culture (downcased)
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CULTURE,
            (LPBYTE*) &pTCInfo->pwzCulture, &cb))
            || (pTCInfo->pwzCulture && !_wcslwr(pTCInfo->pwzCulture))

        // PublicKeyToken
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_PUBLIC_KEY_TOKEN, 
            &pTCInfo->blobPKT.pBlobData, &pTCInfo->blobPKT.cbSize))

        // Custom
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CUSTOM, 
            &pTCInfo->blobCustom.pBlobData, &pTCInfo->blobCustom.cbSize))

        // MVID
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_MVID, 
            &pTCInfo->blobMVID.pBlobData, &pTCInfo->blobMVID.cbSize))    
    
        // Codebase url if any from target
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_CODEBASE_URL, 
            (LPBYTE*)&pwzCodebaseUrl, &(cb = 0)))

        // Codebase last modified time if any from target.
        || FAILED(hr = pName->GetProperty(ASM_NAME_CODEBASE_LASTMOD,
            &pTCInfo->ftLastModified, &(cb = sizeof(FILETIME))))

        // PK if any from source.
        || FAILED(hr = NameObjGetWrapper(pName, ASM_NAME_PUBLIC_KEY, 
            &pTCInfo->blobPK.pBlobData, &pTCInfo->blobPK.cbSize))


        )
    {
        goto exit;
    }

    if (pwzCodebaseUrl)
    {
        cb = MAX_URL_LENGTH;
        hr = UrlCanonicalizeUnescape(pwzCodebaseUrl, pwzCanonicalized, &cb, 0);
        if (FAILED(hr)) {
            goto exit;
        }

        pTCInfo->pwzCodebaseURL = WSTRDupDynamic(pwzCanonicalized);
        if (!pTCInfo->pwzCodebaseURL) {
            hr = E_OUTOFMEMORY;
            goto exit;
        }
    }
    else
    {
        pTCInfo->pwzCodebaseURL = NULL;
    }

    // Copy in path.
    if (!(pTCInfo->pwzPath = TSTRDupDynamic(szPath)))
    {
        hr = E_OUTOFMEMORY;
        goto exit;
    }

    // File size
    pTCInfo->dwKBSize = dwKBSize;

    // Set pin Bits
    pTCInfo->dwPinBits = dwPinBits;        
             
exit:
    SAFEDELETEARRAY(pwzCodebaseUrl);

    // Base destructor takes care
    // of everything.
    if (!ppTransCache 
        || (FAILED(hr) && (hr != DB_E_DUPLICATE)))    
    {
        SAFERELEASE(pTransCache);
    }
    else 
    {
        *ppTransCache = pTransCache;
    }
    return hr;
}