/* Copyright (c) Microsoft Corporation */ #include "stdinc.h" #include "fusionbuffer.h" #include "fusionhash.h" #include "csecuritymetadata.h" #include "strongname.h" #include "hashfile.h" typedef CCaseInsensitiveSimpleUnicodeStringTableIter CFileHashTableIter; // // We should try to remove this. // BOOL CFileInformationTableHelper::UpdateValue( const CMetaDataFileElement &vin, CMetaDataFileElement &stored ) { FN_PROLOG_WIN32 ASSERT( FALSE ); FN_EPILOG } CMetaDataFileElement::CMetaDataFileElement() { } BOOL CMetaDataFileElement::WriteToRegistry( CRegKey & hkThisFileNode ) const { if (SXS_AVOID_WRITING_REGISTRY) return TRUE; FN_PROLOG_WIN32 const CFileHashTable &rfileHashTable = *this; CFileHashTableIter TableIterator( const_cast(rfileHashTable) ); for ( TableIterator.Reset(); TableIterator.More(); TableIterator.Next() ) { const PCWSTR &rcbuffAlgName = TableIterator.GetKey(); const CFusionByteArray &rbbuffHashData = TableIterator.GetValue(); IFW32FALSE_EXIT( hkThisFileNode.SetValue( rcbuffAlgName, REG_BINARY, rbbuffHashData.GetArrayPtr(), rbbuffHashData.GetSize() ) ); } FN_EPILOG } BOOL CMetaDataFileElement::ReadFromRegistry( CRegKey& hkThisFileNode ) { /* Here we take a few shortcuts. We know there is a list of "valid" hash alg name strings, so we only query for them in the registry. If anything else is in there, then too bad for them. */ FN_PROLOG_WIN32 DWORD dwIndex = 0; DWORD dwLastError = 0; CFusionByteArray baHashValue; CSmallStringBuffer buffHashAlgName; IFW32FALSE_EXIT(baHashValue.Win32Initialize()); while ( true ) { BOOL fNoMoreItems = FALSE; buffHashAlgName.Clear(); IFW32FALSE_EXIT( ::SxspEnumKnownHashTypes( dwIndex++, buffHashAlgName, fNoMoreItems ) ); // // There's no more hash types to be enumerated... // if (fNoMoreItems) break; // // Get the hash data out of the registry // IFW32FALSE_EXIT( ::FusionpRegQueryBinaryValueEx( FUSIONP_REG_QUERY_BINARY_NO_FAIL_IF_NON_BINARY, hkThisFileNode, buffHashAlgName, baHashValue, dwLastError, 2, ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND)); // // ISSUE: jonwis 3/12/2002 - Someone could put non-binary data here in the registry // and so we'll fail when we try to compare the hash against what's on the // filesystem. This isn't necessarily bad, since we do compare binary-wise, // but maybe we should validate here to ensure that the type is binary, and // not add the hash data if it isn't. // if (dwLastError == ERROR_SUCCESS) IFW32FALSE_EXIT(this->PutHashData(buffHashAlgName, baHashValue)); } FN_EPILOG } BOOL CMetaDataFileElement::Initialize() { FN_PROLOG_WIN32 IFW32FALSE_EXIT( CFileHashTable::Initialize() ); FN_EPILOG } BOOL CMetaDataFileElement::GetHashDataForKind( IN const ALG_ID aid, OUT CFusionByteArray& arrHashData, OUT BOOL &rfHadSuchData ) const { FN_PROLOG_WIN32 CSmallStringBuffer buffAlgName; IFW32FALSE_EXIT( ::SxspHashStringFromAlg(aid, buffAlgName) ); IFW32FALSE_EXIT( this->GetHashDataForKind( buffAlgName, arrHashData, rfHadSuchData ) ); FN_EPILOG } BOOL CMetaDataFileElement::GetHashDataForKind( IN const CBaseStringBuffer& buffId, OUT CFusionByteArray& arrHashData, OUT BOOL &rfHadSuchData ) const { // NTRAID#NTBUG9 - 556341 - jonwis - 2002/4/25 - Always set the output param FN_PROLOG_WIN32 CFusionByteArray *pFoundData = NULL; rfHadSuchData = FALSE; IFW32FALSE_EXIT( arrHashData.Win32Reset() ); IFW32FALSE_EXIT( this->Find( buffId, pFoundData ) ); if ( pFoundData != NULL ) { IFW32FALSE_EXIT(pFoundData->Win32Clone(arrHashData)); rfHadSuchData = TRUE; } FN_EPILOG } BOOL CMetaDataFileElement::PutHashData( IN const ALG_ID aid, IN const CFusionByteArray& arrHashData ) { FN_PROLOG_WIN32 CSmallStringBuffer buffTempAlgId; IFW32FALSE_EXIT( ::SxspHashStringFromAlg( aid, buffTempAlgId ) ); IFW32FALSE_EXIT( this->PutHashData( buffTempAlgId, arrHashData ) ); FN_EPILOG } BOOL CMetaDataFileElement::PutHashData( IN const CBaseStringBuffer& buffId, IN const CFusionByteArray& arrHashData ) { FN_PROLOG_WIN32 CFusionByteArray *pStoredValue = NULL; BOOL bFound = FALSE; IFW32FALSE_EXIT( this->FindOrInsertIfNotPresent( buffId, arrHashData, &pStoredValue, &bFound ) ); if ( bFound ) { ASSERT( pStoredValue != NULL ); IFW32FALSE_EXIT(arrHashData.Win32Clone(*pStoredValue)); } FN_EPILOG } BOOL CSecurityMetaData::GetFileMetaData( const CBaseStringBuffer& buffFileName, const CMetaDataFileElement* &pElementData ) const { FN_PROLOG_WIN32 IFW32FALSE_EXIT( m_fitFileDataTable.Find(buffFileName, pElementData) ); FN_EPILOG } BOOL CSecurityMetaData::Initialize() { FN_PROLOG_WIN32 IFW32FALSE_EXIT(m_cilCodebases.Win32Initialize()); IFW32FALSE_EXIT(m_baSignerPublicKeyToken.Win32Initialize()); IFW32FALSE_EXIT(m_baManifestSha1Hash.Win32Initialize()); IFW32FALSE_EXIT(m_fitFileDataTable.Initialize()); m_buffShortNameOnDisk.Clear(); m_buffShortCatalogName.Clear(); m_buffShortManifestName.Clear(); FN_EPILOG } BOOL CSecurityMetaData::Initialize( const CSecurityMetaData &other ) { FN_PROLOG_WIN32 // // ISSUE: jonwis 3/12/2002 - Ick. Use 'Win32Assign' to assign from one string to another... Don't // bother doing the cast operator and calling Cch! // - PS: This style of doing copying is gross... either make it so that it only takes the // name of the thing to copy, or do the verbose thing of IFW32FALSE_EXIT(...). // #define CLONEFUSIONARRAY( src, dst ) IFW32FALSE_EXIT( (src).Win32Clone( dst ) ) #define CLONESTRING( dst, src ) IFW32FALSE_EXIT( (dst).Win32Assign( (src), (src).Cch() ) ) IFW32FALSE_EXIT( this->Initialize() ); CLONEFUSIONARRAY(other.m_cilCodebases, this->m_cilCodebases); CLONEFUSIONARRAY(other.m_baSignerPublicKeyToken, this->m_baSignerPublicKeyToken); CLONEFUSIONARRAY(other.m_baManifestSha1Hash, this->m_baManifestSha1Hash); CLONESTRING(this->m_buffShortNameOnDisk, other.m_buffShortNameOnDisk); CLONESTRING(this->m_buffTextualAssemblyIdentity, other.m_buffTextualAssemblyIdentity); CLONESTRING(this->m_buffShortManifestName, other.m_buffShortManifestName); CLONESTRING(this->m_buffShortCatalogName, other.m_buffShortCatalogName); // // Copy file information table over // { CFileInformationTableIter Iter(const_cast(other.m_fitFileDataTable)); for (Iter.Reset(); Iter.More(); Iter.Next()) IFW32FALSE_EXIT( this->m_fitFileDataTable.Insert( Iter.GetKey(), Iter.GetValue() ) ); } FN_EPILOG } BOOL CSecurityMetaData::AddFileMetaData( const CBaseStringBuffer &rbuffFileName, CMetaDataFileElement &rElementData, CSecurityMetaData::FileAdditionDisposition dispHowToAdd ) { FN_PROLOG_WIN32 if (dispHowToAdd == CSecurityMetaData::eFailIfAlreadyExists) { IFW32FALSE_EXIT(m_fitFileDataTable.Insert(rbuffFileName, rElementData)); } else if (dispHowToAdd == CSecurityMetaData::eReplaceIfAlreadyExists) { bool fAlreadyExists = false; IFW32FALSE_EXIT_UNLESS( m_fitFileDataTable.Insert(rbuffFileName, rElementData), (::FusionpGetLastWin32Error() == ERROR_ALREADY_EXISTS), fAlreadyExists); if (fAlreadyExists) { IFW32FALSE_EXIT(m_fitFileDataTable.Remove(rbuffFileName)); IFW32FALSE_EXIT(m_fitFileDataTable.Insert(rbuffFileName, rElementData)); } } else if (dispHowToAdd == CSecurityMetaData::eMergeIfAlreadyExists) { IFW32FALSE_EXIT( m_fitFileDataTable.InsertOrUpdateIf( rbuffFileName, rElementData, this, &CSecurityMetaData::MergeFileDataElement)); } FN_EPILOG } BOOL CSecurityMetaData::SetSignerPublicKeyTokenBits( const CFusionByteArray & rcbuffSignerPublicKeyBits ) { FN_PROLOG_WIN32 IFW32FALSE_EXIT(rcbuffSignerPublicKeyBits.Win32Clone(this->m_baSignerPublicKeyToken)); FN_EPILOG } // // ISSUE: jonwis 3/12/2002 - Performance here sucks. We should look in the file table and get // the one that's already present rather than doing a merge... Mostly we're wasting stack, // but I'm sure we'd gain something in perf as well. // BOOL CSecurityMetaData::QuickAddFileHash( const CBaseStringBuffer &rcbuffFileName, ALG_ID aidHashAlg, const CBaseStringBuffer &rcbuffHashValue ) { FN_PROLOG_WIN32 CMetaDataFileElement Element; CFusionByteArray baHashBytes; // // Build the element // IFW32FALSE_EXIT(Element.Initialize()); IFW32FALSE_EXIT(::SxspHashStringToBytes(rcbuffHashValue, rcbuffHashValue.Cch(), baHashBytes)); IFW32FALSE_EXIT(Element.PutHashData(aidHashAlg, baHashBytes)); // // And merge it in // IFW32FALSE_EXIT( this->AddFileMetaData( rcbuffFileName, Element, eMergeIfAlreadyExists)); FN_EPILOG } BOOL CSecurityMetaData::WritePrimaryAssemblyInfoIntoRegistryKey( ULONG Flags, const CRegKey &rhkRegistryNode ) const { if (SXS_AVOID_WRITING_REGISTRY) return TRUE; FN_PROLOG_WIN32 // // ISSUE: jonwis 3/12/2002 - Consider moving hkCodebases into the scope in which // it belongs, and putting the FusionDbgPrintEx's under DBG. // CRegKey hkFilesKey; CRegKey hkCodebases; ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_INSTALLATION, "SXS: %s - starting\n", __FUNCTION__); PARAMETER_CHECK((Flags & ~(SXSP_WRITE_PRIMARY_ASSEMBLY_INFO_INTO_REGISTRY_KEY_FLAG_REFRESH)) == 0); IFW32FALSE_EXIT( rhkRegistryNode.SetValue( CSMD_TOPLEVEL_IDENTITY, this->GetTextualIdentity())); IFW32FALSE_EXIT( rhkRegistryNode.SetValue( CSMD_TOPLEVEL_CATALOG, static_cast(1))); IFW32FALSE_EXIT( rhkRegistryNode.SetValue( CSMD_TOPLEVEL_MANIFESTHASH, REG_BINARY, this->m_baManifestSha1Hash.GetArrayPtr(), this->m_baManifestSha1Hash.GetSize() ) ); IFW32FALSE_EXIT( rhkRegistryNode.OpenOrCreateSubKey( hkFilesKey, CSMD_TOPLEVEL_FILES, KEY_WRITE)); IFW32FALSE_EXIT(this->WriteFilesIntoKey(hkFilesKey)); // // Write keys into this codebase node // if ((Flags & SXSP_WRITE_PRIMARY_ASSEMBLY_INFO_INTO_REGISTRY_KEY_FLAG_REFRESH) == 0) { IFW32FALSE_EXIT( rhkRegistryNode.OpenOrCreateSubKey( hkCodebases, CSMD_TOPLEVEL_CODEBASES, KEY_WRITE)); for (ULONG ulI = 0; ulI < this->m_cilCodebases.GetSize(); ulI++) { CRegKey hkSingleCodebaseKey; const CCodebaseInformation &rcCodebase = m_cilCodebases[ulI]; // Don't attempt to write blank (Darwin) referenced codebases to the // registry. if ( rcCodebase.GetReference().Cch() == 0 ) continue; IFW32FALSE_EXIT( hkCodebases.OpenOrCreateSubKey( hkSingleCodebaseKey, rcCodebase.GetReference(), KEY_WRITE)); IFW32FALSE_EXIT(rcCodebase.WriteToRegistryKey(hkSingleCodebaseKey)); } } #if DBG else { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_WFP | FUSION_DBG_LEVEL_INSTALLATION, "SXS.DLL: %s - recovery, not writing codebase and codebase prompt\n", __FUNCTION__); } #endif FN_EPILOG } BOOL CSecurityMetaData::WriteSecondaryAssemblyInfoIntoRegistryKey( const CRegKey &rhkRegistryNode ) const { if (SXS_AVOID_WRITING_REGISTRY) return TRUE; FN_PROLOG_WIN32 IFW32FALSE_EXIT(rhkRegistryNode.SetValue(CSMD_TOPLEVEL_SHORTNAME, this->GetInstalledDirShortName())); IFW32FALSE_EXIT(rhkRegistryNode.SetValue(CSMD_TOPLEVEL_SHORTCATALOG, this->GetShortCatalogPath())); IFW32FALSE_EXIT(rhkRegistryNode.SetValue(CSMD_TOPLEVEL_SHORTMANIFEST, this->GetShortManifestPath())); IFW32FALSE_EXIT( rhkRegistryNode.SetValue( CSMD_TOPLEVEL_PUBLIC_KEY_TOKEN, REG_BINARY, this->m_baSignerPublicKeyToken.GetArrayPtr(), this->m_baSignerPublicKeyToken.GetSize())); FN_EPILOG } BOOL CSecurityMetaData::WriteFilesIntoKey( CRegKey & rhkFilesKey ) const { if (SXS_AVOID_WRITING_REGISTRY) return TRUE; FN_PROLOG_WIN32 CFileInformationTableIter FilesIterator( const_cast(m_fitFileDataTable) ); ULONG uliIndex = 0; for ( FilesIterator.Reset(); FilesIterator.More(); FilesIterator.Next() ) { const PCWSTR pcwszFileName = FilesIterator.GetKey(); const CMetaDataFileElement& rcmdfeFileData = FilesIterator.GetValue(); CRegKey hkFileSubKey; CSmallStringBuffer buffKeySubname; // // The trick here is that you can't simply create the subkey off this node, // as it might be "foo\bar\bas\zip.ding". // IFW32FALSE_EXIT( buffKeySubname.Win32Format( L"%ld", uliIndex++ ) ); IFW32FALSE_EXIT( rhkFilesKey.OpenOrCreateSubKey( hkFileSubKey, buffKeySubname, KEY_ALL_ACCESS ) ); // // So instead, we set the default value of the key to be the name of the file. // IFW32FALSE_EXIT( buffKeySubname.Win32Assign( pcwszFileName, lstrlenW(pcwszFileName) ) ); IFW32FALSE_EXIT( hkFileSubKey.SetValue( NULL, buffKeySubname ) ); IFW32FALSE_EXIT( rcmdfeFileData.WriteToRegistry( hkFileSubKey ) ); } FN_EPILOG } /* [name of full assembly] v : Codebase = [meta-url] v : Catalog = 1 v : Shortname = [shortname generated during installation] v : ManifestHash = [...] v : PublicKeyToken = [...] k : Files k : [Filename] v : SHA1 = [...] v : MD5 = [...] k : [Filename] ... k : Codebases k : [reference-string] v : PromptString = [...] v : Url = [meta-url] */ BOOL CSecurityMetaData::LoadFromRegistryKey( const CRegKey &rhkRegistryNode ) { FN_PROLOG_WIN32 CRegKey hkTempStuff; DWORD dwHasCatalog = 0; IFW32FALSE_EXIT( ::FusionpRegQueryDwordValueEx( 0, rhkRegistryNode, CSMD_TOPLEVEL_CATALOG, &dwHasCatalog, 0)); // NTRAID#NTBUG9 - 556327 - jonwis - 2002/04/25 - Remove this assert, make it deal better with zero values ASSERT(dwHasCatalog != 0); IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING, rhkRegistryNode, CSMD_TOPLEVEL_IDENTITY, this->m_buffTextualAssemblyIdentity)); IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING, rhkRegistryNode, CSMD_TOPLEVEL_SHORTNAME, this->m_buffShortNameOnDisk)); IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING, rhkRegistryNode, CSMD_TOPLEVEL_SHORTCATALOG, this->m_buffShortCatalogName)); IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING, rhkRegistryNode, CSMD_TOPLEVEL_SHORTMANIFEST, this->m_buffShortManifestName)); IFW32FALSE_EXIT( ::FusionpRegQueryBinaryValueEx( 0, rhkRegistryNode, CSMD_TOPLEVEL_MANIFESTHASH, this->m_baManifestSha1Hash)); IFW32FALSE_EXIT( ::FusionpRegQueryBinaryValueEx( 0, rhkRegistryNode, CSMD_TOPLEVEL_PUBLIC_KEY_TOKEN, this->m_baSignerPublicKeyToken)); IFW32FALSE_EXIT(rhkRegistryNode.OpenSubKey(hkTempStuff, CSMD_TOPLEVEL_CODEBASES, KEY_READ)); if (hkTempStuff != CRegKey::GetInvalidValue()) { IFW32FALSE_EXIT(this->LoadCodebasesFromKey(hkTempStuff)); IFW32FALSE_EXIT(hkTempStuff.Win32Close()); } IFW32FALSE_EXIT( rhkRegistryNode.OpenSubKey(hkTempStuff, CSMD_TOPLEVEL_FILES, KEY_READ)); if (hkTempStuff != CRegKey::GetInvalidValue()) { IFW32FALSE_EXIT(this->LoadFilesFromKey(hkTempStuff)); IFW32FALSE_EXIT(hkTempStuff.Win32Close()); } FN_EPILOG } BOOL CSecurityMetaData::LoadFilesFromKey( CRegKey &hkTopLevelFileKey ) { FN_PROLOG_WIN32 CSmallStringBuffer buffNextKeyName; DWORD dwIndex = 0; while ( true ) { BOOL fNoMoreItems = FALSE; CRegKey hkIterator; buffNextKeyName.Clear(); IFW32FALSE_EXIT(hkTopLevelFileKey.EnumKey( dwIndex++, buffNextKeyName, NULL, &fNoMoreItems ) ); if ( fNoMoreItems ) { break; } IFW32FALSE_EXIT( hkTopLevelFileKey.OpenSubKey( hkIterator, buffNextKeyName, KEY_READ ) ); if ( hkIterator != CRegKey::GetInvalidValue() ) { CMetaDataFileElement SingleFileElement; IFW32FALSE_EXIT( SingleFileElement.Initialize() ); IFW32FALSE_EXIT( SingleFileElement.ReadFromRegistry( hkIterator ) ); // // Now read the name of the file from the default // IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( 0, hkIterator, NULL, buffNextKeyName)); IFW32FALSE_EXIT(this->AddFileMetaData( buffNextKeyName, SingleFileElement)); } } FN_EPILOG } class CSecurityMetaDataLoadCodebasesFromKeyLocals { public: CStringBuffer buffKeyNameTemp; CCodebaseInformation Codebase; }; BOOL CSecurityMetaData::LoadCodebasesFromKey( IN CRegKey& hkCodebaseSubkey ) { FN_PROLOG_WIN32 DWORD dwMaxKeyLength = 0; DWORD dwNextIndex = 0; CSmartPtr Locals; IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__)); CStringBuffer &buffKeyNameTemp = Locals->buffKeyNameTemp; // // Find out how big the largest subkey string is, then reset our iterator temp // to be that big. // IFW32FALSE_EXIT(hkCodebaseSubkey.LargestSubItemLengths(&dwMaxKeyLength, NULL)); IFW32FALSE_EXIT(buffKeyNameTemp.Win32ResizeBuffer(dwMaxKeyLength + 1, eDoNotPreserveBufferContents)); // // Codebases are stored as subkeys and then values under them. // for (;;) { BOOL fNoMoreItems = FALSE; IFW32FALSE_EXIT( hkCodebaseSubkey.EnumKey( dwNextIndex++, buffKeyNameTemp, NULL, &fNoMoreItems)); if (fNoMoreItems) break; CRegKey hkSingleCodebaseKey; IFW32FALSE_EXIT( hkCodebaseSubkey.OpenSubKey( hkSingleCodebaseKey, buffKeyNameTemp, KEY_READ)); if (hkSingleCodebaseKey == CRegKey::GetInvalidValue()) continue; CCodebaseInformation &Codebase = Locals->Codebase; IFW32FALSE_EXIT(Codebase.Initialize()); IFW32FALSE_EXIT(Codebase.SetReference(buffKeyNameTemp)); #if DBG ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_INSTALLATION, "SXS: %s - read codebase %ls %ls\n", __FUNCTION__, static_cast(buffKeyNameTemp), static_cast(Codebase.GetCodebase()) ); #endif IFW32FALSE_EXIT(Codebase.ReadFromRegistryKey(hkSingleCodebaseKey)); IFW32FALSE_EXIT(this->m_cilCodebases.Win32Append(Codebase)); } FN_EPILOG } BOOL CMetaDataFileElement::Initialize( const CMetaDataFileElement &other ) { FN_PROLOG_WIN32 // The lack of a const iterator here is disturbing, so I have to const_cast // the metadatafileelement CFileHashTableIter InputTableIter( const_cast(other) ); // // Why is this not a bool?? // this->ClearNoCallback(); for(InputTableIter.Reset(); InputTableIter.More(); InputTableIter.Next()) { IFW32FALSE_EXIT( this->Insert( InputTableIter.GetKey(), InputTableIter.GetValue() ) ); } FN_EPILOG } BOOL CCodebaseInformation::Initialize() { this->m_Codebase.Clear(); this->m_PromptText.Clear(); this->m_Reference.Clear(); this->m_Type = CODEBASE_RESOLVED_URLHEAD_UNKNOWN; return TRUE; } BOOL CCodebaseInformation::Initialize( const CCodebaseInformation &other ) { FN_PROLOG_WIN32 IFW32FALSE_EXIT(this->SetCodebase(other.GetCodebase())); IFW32FALSE_EXIT(this->SetPromptText(other.GetPromptText())); IFW32FALSE_EXIT(this->SetReference(other.GetReference())); this->m_Type = other.m_Type; FN_EPILOG } BOOL CCodebaseInformation::WriteToRegistryKey( const CRegKey &rhkCodebaseKey ) const { if (SXS_AVOID_WRITING_REGISTRY) return TRUE; FN_PROLOG_WIN32 if (m_PromptText.Cch() != 0) { IFW32FALSE_EXIT( rhkCodebaseKey.SetValue( CSMD_CODEBASES_PROMPTSTRING, this->m_PromptText)); } IFW32FALSE_EXIT( rhkCodebaseKey.SetValue( CSMD_CODEBASES_URL, this->m_Codebase)); FN_EPILOG } BOOL CCodebaseInformation::ReadFromRegistryKey( const CRegKey &rhkSingleCodebaseKey ) { FN_PROLOG_WIN32 // // Missing prompt is OK // IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING, rhkSingleCodebaseKey, CSMD_CODEBASES_PROMPTSTRING, m_PromptText)); // // We don't want to fail just because someone messed up the registry... // IFW32FALSE_EXIT( ::FusionpRegQuerySzValueEx( FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING, rhkSingleCodebaseKey, CSMD_CODEBASES_URL, m_Codebase)); FN_EPILOG } BOOL CCodebaseInformationList::FindCodebase( const CBaseStringBuffer &rbuffReference, CCodebaseInformation *&rpCodebaseInformation ) { FN_PROLOG_WIN32 bool fMatches = false; SIZE_T i = 0; rpCodebaseInformation = NULL; for (i=0; i < m_cElements; i++) { IFW32FALSE_EXIT(m_prgtElements[i].GetReference().Win32Equals(rbuffReference, fMatches, true)); if (fMatches) break; } if (fMatches) { INTERNAL_ERROR_CHECK(i < m_cElements); rpCodebaseInformation = &m_prgtElements[i]; } FN_EPILOG } BOOL CCodebaseInformationList::RemoveCodebase( const CBaseStringBuffer &rbuffReference, bool &rfRemoved ) { FN_PROLOG_WIN32 bool fMatches = false; SIZE_T i = 0; rfRemoved = false; if (SXS_AVOID_WRITING_REGISTRY) return TRUE; for (i=0; i < m_cElements; i++) { IFW32FALSE_EXIT(m_prgtElements[i].GetReference().Win32Equals(rbuffReference, fMatches, true)); if (fMatches) { IFW32FALSE_EXIT(this->Win32Remove(i)); rfRemoved = true; break; } } FN_EPILOG } BOOL SxspValidateAllFileHashes( IN const CMetaDataFileElement &rmdfeElement, IN const CBaseStringBuffer &rbuffFileName, OUT HashValidateResult &rResult ) { FN_PROLOG_WIN32 DWORD dwIndex = 0; CSmallStringBuffer buffHashName; BOOL fAllHashesMatch = TRUE; CFusionByteArray baFileHashData; rResult = HashValidate_OtherProblems; while ( true && fAllHashesMatch ) { BOOL fTemp; ALG_ID aid = 0; HashValidateResult Results = HashValidate_OtherProblems; IFW32FALSE_EXIT( ::SxspEnumKnownHashTypes( dwIndex++, buffHashName, fTemp)); if (fTemp) break; IFW32FALSE_EXIT( SxspHashAlgFromString( buffHashName, aid ) ); // // Did the file element have this type of hash data in it? // IFW32FALSE_EXIT( rmdfeElement.GetHashDataForKind( buffHashName, baFileHashData, fTemp )); if ( !fTemp ) { continue; } IFW32FALSE_EXIT( ::SxspVerifyFileHash( SVFH_RETRY_LOGIC_SIMPLE, rbuffFileName, baFileHashData, aid, Results ) ); if ( Results != HashValidate_Matches ) { fAllHashesMatch = FALSE; } } if ( fAllHashesMatch ) { rResult = HashValidate_Matches; } FN_EPILOG } BOOL CSecurityMetaData::RemoveCodebase( const CBaseStringBuffer &rbuffReference, bool &rfRemoved ) { if (SXS_AVOID_WRITING_REGISTRY) return TRUE; return m_cilCodebases.RemoveCodebase(rbuffReference, rfRemoved); }