HRESULT AssemblySpec::GetAssemblyFromFusion(AppDomain* pAppDomain, IAssemblyName* pFusionAssemblyName, CodeBaseInfo* pCodeBase, IAssembly** ppFusionAssembly, PEFile** ppFile, CQuickWSTR* pFusionLog, OBJECTREF* pExtraEvidence, OBJECTREF* pThrowable) { _ASSERTE(ppFile); HRESULT hr = S_OK; IAssembly *pFusionAssembly = NULL; COMPLUS_TRY { DWORD dwSize = MAX_PATH; CQuickWSTR bufferPath; WCHAR *pPath = NULL; AssemblySink* pSink; DWORD eLocation; CQuickWSTR bufferCodebase; LPWSTR pwsCodeBase = NULL; DWORD dwCodeBase = 0; IAssemblyName *pNameDef = NULL; IApplicationContext *pFusionContext = pAppDomain->GetFusionContext(); pSink = pAppDomain->GetAssemblySink(); if(!pSink) { hr = E_OUTOFMEMORY; COMPLUS_LEAVE; } pSink->pFusionLog=pFusionLog; hr = FusionBind::GetAssemblyFromFusion(pFusionContext, pSink, pFusionAssemblyName, pCodeBase, &pFusionAssembly); pSink->pFusionLog=NULL; if(SUCCEEDED(hr)) { _ASSERTE(pFusionAssembly); // Get the path to the module containing the manifest dwSize = bufferPath.MaxSize(); pPath = bufferPath.Ptr(); hr = pFusionAssembly->GetManifestModulePath(pPath, &dwSize); if(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { pPath = bufferPath.Alloc(dwSize); if (pPath == NULL) { hr = E_OUTOFMEMORY; COMPLUS_LEAVE; } hr = pFusionAssembly->GetManifestModulePath(pPath, &dwSize); } if(SUCCEEDED(hr)) { hr = pFusionAssembly->GetAssemblyNameDef(&pNameDef); if (SUCCEEDED(hr)) { dwCodeBase = bufferCodebase.MaxSize(); pwsCodeBase = bufferCodebase.Ptr(); hr = pNameDef->GetProperty(ASM_NAME_CODEBASE_URL, pwsCodeBase, &dwCodeBase); if(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { pwsCodeBase = bufferCodebase.Alloc(dwCodeBase); if (pwsCodeBase == NULL) { hr = E_OUTOFMEMORY; COMPLUS_LEAVE; } hr = pNameDef->GetProperty(ASM_NAME_CODEBASE_URL, pwsCodeBase, &dwCodeBase); } pNameDef->Release(); } } } pSink->Release(); if(hr == S_OK && dwSize) { // See if we need to perform a strong name verification. hr = pFusionAssembly->GetAssemblyLocation(&eLocation); if (SUCCEEDED(hr)) { switch ((eLocation & ASMLOC_LOCATION_MASK)) { case ASMLOC_GAC: case ASMLOC_DOWNLOAD_CACHE: case ASMLOC_UNKNOWN: // Assemblies from the GAC or download cache have // already been verified by Fusion. Location Unknown // indicates a load from the dev path, which we'll // assume isn't a interesting case for verification. hr = S_OK; break; case ASMLOC_RUN_FROM_SOURCE: // For now, just verify these every time, we need to // cache the fact that at least one verification has // been performed (if strong name policy permits if (SUCCEEDED(hr)&&(eLocation&ASMLOC_CODEBASE_HINT)) { hr=CheckFileAccess(pPath,FILE_READ_DATA); if (FAILED(hr)) break; } // caching of verification results). if (StrongNameSignatureVerification(pPath, SN_INFLAG_INSTALL|SN_INFLAG_ALL_ACCESS|SN_INFLAG_RUNTIME, NULL)) hr = S_OK; else { hr = StrongNameErrorInfo(); if (hr == CORSEC_E_MISSING_STRONGNAME) hr = S_OK; else hr = CORSEC_E_INVALID_STRONGNAME; } break; default: _ASSERTE(FALSE); } if (SUCCEEDED(hr)) { hr = SystemDomain::LoadFile(pPath, NULL, mdFileNil, FALSE, pFusionAssembly, pwsCodeBase, pExtraEvidence, ppFile, FALSE); if (SUCCEEDED(hr)) { if(ppFusionAssembly) { pFusionAssembly->AddRef(); *ppFusionAssembly = pFusionAssembly; } if((eLocation & ASMLOC_LOCATION_MASK) == ASMLOC_GAC) // Assemblies in the GAC have also had any internal module // hashes verified at install time. (*ppFile)->SetHashesVerified(); } } } else if (hr == E_NOTIMPL) { // process exe _ASSERTE(pAppDomain == SystemDomain::System()->DefaultDomain()); hr = PEFile::Clone(SystemDomain::System()->DefaultDomain()->m_pRootFile, ppFile); if(SUCCEEDED(hr) && ppFusionAssembly) { pFusionAssembly->AddRef(); *ppFusionAssembly = pFusionAssembly; } } } } COMPLUS_CATCH { BEGIN_ENSURE_COOPERATIVE_GC(); if (pThrowable) { *pThrowable = GETTHROWABLE(); hr = SecurityHelper::MapToHR(*pThrowable); } else hr = SecurityHelper::MapToHR(GETTHROWABLE()); END_ENSURE_COOPERATIVE_GC(); } COMPLUS_END_CATCH if (pFusionAssembly) pFusionAssembly->Release(); return hr; }
STDAPI CopyPDBs(IAssembly *pAsm) { HRESULT hr = S_OK; IAssemblyName *pName = NULL; IAssemblyModuleImport *pModImport = NULL; DWORD dwSize; WCHAR wzAsmCachePath[MAX_PATH]; WCHAR wzFileName[MAX_PATH]; WCHAR wzSourcePath[MAX_PATH]; WCHAR wzPDBName[MAX_PATH]; WCHAR wzPDBSourcePath[MAX_PATH]; WCHAR wzPDBTargetPath[MAX_PATH]; WCHAR wzModPath[MAX_PATH]; LPWSTR wzCodebase=NULL; LPWSTR wzModName = NULL; DWORD dwIdx = 0; LPWSTR wzTmp = NULL; if (!pAsm) { hr = E_INVALIDARG; goto Exit; } if (pAsm->GetAssemblyLocation(NULL) == E_NOTIMPL) { // This is a registered "known assembly" (ie. the process EXE). // We don't copy PDBs for the process EXE because it's never // shadow copied. hr = S_FALSE; goto Exit; } // Find the source location. Make sure this is a file:// URL (ie. we // don't support retrieving the PDB over http://). hr = pAsm->GetAssemblyNameDef(&pName); if (FAILED(hr)) { goto Exit; } wzCodebase = NEW(WCHAR[MAX_URL_LENGTH+1]); if (!wzCodebase) { hr = E_OUTOFMEMORY; goto Exit; } dwSize = MAX_URL_LENGTH * sizeof(WCHAR); hr = pName->GetProperty(ASM_NAME_CODEBASE_URL, (void *)wzCodebase, &dwSize); if (FAILED(hr)) { goto Exit; } if (!UrlIsW(wzCodebase, URLIS_FILEURL)) { hr = E_INVALIDARG; goto Exit; } dwSize = MAX_PATH; hr = PathCreateFromUrlWrap(wzCodebase, wzSourcePath, &dwSize, 0); if (FAILED(hr)) { goto Exit; } wzTmp = PathFindFileName(wzSourcePath); ASSERT(wzTmp > (LPWSTR)wzSourcePath); *wzTmp = L'\0'; // Find the target location in the cache. dwSize = MAX_PATH; hr = pAsm->GetManifestModulePath(wzAsmCachePath, &dwSize); if (FAILED(hr)) { goto Exit; } wzTmp = PathFindFileName(wzAsmCachePath); ASSERT(wzTmp > (LPWSTR)wzAsmCachePath); StrCpy(wzFileName, wzTmp); *wzTmp = L'\0'; // Copy the manifest PDB. // Hack for now dwSize = MAX_PATH; hr = GetPDBName(wzFileName, wzPDBName, &dwSize); if (FAILED(hr)) { goto Exit; } wnsprintfW(wzPDBSourcePath, MAX_PATH, L"%ws%ws", wzSourcePath, wzPDBName); wnsprintf(wzPDBTargetPath, MAX_PATH, L"%ws%ws", wzAsmCachePath, wzPDBName); if (GetFileAttributes(wzPDBTargetPath) == (DWORD) -1 && lstrcmpiW(wzPDBSourcePath, wzPDBTargetPath)) { CopyFile(wzPDBSourcePath, wzPDBTargetPath, TRUE); } // Copy the module PDBs. dwIdx = 0; while (SUCCEEDED(hr)) { hr = pAsm->GetNextAssemblyModule(dwIdx++, &pModImport); if (SUCCEEDED(hr)) { if (pModImport->IsAvailable()) { dwSize = MAX_PATH; hr = pModImport->GetModulePath(wzModPath, &dwSize); if (FAILED(hr)) { SAFERELEASE(pModImport); goto Exit; } wzModName = PathFindFileName(wzModPath); ASSERT(wzModName); dwSize = MAX_PATH; hr = GetPDBName(wzModName, wzPDBName, &dwSize); if (FAILED(hr)) { SAFERELEASE(pModImport); goto Exit; } wnsprintfW(wzPDBSourcePath, MAX_PATH, L"%ws%ws", wzSourcePath, wzPDBName); wnsprintfW(wzPDBTargetPath, MAX_PATH, L"%ws%ws", wzAsmCachePath, wzPDBName); if (GetFileAttributes(wzPDBTargetPath) == (DWORD) -1 && lstrcmpiW(wzPDBSourcePath, wzPDBTargetPath)) { CopyFile(wzPDBSourcePath, wzPDBTargetPath, TRUE); } } SAFERELEASE(pModImport); } } // Copy complete. Return success. if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) { hr = S_OK; } Exit: SAFERELEASE(pName); SAFEDELETEARRAY(wzCodebase); return hr; }
void AsmMan::EndAssembly() { if(m_pCurAsmRef) { if(m_pCurAsmRef->isRef) { // list the assembly ref if(GetAsmRefByName(m_pCurAsmRef->szAlias)) { //report->warn("Multiple declarations of Assembly Ref '%s', ignored except the 1st one\n",m_pCurAsmRef->szName); delete m_pCurAsmRef; m_pCurAsmRef = NULL; return; } if(m_pCurAsmRef->isAutodetect) { IAssemblyName* pIAsmName; HRESULT hr; // Convert name to Unicode WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf); hr = CreateAssemblyNameObject(&pIAsmName,wzUniBuf,CANOF_PARSE_DISPLAY_NAME,NULL); if(SUCCEEDED(hr)) { // set enumeration criteria: what is known about AsmRef (besides name) if(m_pCurAsmRef->usVerMajor != (USHORT)0xFFFF) pIAsmName->SetProperty(ASM_NAME_MAJOR_VERSION,&(m_pCurAsmRef->usVerMajor),2); if(m_pCurAsmRef->usVerMinor != (USHORT)0xFFFF) pIAsmName->SetProperty(ASM_NAME_MINOR_VERSION,&(m_pCurAsmRef->usVerMinor),2); if(m_pCurAsmRef->usBuild != (USHORT)0xFFFF) pIAsmName->SetProperty(ASM_NAME_BUILD_NUMBER,&(m_pCurAsmRef->usBuild),2); if(m_pCurAsmRef->usRevision != (USHORT)0xFFFF) pIAsmName->SetProperty(ASM_NAME_REVISION_NUMBER,&(m_pCurAsmRef->usRevision),2); if(m_pCurAsmRef->pPublicKeyToken) pIAsmName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, m_pCurAsmRef->pPublicKeyToken->ptr(), m_pCurAsmRef->pPublicKeyToken->length()); if(m_pCurAsmRef->pLocale) pIAsmName->SetProperty(ASM_NAME_CULTURE, m_pCurAsmRef->pLocale->ptr(), m_pCurAsmRef->pLocale->length()); // enumerate assemblies IAssemblyEnum* pIAsmEnum = NULL; hr = CreateAssemblyEnum(&pIAsmEnum, NULL, pIAsmName, ASM_CACHE_GAC, NULL); if(SUCCEEDED(hr)) { IAssemblyName* pIAsmNameFound; IAssemblyName* pIAsmNameLatestVer = NULL; ULONGLONG ullVer=0, ullVerLatest=0; DWORD dwVerHi, dwVerLo; // find the latest and greatest, if any for(;;) { pIAsmNameFound = NULL; hr = pIAsmEnum->GetNextAssembly(NULL,&pIAsmNameFound,0); if(SUCCEEDED(hr) && pIAsmNameFound) { pIAsmNameFound->GetVersion(&dwVerHi,&dwVerLo); ullVer = (ULONGLONG)dwVerHi; ullVer <<= sizeof(DWORD); ullVer |= dwVerLo; if(ullVer > ullVerLatest) { if(pIAsmNameLatestVer) pIAsmNameLatestVer->Release(); ullVerLatest = ullVer; pIAsmNameLatestVer = pIAsmNameFound; } else pIAsmNameFound->Release(); } else break; } // if found, fill the gaps if(pIAsmNameLatestVer) { DWORD cbSize=0; USHORT usDummy=0; if(m_pCurAsmRef->pPublicKeyToken == NULL) { cbSize = 1024; pIAsmNameLatestVer->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, wzUniBuf, &cbSize); if(cbSize) { if((m_pCurAsmRef->pPublicKeyToken = new BinStr())) memcpy(m_pCurAsmRef->pPublicKeyToken->getBuff(cbSize), wzUniBuf, cbSize); } } if(m_pCurAsmRef->usVerMajor == (USHORT)0xFFFF) { cbSize = (DWORD)sizeof(WORD); pIAsmNameLatestVer->GetProperty(ASM_NAME_MAJOR_VERSION, &usDummy, &cbSize); m_pCurAsmRef->usVerMajor = usDummy; } if(m_pCurAsmRef->usVerMinor == (USHORT)0xFFFF) { cbSize = (DWORD)sizeof(WORD); pIAsmNameLatestVer->GetProperty(ASM_NAME_MINOR_VERSION, &usDummy, &cbSize); m_pCurAsmRef->usVerMinor = usDummy; } if(m_pCurAsmRef->usBuild == (USHORT)0xFFFF) { cbSize = (DWORD)sizeof(WORD); pIAsmNameLatestVer->GetProperty(ASM_NAME_BUILD_NUMBER, &usDummy, &cbSize); m_pCurAsmRef->usBuild = usDummy; } if(m_pCurAsmRef->usRevision == (USHORT)0xFFFF) { cbSize = (DWORD)sizeof(WORD); pIAsmNameLatestVer->GetProperty(ASM_NAME_REVISION_NUMBER, &usDummy, &cbSize); m_pCurAsmRef->usRevision = usDummy; } if(m_pCurAsmRef->pLocale == NULL) { cbSize = 1024; pIAsmNameLatestVer->GetProperty(ASM_NAME_CULTURE, wzUniBuf, &cbSize); if(cbSize > (DWORD)sizeof(WCHAR)) { if((m_pCurAsmRef->pLocale = new BinStr())) memcpy(m_pCurAsmRef->pLocale->getBuff(cbSize), wzUniBuf, cbSize); } } pIAsmNameLatestVer->Release(); } else report->warn("Failed to autodetect assembly '%s'\n",m_pCurAsmRef->szName); // if no assembly found, leave it as is, it might be not a GAC assembly pIAsmEnum->Release(); } else report->error("Failed to enum assemblies %S, hr=0x%08X\n",wzUniBuf,hr); pIAsmName->Release(); } else report->error("Failed to create assembly name object for %S, hr=0x%08X\n",wzUniBuf,hr); } // end if isAutodetect m_AsmRefLst.PUSH(m_pCurAsmRef); m_pCurAsmRef->tkTok = TokenFromRid(m_AsmRefLst.COUNT(),mdtAssemblyRef); } else { HRESULT hr = S_OK; m_pCurAsmRef->tkTok = TokenFromRid(1,mdtAssembly); // Determine the strong name public key. This may have been set // via a directive in the source or from the command line (which // overrides the directive). From the command line we may have // been provided with a file or the name of a CAPI key // container. Either may contain a public key or a full key // pair. if (((Assembler*)m_pAssembler)->m_wzKeySourceName) { { // Read public key or key pair from file. HANDLE hFile = WszCreateFile(((Assembler*)m_pAssembler)->m_wzKeySourceName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if(hFile == INVALID_HANDLE_VALUE) { hr = GetLastError(); report->error("Failed to open key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr); m_pCurAsmRef = NULL; return; } // Determine file size and allocate an appropriate buffer. m_sStrongName.m_cbPublicKey = SafeGetFileSize(hFile, NULL); if (m_sStrongName.m_cbPublicKey == 0xffffffff) { report->error("File size too large\n"); m_pCurAsmRef = NULL; CloseHandle(hFile); return; } m_sStrongName.m_pbPublicKey = new BYTE[m_sStrongName.m_cbPublicKey]; if (m_sStrongName.m_pbPublicKey == NULL) { report->error("Failed to allocate key buffer\n"); m_pCurAsmRef = NULL; CloseHandle(hFile); return; } m_sStrongName.m_dwPublicKeyAllocated = 2; // Read the file into the buffer. DWORD dwBytesRead; if (!ReadFile(hFile, m_sStrongName.m_pbPublicKey, m_sStrongName.m_cbPublicKey, &dwBytesRead, NULL)) { hr = GetLastError(); report->error("Failed to read key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr); m_pCurAsmRef = NULL; CloseHandle(hFile); return; } CloseHandle(hFile); // Guess whether we're full or delay signing based on // whether the blob passed to us looks like a public // key. (I.e. we may just have copied a full key pair // into the public key buffer). if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) && (offsetof(PublicKeyBlob, PublicKey) + ((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey) == m_sStrongName.m_cbPublicKey) m_sStrongName.m_fFullSign = FALSE; else m_sStrongName.m_fFullSign = TRUE; // If we really have a key pair, we'll move it into a // key container so the signing code gets the key pair // from a consistent place. if (m_sStrongName.m_fFullSign) { m_sStrongName.m_pbPrivateKey = m_sStrongName.m_pbPublicKey; m_sStrongName.m_cbPrivateKey = m_sStrongName.m_cbPublicKey; m_sStrongName.m_pbPublicKey = NULL; m_sStrongName.m_cbPublicKey = NULL; m_sStrongName.m_dwPublicKeyAllocated = 0; // Retrieve the public key portion as a byte blob. if (!StrongNameGetPublicKey(NULL, m_sStrongName.m_pbPrivateKey, m_sStrongName.m_cbPrivateKey, &m_sStrongName.m_pbPublicKey, &m_sStrongName.m_cbPublicKey)) { hr = StrongNameErrorInfo(); report->error("Failed to extract public key: 0x%08X\n",hr); m_pCurAsmRef = NULL; return; } m_sStrongName.m_dwPublicKeyAllocated = 2; } } } else if (m_pAssembly->pPublicKey) { m_sStrongName.m_pbPublicKey = m_pAssembly->pPublicKey->ptr(); m_sStrongName.m_cbPublicKey = m_pAssembly->pPublicKey->length(); m_sStrongName.m_wzKeyContainer = NULL; m_sStrongName.m_fFullSign = FALSE; m_sStrongName.m_dwPublicKeyAllocated = 0; } else { m_sStrongName.m_pbPublicKey = NULL; m_sStrongName.m_cbPublicKey = 0; m_sStrongName.m_wzKeyContainer = NULL; m_sStrongName.m_fFullSign = FALSE; m_sStrongName.m_dwPublicKeyAllocated = 0; } } m_pCurAsmRef = NULL; } ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP(); }
HRESULT CNodeFactory::ProcessQualifyAssemblyTag(XML_NODE_INFO **aNodeInfo, USHORT cNumRecs) { HRESULT hr = S_OK; USHORT idx = 1; LPWSTR pwzAttributeNS = NULL; LPWSTR pwzPartialName = NULL; LPWSTR pwzFullName = NULL; CQualifyAssembly *pqa = NULL; IAssemblyName *pNameFull = NULL; IAssemblyName *pNamePartial = NULL; IAssemblyName *pNameQualified = NULL; LPWSTR wzCanonicalDisplayName=NULL; ASSERT(aNodeInfo && cNumRecs); while (idx < cNumRecs) { if (aNodeInfo[idx]->dwType == XML_ATTRIBUTE) { // Found an attribute. Find out which one, and extract the data. // Node: ::ExtractXMLAttribute increments idx. hr = ApplyNamespace(aNodeInfo[idx], &pwzAttributeNS, 0); if (FAILED(hr)) { goto Exit; } if (!lstrcmpW(pwzAttributeNS, XML_ATTRIBUTE_PARTIALNAME)) { SAFEDELETEARRAY(pwzAttributeNS); if (pwzPartialName) { // Ignore duplicate attribute idx++; } else { hr = ::ExtractXMLAttribute(&pwzPartialName, aNodeInfo, &idx, cNumRecs); if (FAILED(hr)) { goto Exit; } } } else if (!lstrcmpW(pwzAttributeNS, XML_ATTRIBUTE_FULLNAME)) { SAFEDELETEARRAY(pwzAttributeNS); if (pwzFullName) { // Ignore duplicate attribute idx++; } else { hr = ::ExtractXMLAttribute(&pwzFullName, aNodeInfo, &idx, cNumRecs); if (FAILED(hr)) { goto Exit; } } } else { SAFEDELETEARRAY(pwzAttributeNS); idx++; } } else { idx++; } } if (pwzPartialName && pwzFullName) { DWORD dwSize; DWORD adwProperties[] = { ASM_NAME_NAME, ASM_NAME_MAJOR_VERSION, ASM_NAME_MINOR_VERSION, ASM_NAME_BUILD_NUMBER, ASM_NAME_REVISION_NUMBER, ASM_NAME_CULTURE, ASM_NAME_PUBLIC_KEY_TOKEN }; DWORD adwCmpFlags[] = { ASM_CMPF_NAME, ASM_CMPF_MAJOR_VERSION, ASM_CMPF_MINOR_VERSION, ASM_CMPF_BUILD_NUMBER, ASM_CMPF_REVISION_NUMBER, ASM_CMPF_CULTURE, ASM_CMPF_PUBLIC_KEY_TOKEN }; DWORD dwNumProps = sizeof(adwProperties) / sizeof(adwProperties[0]); if (FAILED(CreateAssemblyNameObject(&pNameFull, pwzFullName, CANOF_PARSE_DISPLAY_NAME, 0))) { goto Exit; } if (FAILED(CreateAssemblyNameObject(&pNamePartial, pwzPartialName, CANOF_PARSE_DISPLAY_NAME, 0))) { goto Exit; } // Check validity of qualification if (CAssemblyName::IsPartial(pNameFull) || !CAssemblyName::IsPartial(pNamePartial)) { goto Exit; } if (FAILED(pNamePartial->Clone(&pNameQualified))) { goto Exit; } for (DWORD i = 0; i < dwNumProps; i++) { dwSize = 0; if (pNamePartial->GetProperty(adwProperties[i], NULL, &dwSize) != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { // Partial on this field. Set pNameQualified's corresponding // property to whatever is in pNameFull. dwSize = 0; pNameFull->GetProperty(adwProperties[i], NULL, &dwSize); if (!dwSize) { goto Exit; } else { BYTE *pBuf; pBuf = NEW(BYTE[dwSize]); if (!pBuf) { hr = E_OUTOFMEMORY; goto Exit; } if (FAILED(pNameFull->GetProperty(adwProperties[i], pBuf, &dwSize))) { SAFEDELETEARRAY(pBuf); goto Exit; } if (FAILED(pNameQualified->SetProperty(adwProperties[i], pBuf, dwSize))) { SAFEDELETEARRAY(pBuf); goto Exit; } SAFEDELETEARRAY(pBuf); } } else { // Full-specified on this field. Make sure it matches the full ref specified. if (pNamePartial->IsEqual(pNameFull, adwCmpFlags[i]) != S_OK) { goto Exit; } } } if (CAssemblyName::IsPartial(pNameQualified)) { goto Exit; } // Get canonical display name format wzCanonicalDisplayName = NEW(WCHAR[MAX_URL_LENGTH+1]); if (!wzCanonicalDisplayName) { hr = E_OUTOFMEMORY; goto Exit; } dwSize = MAX_URL_LENGTH; if (FAILED(pNamePartial->GetDisplayName(wzCanonicalDisplayName, &dwSize, 0))) { goto Exit; } // Add qualified assembly entry to list pqa = new CQualifyAssembly; if (!pqa) { hr = E_OUTOFMEMORY; goto Exit; } pqa->_pwzPartialName = WSTRDupDynamic(wzCanonicalDisplayName); if (!pqa->_pwzPartialName) { hr = E_OUTOFMEMORY; goto Exit; } pqa->_pNameFull = pNameQualified; pNameQualified->AddRef(); _listQualifyAssembly.AddTail(pqa); } Exit: SAFEDELETEARRAY(pwzPartialName); SAFEDELETEARRAY(pwzFullName); SAFERELEASE(pNameFull); SAFERELEASE(pNamePartial); SAFERELEASE(pNameQualified); SAFEDELETEARRAY(wzCanonicalDisplayName); return hr; }