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.

1020 lines
26 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation
  3. */
  4. #include "stdinc.h"
  5. #include "fusionbuffer.h"
  6. #include "fusionhash.h"
  7. #include "csecuritymetadata.h"
  8. #include "strongname.h"
  9. #include "hashfile.h"
  10. typedef CCaseInsensitiveSimpleUnicodeStringTableIter<CFusionByteArray, CFileHashTableHelper> CFileHashTableIter;
  11. //
  12. // We should try to remove this.
  13. //
  14. BOOL
  15. CFileInformationTableHelper::UpdateValue(
  16. const CMetaDataFileElement &vin,
  17. CMetaDataFileElement &stored
  18. )
  19. {
  20. FN_PROLOG_WIN32
  21. ASSERT( FALSE );
  22. FN_EPILOG
  23. }
  24. CMetaDataFileElement::CMetaDataFileElement()
  25. {
  26. }
  27. BOOL
  28. CMetaDataFileElement::WriteToRegistry( CRegKey & hkThisFileNode ) const
  29. {
  30. if (SXS_AVOID_WRITING_REGISTRY)
  31. return TRUE;
  32. FN_PROLOG_WIN32
  33. const CFileHashTable &rfileHashTable = *this;
  34. CFileHashTableIter TableIterator( const_cast<CFileHashTable&>(rfileHashTable) );
  35. for ( TableIterator.Reset(); TableIterator.More(); TableIterator.Next() )
  36. {
  37. const PCWSTR &rcbuffAlgName = TableIterator.GetKey();
  38. const CFusionByteArray &rbbuffHashData = TableIterator.GetValue();
  39. IFW32FALSE_EXIT( hkThisFileNode.SetValue(
  40. rcbuffAlgName,
  41. REG_BINARY,
  42. rbbuffHashData.GetArrayPtr(),
  43. rbbuffHashData.GetSize() ) );
  44. }
  45. FN_EPILOG
  46. }
  47. BOOL
  48. CMetaDataFileElement::ReadFromRegistry(
  49. CRegKey& hkThisFileNode
  50. )
  51. {
  52. /*
  53. Here we take a few shortcuts. We know there is a list of "valid" hash
  54. alg name strings, so we only query for them in the registry. If anything
  55. else is in there, then too bad for them.
  56. */
  57. FN_PROLOG_WIN32
  58. DWORD dwIndex = 0;
  59. DWORD dwLastError = 0;
  60. CFusionByteArray baHashValue;
  61. CSmallStringBuffer buffHashAlgName;
  62. IFW32FALSE_EXIT(baHashValue.Win32Initialize());
  63. while ( true )
  64. {
  65. BOOL fNoMoreItems = FALSE;
  66. buffHashAlgName.Clear();
  67. IFW32FALSE_EXIT( ::SxspEnumKnownHashTypes( dwIndex++, buffHashAlgName, fNoMoreItems ) );
  68. //
  69. // There's no more hash types to be enumerated...
  70. //
  71. if (fNoMoreItems)
  72. break;
  73. //
  74. // Get the hash data out of the registry
  75. //
  76. IFW32FALSE_EXIT(
  77. ::FusionpRegQueryBinaryValueEx(
  78. FUSIONP_REG_QUERY_BINARY_NO_FAIL_IF_NON_BINARY,
  79. hkThisFileNode,
  80. buffHashAlgName,
  81. baHashValue,
  82. dwLastError,
  83. 2,
  84. ERROR_PATH_NOT_FOUND,
  85. ERROR_FILE_NOT_FOUND));
  86. //
  87. // ISSUE: jonwis 3/12/2002 - Someone could put non-binary data here in the registry
  88. // and so we'll fail when we try to compare the hash against what's on the
  89. // filesystem. This isn't necessarily bad, since we do compare binary-wise,
  90. // but maybe we should validate here to ensure that the type is binary, and
  91. // not add the hash data if it isn't.
  92. //
  93. if (dwLastError == ERROR_SUCCESS)
  94. IFW32FALSE_EXIT(this->PutHashData(buffHashAlgName, baHashValue));
  95. }
  96. FN_EPILOG
  97. }
  98. BOOL
  99. CMetaDataFileElement::Initialize()
  100. {
  101. FN_PROLOG_WIN32
  102. IFW32FALSE_EXIT( CFileHashTable::Initialize() );
  103. FN_EPILOG
  104. }
  105. BOOL
  106. CMetaDataFileElement::GetHashDataForKind(
  107. IN const ALG_ID aid,
  108. OUT CFusionByteArray& arrHashData,
  109. OUT BOOL &rfHadSuchData
  110. ) const
  111. {
  112. FN_PROLOG_WIN32
  113. CSmallStringBuffer buffAlgName;
  114. IFW32FALSE_EXIT( ::SxspHashStringFromAlg(aid, buffAlgName) );
  115. IFW32FALSE_EXIT( this->GetHashDataForKind( buffAlgName, arrHashData, rfHadSuchData ) );
  116. FN_EPILOG
  117. }
  118. BOOL
  119. CMetaDataFileElement::GetHashDataForKind(
  120. IN const CBaseStringBuffer& buffId,
  121. OUT CFusionByteArray& arrHashData,
  122. OUT BOOL &rfHadSuchData
  123. ) const
  124. {
  125. // NTRAID#NTBUG9 - 556341 - jonwis - 2002/4/25 - Always set the output param
  126. FN_PROLOG_WIN32
  127. CFusionByteArray *pFoundData = NULL;
  128. rfHadSuchData = FALSE;
  129. IFW32FALSE_EXIT( arrHashData.Win32Reset() );
  130. IFW32FALSE_EXIT( this->Find( buffId, pFoundData ) );
  131. if ( pFoundData != NULL )
  132. {
  133. IFW32FALSE_EXIT(pFoundData->Win32Clone(arrHashData));
  134. rfHadSuchData = TRUE;
  135. }
  136. FN_EPILOG
  137. }
  138. BOOL
  139. CMetaDataFileElement::PutHashData(
  140. IN const ALG_ID aid,
  141. IN const CFusionByteArray& arrHashData
  142. )
  143. {
  144. FN_PROLOG_WIN32
  145. CSmallStringBuffer buffTempAlgId;
  146. IFW32FALSE_EXIT( ::SxspHashStringFromAlg( aid, buffTempAlgId ) );
  147. IFW32FALSE_EXIT( this->PutHashData( buffTempAlgId, arrHashData ) );
  148. FN_EPILOG
  149. }
  150. BOOL
  151. CMetaDataFileElement::PutHashData(
  152. IN const CBaseStringBuffer& buffId,
  153. IN const CFusionByteArray& arrHashData
  154. )
  155. {
  156. FN_PROLOG_WIN32
  157. CFusionByteArray *pStoredValue = NULL;
  158. BOOL bFound = FALSE;
  159. IFW32FALSE_EXIT( this->FindOrInsertIfNotPresent(
  160. buffId,
  161. arrHashData,
  162. &pStoredValue,
  163. &bFound ) );
  164. if ( bFound )
  165. {
  166. ASSERT( pStoredValue != NULL );
  167. IFW32FALSE_EXIT(arrHashData.Win32Clone(*pStoredValue));
  168. }
  169. FN_EPILOG
  170. }
  171. BOOL
  172. CSecurityMetaData::GetFileMetaData(
  173. const CBaseStringBuffer& buffFileName,
  174. const CMetaDataFileElement* &pElementData
  175. ) const
  176. {
  177. FN_PROLOG_WIN32
  178. IFW32FALSE_EXIT( m_fitFileDataTable.Find(buffFileName, pElementData) );
  179. FN_EPILOG
  180. }
  181. BOOL
  182. CSecurityMetaData::Initialize()
  183. {
  184. FN_PROLOG_WIN32
  185. IFW32FALSE_EXIT(m_cilCodebases.Win32Initialize());
  186. IFW32FALSE_EXIT(m_baSignerPublicKeyToken.Win32Initialize());
  187. IFW32FALSE_EXIT(m_baManifestSha1Hash.Win32Initialize());
  188. IFW32FALSE_EXIT(m_fitFileDataTable.Initialize());
  189. m_buffShortNameOnDisk.Clear();
  190. m_buffShortCatalogName.Clear();
  191. m_buffShortManifestName.Clear();
  192. FN_EPILOG
  193. }
  194. BOOL
  195. CSecurityMetaData::Initialize(
  196. const CSecurityMetaData &other
  197. )
  198. {
  199. FN_PROLOG_WIN32
  200. //
  201. // ISSUE: jonwis 3/12/2002 - Ick. Use 'Win32Assign' to assign from one string to another... Don't
  202. // bother doing the cast operator and calling Cch!
  203. // - PS: This style of doing copying is gross... either make it so that it only takes the
  204. // name of the thing to copy, or do the verbose thing of IFW32FALSE_EXIT(...).
  205. //
  206. #define CLONEFUSIONARRAY( src, dst ) IFW32FALSE_EXIT( (src).Win32Clone( dst ) )
  207. #define CLONESTRING( dst, src ) IFW32FALSE_EXIT( (dst).Win32Assign( (src), (src).Cch() ) )
  208. IFW32FALSE_EXIT( this->Initialize() );
  209. CLONEFUSIONARRAY(other.m_cilCodebases, this->m_cilCodebases);
  210. CLONEFUSIONARRAY(other.m_baSignerPublicKeyToken, this->m_baSignerPublicKeyToken);
  211. CLONEFUSIONARRAY(other.m_baManifestSha1Hash, this->m_baManifestSha1Hash);
  212. CLONESTRING(this->m_buffShortNameOnDisk, other.m_buffShortNameOnDisk);
  213. CLONESTRING(this->m_buffTextualAssemblyIdentity, other.m_buffTextualAssemblyIdentity);
  214. CLONESTRING(this->m_buffShortManifestName, other.m_buffShortManifestName);
  215. CLONESTRING(this->m_buffShortCatalogName, other.m_buffShortCatalogName);
  216. //
  217. // Copy file information table over
  218. //
  219. {
  220. CFileInformationTableIter Iter(const_cast<CFileInformationTable&>(other.m_fitFileDataTable));
  221. for (Iter.Reset(); Iter.More(); Iter.Next())
  222. IFW32FALSE_EXIT( this->m_fitFileDataTable.Insert( Iter.GetKey(), Iter.GetValue() ) );
  223. }
  224. FN_EPILOG
  225. }
  226. BOOL
  227. CSecurityMetaData::AddFileMetaData(
  228. const CBaseStringBuffer &rbuffFileName,
  229. CMetaDataFileElement &rElementData,
  230. CSecurityMetaData::FileAdditionDisposition dispHowToAdd
  231. )
  232. {
  233. FN_PROLOG_WIN32
  234. if (dispHowToAdd == CSecurityMetaData::eFailIfAlreadyExists)
  235. {
  236. IFW32FALSE_EXIT(m_fitFileDataTable.Insert(rbuffFileName, rElementData));
  237. }
  238. else if (dispHowToAdd == CSecurityMetaData::eReplaceIfAlreadyExists)
  239. {
  240. bool fAlreadyExists = false;
  241. IFW32FALSE_EXIT_UNLESS(
  242. m_fitFileDataTable.Insert(rbuffFileName, rElementData),
  243. (::FusionpGetLastWin32Error() == ERROR_ALREADY_EXISTS),
  244. fAlreadyExists);
  245. if (fAlreadyExists)
  246. {
  247. IFW32FALSE_EXIT(m_fitFileDataTable.Remove(rbuffFileName));
  248. IFW32FALSE_EXIT(m_fitFileDataTable.Insert(rbuffFileName, rElementData));
  249. }
  250. }
  251. else if (dispHowToAdd == CSecurityMetaData::eMergeIfAlreadyExists)
  252. {
  253. IFW32FALSE_EXIT(
  254. m_fitFileDataTable.InsertOrUpdateIf<CSecurityMetaData>(
  255. rbuffFileName,
  256. rElementData,
  257. this,
  258. &CSecurityMetaData::MergeFileDataElement));
  259. }
  260. FN_EPILOG
  261. }
  262. BOOL
  263. CSecurityMetaData::SetSignerPublicKeyTokenBits(
  264. const CFusionByteArray & rcbuffSignerPublicKeyBits
  265. )
  266. {
  267. FN_PROLOG_WIN32
  268. IFW32FALSE_EXIT(rcbuffSignerPublicKeyBits.Win32Clone(this->m_baSignerPublicKeyToken));
  269. FN_EPILOG
  270. }
  271. //
  272. // ISSUE: jonwis 3/12/2002 - Performance here sucks. We should look in the file table and get
  273. // the one that's already present rather than doing a merge... Mostly we're wasting stack,
  274. // but I'm sure we'd gain something in perf as well.
  275. //
  276. BOOL
  277. CSecurityMetaData::QuickAddFileHash(
  278. const CBaseStringBuffer &rcbuffFileName,
  279. ALG_ID aidHashAlg,
  280. const CBaseStringBuffer &rcbuffHashValue
  281. )
  282. {
  283. FN_PROLOG_WIN32
  284. CMetaDataFileElement Element;
  285. CFusionByteArray baHashBytes;
  286. //
  287. // Build the element
  288. //
  289. IFW32FALSE_EXIT(Element.Initialize());
  290. IFW32FALSE_EXIT(::SxspHashStringToBytes(rcbuffHashValue, rcbuffHashValue.Cch(), baHashBytes));
  291. IFW32FALSE_EXIT(Element.PutHashData(aidHashAlg, baHashBytes));
  292. //
  293. // And merge it in
  294. //
  295. IFW32FALSE_EXIT(
  296. this->AddFileMetaData(
  297. rcbuffFileName,
  298. Element,
  299. eMergeIfAlreadyExists));
  300. FN_EPILOG
  301. }
  302. BOOL
  303. CSecurityMetaData::WritePrimaryAssemblyInfoIntoRegistryKey(
  304. ULONG Flags,
  305. const CRegKey &rhkRegistryNode
  306. ) const
  307. {
  308. if (SXS_AVOID_WRITING_REGISTRY)
  309. return TRUE;
  310. FN_PROLOG_WIN32
  311. //
  312. // ISSUE: jonwis 3/12/2002 - Consider moving hkCodebases into the scope in which
  313. // it belongs, and putting the FusionDbgPrintEx's under DBG.
  314. //
  315. CRegKey hkFilesKey;
  316. CRegKey hkCodebases;
  317. ::FusionpDbgPrintEx(
  318. FUSION_DBG_LEVEL_INSTALLATION,
  319. "SXS: %s - starting\n",
  320. __FUNCTION__);
  321. PARAMETER_CHECK((Flags & ~(SXSP_WRITE_PRIMARY_ASSEMBLY_INFO_INTO_REGISTRY_KEY_FLAG_REFRESH)) == 0);
  322. IFW32FALSE_EXIT(
  323. rhkRegistryNode.SetValue(
  324. CSMD_TOPLEVEL_IDENTITY,
  325. this->GetTextualIdentity()));
  326. IFW32FALSE_EXIT( rhkRegistryNode.SetValue(
  327. CSMD_TOPLEVEL_CATALOG,
  328. static_cast<DWORD>(1)));
  329. IFW32FALSE_EXIT( rhkRegistryNode.SetValue(
  330. CSMD_TOPLEVEL_MANIFESTHASH,
  331. REG_BINARY,
  332. this->m_baManifestSha1Hash.GetArrayPtr(),
  333. this->m_baManifestSha1Hash.GetSize() ) );
  334. IFW32FALSE_EXIT(
  335. rhkRegistryNode.OpenOrCreateSubKey(
  336. hkFilesKey,
  337. CSMD_TOPLEVEL_FILES,
  338. KEY_WRITE));
  339. IFW32FALSE_EXIT(this->WriteFilesIntoKey(hkFilesKey));
  340. //
  341. // Write keys into this codebase node
  342. //
  343. if ((Flags & SXSP_WRITE_PRIMARY_ASSEMBLY_INFO_INTO_REGISTRY_KEY_FLAG_REFRESH) == 0)
  344. {
  345. IFW32FALSE_EXIT(
  346. rhkRegistryNode.OpenOrCreateSubKey(
  347. hkCodebases,
  348. CSMD_TOPLEVEL_CODEBASES,
  349. KEY_WRITE));
  350. for (ULONG ulI = 0; ulI < this->m_cilCodebases.GetSize(); ulI++)
  351. {
  352. CRegKey hkSingleCodebaseKey;
  353. const CCodebaseInformation &rcCodebase = m_cilCodebases[ulI];
  354. // Don't attempt to write blank (Darwin) referenced codebases to the
  355. // registry.
  356. if ( rcCodebase.GetReference().Cch() == 0 )
  357. continue;
  358. IFW32FALSE_EXIT(
  359. hkCodebases.OpenOrCreateSubKey(
  360. hkSingleCodebaseKey,
  361. rcCodebase.GetReference(),
  362. KEY_WRITE));
  363. IFW32FALSE_EXIT(rcCodebase.WriteToRegistryKey(hkSingleCodebaseKey));
  364. }
  365. }
  366. #if DBG
  367. else
  368. {
  369. ::FusionpDbgPrintEx(
  370. FUSION_DBG_LEVEL_WFP | FUSION_DBG_LEVEL_INSTALLATION,
  371. "SXS.DLL: %s - recovery, not writing codebase and codebase prompt\n",
  372. __FUNCTION__);
  373. }
  374. #endif
  375. FN_EPILOG
  376. }
  377. BOOL
  378. CSecurityMetaData::WriteSecondaryAssemblyInfoIntoRegistryKey(
  379. const CRegKey &rhkRegistryNode
  380. ) const
  381. {
  382. if (SXS_AVOID_WRITING_REGISTRY)
  383. return TRUE;
  384. FN_PROLOG_WIN32
  385. IFW32FALSE_EXIT(rhkRegistryNode.SetValue(CSMD_TOPLEVEL_SHORTNAME, this->GetInstalledDirShortName()));
  386. IFW32FALSE_EXIT(rhkRegistryNode.SetValue(CSMD_TOPLEVEL_SHORTCATALOG, this->GetShortCatalogPath()));
  387. IFW32FALSE_EXIT(rhkRegistryNode.SetValue(CSMD_TOPLEVEL_SHORTMANIFEST, this->GetShortManifestPath()));
  388. IFW32FALSE_EXIT(
  389. rhkRegistryNode.SetValue(
  390. CSMD_TOPLEVEL_PUBLIC_KEY_TOKEN,
  391. REG_BINARY,
  392. this->m_baSignerPublicKeyToken.GetArrayPtr(),
  393. this->m_baSignerPublicKeyToken.GetSize()));
  394. FN_EPILOG
  395. }
  396. BOOL
  397. CSecurityMetaData::WriteFilesIntoKey(
  398. CRegKey & rhkFilesKey
  399. ) const
  400. {
  401. if (SXS_AVOID_WRITING_REGISTRY)
  402. return TRUE;
  403. FN_PROLOG_WIN32
  404. CFileInformationTableIter FilesIterator( const_cast<CFileInformationTable&>(m_fitFileDataTable) );
  405. ULONG uliIndex = 0;
  406. for ( FilesIterator.Reset(); FilesIterator.More(); FilesIterator.Next() )
  407. {
  408. const PCWSTR pcwszFileName = FilesIterator.GetKey();
  409. const CMetaDataFileElement& rcmdfeFileData = FilesIterator.GetValue();
  410. CRegKey hkFileSubKey;
  411. CSmallStringBuffer buffKeySubname;
  412. //
  413. // The trick here is that you can't simply create the subkey off this node,
  414. // as it might be "foo\bar\bas\zip.ding".
  415. //
  416. IFW32FALSE_EXIT( buffKeySubname.Win32Format( L"%ld", uliIndex++ ) );
  417. IFW32FALSE_EXIT( rhkFilesKey.OpenOrCreateSubKey(
  418. hkFileSubKey,
  419. buffKeySubname,
  420. KEY_ALL_ACCESS ) );
  421. //
  422. // So instead, we set the default value of the key to be the name of the file.
  423. //
  424. IFW32FALSE_EXIT( buffKeySubname.Win32Assign( pcwszFileName, lstrlenW(pcwszFileName) ) );
  425. IFW32FALSE_EXIT( hkFileSubKey.SetValue(
  426. NULL,
  427. buffKeySubname ) );
  428. IFW32FALSE_EXIT( rcmdfeFileData.WriteToRegistry( hkFileSubKey ) );
  429. }
  430. FN_EPILOG
  431. }
  432. /*
  433. [name of full assembly]
  434. v : Codebase = [meta-url] <string>
  435. v : Catalog = 1 <dword>
  436. v : Shortname = [shortname generated during installation] <string>
  437. v : ManifestHash = [...] <binary>
  438. v : PublicKeyToken = [...] <binary>
  439. k : Files
  440. k : [Filename]
  441. v : SHA1 = [...] <binary>
  442. v : MD5 = [...] <binary>
  443. k : [Filename]
  444. ...
  445. k : Codebases
  446. k : [reference-string]
  447. v : PromptString = [...] <string>
  448. v : Url = [meta-url] <string>
  449. */
  450. BOOL
  451. CSecurityMetaData::LoadFromRegistryKey(
  452. const CRegKey &rhkRegistryNode
  453. )
  454. {
  455. FN_PROLOG_WIN32
  456. CRegKey hkTempStuff;
  457. DWORD dwHasCatalog = 0;
  458. IFW32FALSE_EXIT(
  459. ::FusionpRegQueryDwordValueEx(
  460. 0,
  461. rhkRegistryNode,
  462. CSMD_TOPLEVEL_CATALOG,
  463. &dwHasCatalog,
  464. 0));
  465. // NTRAID#NTBUG9 - 556327 - jonwis - 2002/04/25 - Remove this assert, make it deal better with zero values
  466. ASSERT(dwHasCatalog != 0);
  467. IFW32FALSE_EXIT(
  468. ::FusionpRegQuerySzValueEx(
  469. FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING,
  470. rhkRegistryNode,
  471. CSMD_TOPLEVEL_IDENTITY,
  472. this->m_buffTextualAssemblyIdentity));
  473. IFW32FALSE_EXIT(
  474. ::FusionpRegQuerySzValueEx(
  475. FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING,
  476. rhkRegistryNode,
  477. CSMD_TOPLEVEL_SHORTNAME,
  478. this->m_buffShortNameOnDisk));
  479. IFW32FALSE_EXIT(
  480. ::FusionpRegQuerySzValueEx(
  481. FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING,
  482. rhkRegistryNode,
  483. CSMD_TOPLEVEL_SHORTCATALOG,
  484. this->m_buffShortCatalogName));
  485. IFW32FALSE_EXIT(
  486. ::FusionpRegQuerySzValueEx(
  487. FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING,
  488. rhkRegistryNode,
  489. CSMD_TOPLEVEL_SHORTMANIFEST,
  490. this->m_buffShortManifestName));
  491. IFW32FALSE_EXIT(
  492. ::FusionpRegQueryBinaryValueEx(
  493. 0,
  494. rhkRegistryNode,
  495. CSMD_TOPLEVEL_MANIFESTHASH,
  496. this->m_baManifestSha1Hash));
  497. IFW32FALSE_EXIT(
  498. ::FusionpRegQueryBinaryValueEx(
  499. 0,
  500. rhkRegistryNode,
  501. CSMD_TOPLEVEL_PUBLIC_KEY_TOKEN,
  502. this->m_baSignerPublicKeyToken));
  503. IFW32FALSE_EXIT(rhkRegistryNode.OpenSubKey(hkTempStuff, CSMD_TOPLEVEL_CODEBASES, KEY_READ));
  504. if (hkTempStuff != CRegKey::GetInvalidValue())
  505. {
  506. IFW32FALSE_EXIT(this->LoadCodebasesFromKey(hkTempStuff));
  507. IFW32FALSE_EXIT(hkTempStuff.Win32Close());
  508. }
  509. IFW32FALSE_EXIT( rhkRegistryNode.OpenSubKey(hkTempStuff, CSMD_TOPLEVEL_FILES, KEY_READ));
  510. if (hkTempStuff != CRegKey::GetInvalidValue())
  511. {
  512. IFW32FALSE_EXIT(this->LoadFilesFromKey(hkTempStuff));
  513. IFW32FALSE_EXIT(hkTempStuff.Win32Close());
  514. }
  515. FN_EPILOG
  516. }
  517. BOOL
  518. CSecurityMetaData::LoadFilesFromKey(
  519. CRegKey &hkTopLevelFileKey
  520. )
  521. {
  522. FN_PROLOG_WIN32
  523. CSmallStringBuffer buffNextKeyName;
  524. DWORD dwIndex = 0;
  525. while ( true )
  526. {
  527. BOOL fNoMoreItems = FALSE;
  528. CRegKey hkIterator;
  529. buffNextKeyName.Clear();
  530. IFW32FALSE_EXIT(hkTopLevelFileKey.EnumKey(
  531. dwIndex++,
  532. buffNextKeyName,
  533. NULL,
  534. &fNoMoreItems ) );
  535. if ( fNoMoreItems )
  536. {
  537. break;
  538. }
  539. IFW32FALSE_EXIT( hkTopLevelFileKey.OpenSubKey(
  540. hkIterator,
  541. buffNextKeyName,
  542. KEY_READ ) );
  543. if ( hkIterator != CRegKey::GetInvalidValue() )
  544. {
  545. CMetaDataFileElement SingleFileElement;
  546. IFW32FALSE_EXIT( SingleFileElement.Initialize() );
  547. IFW32FALSE_EXIT( SingleFileElement.ReadFromRegistry( hkIterator ) );
  548. //
  549. // Now read the name of the file from the default
  550. //
  551. IFW32FALSE_EXIT(
  552. ::FusionpRegQuerySzValueEx(
  553. 0,
  554. hkIterator,
  555. NULL,
  556. buffNextKeyName));
  557. IFW32FALSE_EXIT(this->AddFileMetaData( buffNextKeyName, SingleFileElement));
  558. }
  559. }
  560. FN_EPILOG
  561. }
  562. class CSecurityMetaDataLoadCodebasesFromKeyLocals
  563. {
  564. public:
  565. CStringBuffer buffKeyNameTemp;
  566. CCodebaseInformation Codebase;
  567. };
  568. BOOL
  569. CSecurityMetaData::LoadCodebasesFromKey(
  570. IN CRegKey& hkCodebaseSubkey
  571. )
  572. {
  573. FN_PROLOG_WIN32
  574. DWORD dwMaxKeyLength = 0;
  575. DWORD dwNextIndex = 0;
  576. CSmartPtr<CSecurityMetaDataLoadCodebasesFromKeyLocals> Locals;
  577. IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__));
  578. CStringBuffer &buffKeyNameTemp = Locals->buffKeyNameTemp;
  579. //
  580. // Find out how big the largest subkey string is, then reset our iterator temp
  581. // to be that big.
  582. //
  583. IFW32FALSE_EXIT(hkCodebaseSubkey.LargestSubItemLengths(&dwMaxKeyLength, NULL));
  584. IFW32FALSE_EXIT(buffKeyNameTemp.Win32ResizeBuffer(dwMaxKeyLength + 1, eDoNotPreserveBufferContents));
  585. //
  586. // Codebases are stored as subkeys and then values under them.
  587. //
  588. for (;;)
  589. {
  590. BOOL fNoMoreItems = FALSE;
  591. IFW32FALSE_EXIT(
  592. hkCodebaseSubkey.EnumKey(
  593. dwNextIndex++,
  594. buffKeyNameTemp,
  595. NULL,
  596. &fNoMoreItems));
  597. if (fNoMoreItems)
  598. break;
  599. CRegKey hkSingleCodebaseKey;
  600. IFW32FALSE_EXIT(
  601. hkCodebaseSubkey.OpenSubKey(
  602. hkSingleCodebaseKey,
  603. buffKeyNameTemp,
  604. KEY_READ));
  605. if (hkSingleCodebaseKey == CRegKey::GetInvalidValue())
  606. continue;
  607. CCodebaseInformation &Codebase = Locals->Codebase;
  608. IFW32FALSE_EXIT(Codebase.Initialize());
  609. IFW32FALSE_EXIT(Codebase.SetReference(buffKeyNameTemp));
  610. #if DBG
  611. ::FusionpDbgPrintEx(
  612. FUSION_DBG_LEVEL_INSTALLATION,
  613. "SXS: %s - read codebase %ls %ls\n",
  614. __FUNCTION__,
  615. static_cast<PCWSTR>(buffKeyNameTemp),
  616. static_cast<PCWSTR>(Codebase.GetCodebase())
  617. );
  618. #endif
  619. IFW32FALSE_EXIT(Codebase.ReadFromRegistryKey(hkSingleCodebaseKey));
  620. IFW32FALSE_EXIT(this->m_cilCodebases.Win32Append(Codebase));
  621. }
  622. FN_EPILOG
  623. }
  624. BOOL
  625. CMetaDataFileElement::Initialize(
  626. const CMetaDataFileElement &other
  627. )
  628. {
  629. FN_PROLOG_WIN32
  630. // The lack of a const iterator here is disturbing, so I have to const_cast
  631. // the metadatafileelement
  632. CFileHashTableIter InputTableIter( const_cast<CMetaDataFileElement&>(other) );
  633. //
  634. // Why is this not a bool??
  635. //
  636. this->ClearNoCallback();
  637. for(InputTableIter.Reset(); InputTableIter.More(); InputTableIter.Next())
  638. {
  639. IFW32FALSE_EXIT( this->Insert( InputTableIter.GetKey(), InputTableIter.GetValue() ) );
  640. }
  641. FN_EPILOG
  642. }
  643. BOOL
  644. CCodebaseInformation::Initialize()
  645. {
  646. this->m_Codebase.Clear();
  647. this->m_PromptText.Clear();
  648. this->m_Reference.Clear();
  649. this->m_Type = CODEBASE_RESOLVED_URLHEAD_UNKNOWN;
  650. return TRUE;
  651. }
  652. BOOL
  653. CCodebaseInformation::Initialize(
  654. const CCodebaseInformation &other
  655. )
  656. {
  657. FN_PROLOG_WIN32
  658. IFW32FALSE_EXIT(this->SetCodebase(other.GetCodebase()));
  659. IFW32FALSE_EXIT(this->SetPromptText(other.GetPromptText()));
  660. IFW32FALSE_EXIT(this->SetReference(other.GetReference()));
  661. this->m_Type = other.m_Type;
  662. FN_EPILOG
  663. }
  664. BOOL
  665. CCodebaseInformation::WriteToRegistryKey(
  666. const CRegKey &rhkCodebaseKey
  667. ) const
  668. {
  669. if (SXS_AVOID_WRITING_REGISTRY)
  670. return TRUE;
  671. FN_PROLOG_WIN32
  672. if (m_PromptText.Cch() != 0)
  673. {
  674. IFW32FALSE_EXIT(
  675. rhkCodebaseKey.SetValue(
  676. CSMD_CODEBASES_PROMPTSTRING,
  677. this->m_PromptText));
  678. }
  679. IFW32FALSE_EXIT(
  680. rhkCodebaseKey.SetValue(
  681. CSMD_CODEBASES_URL,
  682. this->m_Codebase));
  683. FN_EPILOG
  684. }
  685. BOOL
  686. CCodebaseInformation::ReadFromRegistryKey(
  687. const CRegKey &rhkSingleCodebaseKey
  688. )
  689. {
  690. FN_PROLOG_WIN32
  691. //
  692. // Missing prompt is OK
  693. //
  694. IFW32FALSE_EXIT(
  695. ::FusionpRegQuerySzValueEx(
  696. FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING,
  697. rhkSingleCodebaseKey,
  698. CSMD_CODEBASES_PROMPTSTRING,
  699. m_PromptText));
  700. //
  701. // We don't want to fail just because someone messed up the registry...
  702. //
  703. IFW32FALSE_EXIT(
  704. ::FusionpRegQuerySzValueEx(
  705. FUSIONP_REG_QUERY_SZ_VALUE_EX_MISSING_GIVES_NULL_STRING,
  706. rhkSingleCodebaseKey,
  707. CSMD_CODEBASES_URL,
  708. m_Codebase));
  709. FN_EPILOG
  710. }
  711. BOOL
  712. CCodebaseInformationList::FindCodebase(
  713. const CBaseStringBuffer &rbuffReference,
  714. CCodebaseInformation *&rpCodebaseInformation
  715. )
  716. {
  717. FN_PROLOG_WIN32
  718. bool fMatches = false;
  719. SIZE_T i = 0;
  720. rpCodebaseInformation = NULL;
  721. for (i=0; i < m_cElements; i++)
  722. {
  723. IFW32FALSE_EXIT(m_prgtElements[i].GetReference().Win32Equals(rbuffReference, fMatches, true));
  724. if (fMatches)
  725. break;
  726. }
  727. if (fMatches)
  728. {
  729. INTERNAL_ERROR_CHECK(i < m_cElements);
  730. rpCodebaseInformation = &m_prgtElements[i];
  731. }
  732. FN_EPILOG
  733. }
  734. BOOL
  735. CCodebaseInformationList::RemoveCodebase(
  736. const CBaseStringBuffer &rbuffReference,
  737. bool &rfRemoved
  738. )
  739. {
  740. FN_PROLOG_WIN32
  741. bool fMatches = false;
  742. SIZE_T i = 0;
  743. rfRemoved = false;
  744. if (SXS_AVOID_WRITING_REGISTRY)
  745. return TRUE;
  746. for (i=0; i < m_cElements; i++)
  747. {
  748. IFW32FALSE_EXIT(m_prgtElements[i].GetReference().Win32Equals(rbuffReference, fMatches, true));
  749. if (fMatches)
  750. {
  751. IFW32FALSE_EXIT(this->Win32Remove(i));
  752. rfRemoved = true;
  753. break;
  754. }
  755. }
  756. FN_EPILOG
  757. }
  758. BOOL
  759. SxspValidateAllFileHashes(
  760. IN const CMetaDataFileElement &rmdfeElement,
  761. IN const CBaseStringBuffer &rbuffFileName,
  762. OUT HashValidateResult &rResult
  763. )
  764. {
  765. FN_PROLOG_WIN32
  766. DWORD dwIndex = 0;
  767. CSmallStringBuffer buffHashName;
  768. BOOL fAllHashesMatch = TRUE;
  769. CFusionByteArray baFileHashData;
  770. rResult = HashValidate_OtherProblems;
  771. while ( true && fAllHashesMatch )
  772. {
  773. BOOL fTemp;
  774. ALG_ID aid = 0;
  775. HashValidateResult Results = HashValidate_OtherProblems;
  776. IFW32FALSE_EXIT(
  777. ::SxspEnumKnownHashTypes(
  778. dwIndex++,
  779. buffHashName,
  780. fTemp));
  781. if (fTemp)
  782. break;
  783. IFW32FALSE_EXIT( SxspHashAlgFromString( buffHashName, aid ) );
  784. //
  785. // Did the file element have this type of hash data in it?
  786. //
  787. IFW32FALSE_EXIT( rmdfeElement.GetHashDataForKind(
  788. buffHashName,
  789. baFileHashData,
  790. fTemp ));
  791. if ( !fTemp )
  792. {
  793. continue;
  794. }
  795. IFW32FALSE_EXIT( ::SxspVerifyFileHash(
  796. SVFH_RETRY_LOGIC_SIMPLE,
  797. rbuffFileName,
  798. baFileHashData,
  799. aid,
  800. Results ) );
  801. if ( Results != HashValidate_Matches )
  802. {
  803. fAllHashesMatch = FALSE;
  804. }
  805. }
  806. if ( fAllHashesMatch )
  807. {
  808. rResult = HashValidate_Matches;
  809. }
  810. FN_EPILOG
  811. }
  812. BOOL
  813. CSecurityMetaData::RemoveCodebase(
  814. const CBaseStringBuffer &rbuffReference,
  815. bool &rfRemoved
  816. )
  817. {
  818. if (SXS_AVOID_WRITING_REGISTRY)
  819. return TRUE;
  820. return m_cilCodebases.RemoveCodebase(rbuffReference, rfRemoved);
  821. }