Source code of Windows XP (NT5)
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.

873 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000.
  5. //
  6. // File: secstore.cxx
  7. //
  8. // Contents: SDID to security descriptor mapping table
  9. //
  10. // History: 29 Jan 1996 AlanW Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <cistore.hxx>
  16. #include <rcstxact.hxx>
  17. #include <rcstrmit.hxx>
  18. #include <catalog.hxx>
  19. #include <secstore.hxx>
  20. //+-------------------------------------------------------------------------
  21. //
  22. // Method: CSdidLookupTable::CSdidLookupTable, public
  23. //
  24. // Synopsis: Constructor of a CSdidLookupTable
  25. //
  26. // Arguments: -NONE-
  27. //
  28. // Returns: Nothing
  29. //
  30. //--------------------------------------------------------------------------
  31. CSdidLookupTable::CSdidLookupTable( )
  32. : _pTable( 0 ),
  33. _xrsoSdidTable( 0 ),
  34. _mutex(),
  35. _cache()
  36. {
  37. }
  38. void CSdidLookupTable::Empty()
  39. {
  40. CLock lock ( _mutex );
  41. delete [] _pTable; _pTable = 0;
  42. _xrsoSdidTable.Free();
  43. _cache.Empty();
  44. }
  45. CSdidLookupTable::~CSdidLookupTable( )
  46. {
  47. Empty();
  48. }
  49. //+---------------------------------------------------------------------------
  50. //
  51. // Member: CSdidLookupTable::Init, public
  52. //
  53. // Synopsis: Loads metadata from persistent location into memory.
  54. //
  55. // Arguments: [pobj] -- Stream(s) in which metadata is stored.
  56. //
  57. // History: 27-Dec-95 KyleP Created.
  58. //
  59. //----------------------------------------------------------------------------
  60. BOOL CSdidLookupTable::Init( CiStorage * pobj )
  61. {
  62. CLock lock ( _mutex );
  63. _xrsoSdidTable.Set( pobj->QuerySdidLookupTable( eSecStoreWid ) );
  64. //
  65. // Load header
  66. //
  67. CRcovStorageHdr & hdr = _xrsoSdidTable->GetHeader();
  68. struct CRcovUserHdr data;
  69. hdr.GetUserHdr( hdr.GetPrimary(), data );
  70. RtlCopyMemory( &_Header, &data._abHdr, sizeof(_Header) );
  71. ciDebugOut(( DEB_SECSTORE, "SECSTORE: Record size = %d bytes\n", _Header.cbRecord ));
  72. ciDebugOut(( DEB_SECSTORE, "SECSTORE: %d file records\n", _Header.cRecords ));
  73. ciDebugOut(( DEB_SECSTORE, "SECSTORE: Hash size = %u\n", _Header.cHash ));
  74. if ( _Header.cHash == 0 )
  75. {
  76. Win4Assert( 0 == Records() && _Header.cbRecord == 0 );
  77. RtlCopyMemory( _Header.Signature, "SECSTORE", sizeof _Header.Signature );
  78. Win4Assert( (sizeof (SSdHeaderRecord) + SECURITY_DESCRIPTOR_MIN_LENGTH)
  79. < SECSTORE_REC_SIZE );
  80. _Header.cbRecord = SECSTORE_REC_SIZE;
  81. _Header.cHash = SECSTORE_HASH_SIZE;
  82. _Header.cRecords = 0;
  83. }
  84. else
  85. {
  86. Win4Assert( RtlEqualMemory( _Header.Signature, "SECSTORE",
  87. sizeof _Header.Signature) &&
  88. _Header.cbRecord == SECSTORE_REC_SIZE &&
  89. _Header.cHash == SECSTORE_HASH_SIZE );
  90. if ( ! RtlEqualMemory( _Header.Signature, "SECSTORE",
  91. sizeof _Header.Signature) ||
  92. _Header.cbRecord != SECSTORE_REC_SIZE ||
  93. _Header.cHash != SECSTORE_HASH_SIZE )
  94. return FALSE;
  95. }
  96. //
  97. // Load hash table
  98. //
  99. ULONG cRecordsFromFile = Records();
  100. ULONG iRecord = 1;
  101. _pTable = new SDID [ _Header.cHash ];
  102. RtlZeroMemory( _pTable, _Header.cHash * sizeof (SDID) );
  103. _Header.cRecords = 0;
  104. #if (DBG == 1)
  105. _cMaxChainLen = 0;
  106. _cTotalSearches = 0;
  107. _cTotalLength = 0;
  108. #endif // (DBG == 1)
  109. CRcovStrmReadTrans xact( _xrsoSdidTable.GetReference() );
  110. CRcovStrmReadIter iter( xact, SECSTORE_REC_SIZE );
  111. BYTE temp[ SECSTORE_REC_SIZE ];
  112. while ( iter.GetRec( &temp, iRecord-1 ) )
  113. {
  114. SSdHeaderRecord SdHdr = *(SSdHeaderRecord *)temp;
  115. Win4Assert( SdHdr.cbSD >= SECURITY_DESCRIPTOR_MIN_LENGTH &&
  116. SdHdr.cbSD < 256 * 1024 &&
  117. _pTable[ SdHdr.ulHash % SECSTORE_HASH_SIZE ] ==
  118. SdHdr.iHashChain );
  119. if ( SdHdr.cbSD < SECURITY_DESCRIPTOR_MIN_LENGTH ||
  120. SdHdr.cbSD >= 256 * 1024 ||
  121. _pTable[ SdHdr.ulHash % SECSTORE_HASH_SIZE ] != SdHdr.iHashChain )
  122. return FALSE;
  123. _pTable[ SdHdr.ulHash % SECSTORE_HASH_SIZE ] = iRecord;
  124. ciDebugOut(( DEB_SECSTORE,
  125. "SECSTORE: SD record\tSDID = %d, cb = %d, hash = %08x, chain = %d\n",
  126. iRecord, SdHdr.cbSD, SdHdr.ulHash, SdHdr.iHashChain ));
  127. #ifdef UNIT_TEST
  128. // much below is debug code; don't need to allocate
  129. // the SD here; just seek to the start of each record
  130. // and read the record header.
  131. XArray<BYTE> pbSD ( SdHdr.cbSD );
  132. BYTE * pbDst = pbSD.GetPointer();
  133. BYTE * pbSrc = &temp[0] + sizeof (SSdHeaderRecord);
  134. ULONG cb = SdHdr.cbSD;
  135. ULONG cbPart = SECSTORE_REC_SIZE - sizeof (SSdHeaderRecord);
  136. if (cb < cbPart)
  137. cbPart = cb;
  138. RtlCopyMemory( pbDst, pbSrc, cbPart );
  139. pbDst += cbPart;
  140. cb -= cbPart;
  141. pbSrc = &temp[0];
  142. while( 0 != cb )
  143. {
  144. iter.GetRec( temp );
  145. cbPart = (cb > SECSTORE_REC_SIZE) ? SECSTORE_REC_SIZE : cb;
  146. RtlCopyMemory( pbDst, pbSrc, cbPart );
  147. pbDst += cbPart;
  148. cb -= cbPart;
  149. pbSrc = &temp[0];
  150. iRecord++;
  151. }
  152. PSECURITY_DESCRIPTOR pSD = pbSD.GetPointer();
  153. Win4Assert( SdHdr.cbSD == GetSecurityDescriptorLength( pSD ) &&
  154. SdHdr.ulHash == Hash( pSD, SdHdr.cbSD ) );
  155. iRecord++;
  156. #else
  157. iRecord += (SdHdr.cbSD + (sizeof SdHdr) + SECSTORE_REC_SIZE - 1) /
  158. SECSTORE_REC_SIZE;
  159. #endif
  160. _Header.cRecords = iRecord - 1;
  161. }
  162. Win4Assert( Records() == cRecordsFromFile );
  163. return TRUE;
  164. }
  165. //+-------------------------------------------------------------------------
  166. //
  167. // Method: CSdidLookupTable::Hash, public
  168. //
  169. // Synopsis: Generate a hash value for the passed SECURITY_DESCRIPTOR
  170. //
  171. // Arguments: [pSD] -- pointer to SECURITY_DESCRIPTOR
  172. // [cb] -- length of SECURITY_DESCRIPTOR in bytes
  173. //
  174. // Returns: ULONG - Hash value for the input SECURITY_DESCRIPTOR
  175. //
  176. //--------------------------------------------------------------------------
  177. ULONG CSdidLookupTable::Hash(const PSECURITY_DESCRIPTOR pSD, unsigned cb)
  178. {
  179. ULONG ulHash = 0;
  180. BYTE * pb = (BYTE *) pSD;
  181. while (cb-- != 0)
  182. {
  183. if (ulHash & 0x80000000)
  184. {
  185. ulHash = (ulHash << 1) | 1;
  186. }
  187. else
  188. {
  189. ulHash <<= 1;
  190. }
  191. ulHash ^= *pb++;
  192. }
  193. return(ulHash);
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Method: CSdidLookupTable::Lookup, private
  198. //
  199. // Synopsis: Looks up a security descriptor in the table.
  200. //
  201. // Arguments: [sdid] - SDID to look up.
  202. //
  203. // Returns: CSdidLookupEntry* - pointer to entry for SDID
  204. //
  205. // History: 29 Jan 1996 Alanw Created
  206. //
  207. // Notes: The security descriptor entry will be owned by
  208. // the caller after the call.
  209. //
  210. //----------------------------------------------------------------------------
  211. CSdidLookupEntry * CSdidLookupTable::Lookup( SDID sdid )
  212. {
  213. Win4Assert( sdid <= Records() );
  214. Win4Assert( !_xrsoSdidTable.IsNull() );
  215. if ( sdid > Records() )
  216. {
  217. return 0;
  218. }
  219. CSdidLookupEntry * pEntry = 0;
  220. CLock lock ( _mutex );
  221. //
  222. // First see if the desired item is in the cache
  223. //
  224. for ( CSdidCacheIter listiter( _cache );
  225. !_cache.AtEnd( listiter );
  226. _cache.Advance( listiter ) )
  227. {
  228. if ( listiter.GetEntry()->Sdid() == sdid )
  229. {
  230. pEntry = listiter.GetEntry();
  231. _cache.RemoveFromList( pEntry );
  232. return pEntry;
  233. }
  234. }
  235. XPtr<CSdidLookupEntry> xEntry;
  236. //
  237. // The entry was not in the cache. Read it from storage.
  238. //
  239. TRY
  240. {
  241. // Corrupt?
  242. if (_xrsoSdidTable.IsNull())
  243. THROW(CException(CI_CORRUPT_DATABASE));
  244. xEntry.Set( new CSdidLookupEntry(sdid) );
  245. CRcovStrmReadTrans xact( _xrsoSdidTable.GetReference() );
  246. CRcovStrmReadIter iter( xact, SECSTORE_REC_SIZE );
  247. LoadTableEntry( iter, xEntry.GetReference(), sdid );
  248. }
  249. CATCH(CException, e)
  250. {
  251. ciDebugOut(( DEB_WARN, "CSdidLookupTable::Lookup - exception %x\n",
  252. e.GetErrorCode() ));
  253. if (e.GetErrorCode() != STATUS_ACCESS_VIOLATION)
  254. RETHROW();
  255. }
  256. END_CATCH
  257. return xEntry.Acquire();
  258. }
  259. //+---------------------------------------------------------------------------
  260. //
  261. // Method: CSdidLookupTable::LookUpSDID, public
  262. //
  263. // Synopsis: Looks up a security descriptor's ID in the table.
  264. // Add the SD to the table if not found.
  265. //
  266. // Arguments: [pSD] - SD to look up.
  267. // [cbSD] - size of security descriptor
  268. //
  269. // Returns: SDID - ID of security descriptor input
  270. //
  271. // History: 29 Jan 1996 Alanw Created
  272. //
  273. // Notes:
  274. //
  275. //----------------------------------------------------------------------------
  276. SDID CSdidLookupTable::LookupSDID( PSECURITY_DESCRIPTOR pSD, ULONG cbSD )
  277. {
  278. Win4Assert( (((SECURITY_DESCRIPTOR *)pSD)->Control & SE_SELF_RELATIVE) &&
  279. GetSecurityDescriptorLength( pSD ) == cbSD );
  280. Win4Assert( !_xrsoSdidTable.IsNull() );
  281. SDID iSdid = 0;
  282. BOOL fFound = FALSE;
  283. #if (DBG == 1)
  284. ULONG cSearchLen = 0;
  285. #endif // (DBG == 1)
  286. ULONG ulHash = Hash( pSD, cbSD );
  287. CLock lock ( _mutex );
  288. //
  289. // First see if a matching item is in the cache
  290. //
  291. for ( CSdidCacheIter listiter( _cache );
  292. !_cache.AtEnd( listiter );
  293. _cache.Advance( listiter ) )
  294. {
  295. if ( listiter.GetEntry()->IsEqual( pSD, cbSD, ulHash ) )
  296. {
  297. Win4Assert( listiter.GetEntry()->Sdid() > 0 );
  298. return listiter.GetEntry()->Sdid();
  299. }
  300. }
  301. //
  302. // The SD was not found in the cache. Try looking in storage.
  303. //
  304. TRY
  305. {
  306. SDID iNext = _pTable[ ulHash % HashSize() ];
  307. if (iNext != 0)
  308. {
  309. CRcovStrmReadTrans xact( _xrsoSdidTable.GetReference() );
  310. CRcovStrmReadIter iter( xact, SECSTORE_REC_SIZE );
  311. BYTE temp[ SECSTORE_REC_SIZE ];
  312. while (iNext != 0)
  313. {
  314. #if (DBG == 1)
  315. cSearchLen++;
  316. #endif // (DBG == 1)
  317. iter.GetRec( &temp, iNext-1 );
  318. SSdHeaderRecord * pSdHdr = (SSdHeaderRecord *)temp;
  319. Win4Assert( pSdHdr->cbSD >= SECURITY_DESCRIPTOR_MIN_LENGTH &&
  320. pSdHdr->iHashChain < iNext );
  321. if (pSdHdr->cbSD == cbSD && pSdHdr->ulHash == ulHash)
  322. {
  323. // The byte count and hash value match. Fetch the rest of
  324. // the SD to compare it byte-for-byte.
  325. XPtr<CSdidLookupEntry> xEntry( new CSdidLookupEntry( iNext ) );
  326. LoadTableEntry( iter, xEntry.GetReference(), iNext );
  327. if (RtlEqualMemory( pSD, xEntry->GetSD(), cbSD))
  328. {
  329. fFound = TRUE;
  330. iSdid = iNext;
  331. _cache.Add( xEntry.Acquire() );
  332. }
  333. }
  334. iNext = pSdHdr->iHashChain;
  335. }
  336. }
  337. if (! fFound)
  338. {
  339. //
  340. // The SD was not found.
  341. // Write new mapping to the recoverable storage.
  342. //
  343. iSdid = Records() + 1;
  344. CRcovStorageHdr & hdr = _xrsoSdidTable->GetHeader();
  345. CRcovStrmAppendTrans xact( _xrsoSdidTable.GetReference() );
  346. CRcovStrmAppendIter iter( xact, SECSTORE_REC_SIZE );
  347. BYTE temp[ SECSTORE_REC_SIZE ];
  348. SSdHeaderRecord * pSdHdr = (SSdHeaderRecord *)temp;
  349. pSdHdr->cbSD = cbSD;
  350. pSdHdr->ulHash = ulHash;
  351. pSdHdr->iHashChain = _pTable[ ulHash % HashSize() ];
  352. BYTE * pbDst = &temp[0] + sizeof (SSdHeaderRecord);
  353. BYTE * pbSrc = (BYTE *)pSD;
  354. ULONG cb = cbSD;
  355. ULONG cbPart = SECSTORE_REC_SIZE - sizeof (SSdHeaderRecord);
  356. if (cb < cbPart)
  357. cbPart = cb;
  358. RtlCopyMemory( pbDst, pbSrc, cbPart );
  359. pbSrc += cbPart;
  360. cb -= cbPart;
  361. iter.AppendRec( temp );
  362. ULONG cRecordsWritten = 1;
  363. while( 0 != cb )
  364. {
  365. if (cb >= SECSTORE_REC_SIZE)
  366. {
  367. iter.AppendRec( pbSrc );
  368. cbPart = SECSTORE_REC_SIZE;
  369. }
  370. else
  371. {
  372. cbPart = (cb > SECSTORE_REC_SIZE) ? SECSTORE_REC_SIZE : cb;
  373. RtlCopyMemory( temp, pbSrc, cbPart );
  374. RtlZeroMemory( &temp[cbPart], SECSTORE_REC_SIZE - cbPart );
  375. iter.AppendRec( temp );
  376. }
  377. pbSrc += cbPart;
  378. cb -= cbPart;
  379. cRecordsWritten++;
  380. }
  381. ciDebugOut(( DEB_SECSTORE,
  382. "SECSTORE: new SD record\tSDID = %d, cb = %d, hash = %08x, chain = %d\n",
  383. iSdid, cbSD, ulHash, _pTable[ ulHash % SECSTORE_HASH_SIZE ] ));
  384. _pTable[ ulHash % SECSTORE_HASH_SIZE ] = iSdid;
  385. _Header.cRecords += cRecordsWritten;
  386. struct CRcovUserHdr data;
  387. RtlCopyMemory( &data._abHdr, &_Header, sizeof(_Header) );
  388. Win4Assert( hdr.GetCount(hdr.GetBackup()) == hdr.GetCount(hdr.GetPrimary()) + cRecordsWritten);
  389. hdr.SetUserHdr( hdr.GetBackup(), data );
  390. xact.Commit();
  391. }
  392. }
  393. CATCH(CException, e)
  394. {
  395. ciDebugOut(( DEB_WARN, "CSdidLookupTable::LookupSDID - exception %x\n",
  396. e.GetErrorCode() ));
  397. if (e.GetErrorCode() == STATUS_ACCESS_VIOLATION)
  398. {
  399. Win4Assert( !"Access violation in CSdidLookupTable::LookupSDID - "
  400. "Are you running two queries on the same downlevel catalog?" );
  401. }
  402. RETHROW();
  403. }
  404. END_CATCH
  405. #if (DBG == 1)
  406. // Update search statistics
  407. _cTotalSearches++;
  408. if (fFound)
  409. {
  410. _cTotalLength += cSearchLen;
  411. }
  412. else
  413. {
  414. if (cSearchLen >= _cMaxChainLen)
  415. _cMaxChainLen = cSearchLen + 1;
  416. }
  417. #endif // (DBG == 1)
  418. return iSdid;
  419. }
  420. //+---------------------------------------------------------------------------
  421. //
  422. // Method: CSdidLookupTable::LoadTableEntry, private
  423. //
  424. // Synopsis: Loads a table entry for some SDID from the table.
  425. //
  426. // Arguments: [Iter] - CRcovStrmReadIter for access to the stream
  427. // [Entry] - CSdidTableEntry to be filled in
  428. // [iSdid] - SDID to be looked up.
  429. //
  430. // Returns: Nothing
  431. //
  432. // History: 29 Jan 1996 Alanw Created
  433. //
  434. // Notes:
  435. //
  436. //----------------------------------------------------------------------------
  437. void CSdidLookupTable::LoadTableEntry(
  438. CRcovStrmReadIter & iter,
  439. CSdidLookupEntry & Entry,
  440. SDID iSdid )
  441. {
  442. Win4Assert( iSdid <= Records() );
  443. BYTE temp[ SECSTORE_REC_SIZE ];
  444. iter.GetRec( &temp, iSdid-1 );
  445. Entry._hdr = *(SSdHeaderRecord *)temp;
  446. Win4Assert( Entry._hdr.cbSD >= SECURITY_DESCRIPTOR_MIN_LENGTH &&
  447. Entry._hdr.cbSD < 256 * 1024 );
  448. ciDebugOut(( DEB_SECSTORE,
  449. "SECSTORE: SD record\tSDID = %d, cb = %d, hash = %08x, chain = %d\n",
  450. iSdid, Entry._hdr.cbSD, Entry._hdr.ulHash, Entry._hdr.iHashChain ));
  451. XArray<BYTE> pbSD ( Entry._hdr.cbSD );
  452. BYTE * pbDst = pbSD.GetPointer();
  453. BYTE * pbSrc = &temp[0] + sizeof (SSdHeaderRecord);
  454. ULONG cb = Entry._hdr.cbSD;
  455. ULONG cbPart = SECSTORE_REC_SIZE - sizeof (SSdHeaderRecord);
  456. if (cb < cbPart)
  457. cbPart = cb;
  458. RtlCopyMemory( pbDst, pbSrc, cbPart );
  459. pbDst += cbPart;
  460. cb -= cbPart;
  461. pbSrc = &temp[0];
  462. while( 0 != cb )
  463. {
  464. if (cb >= SECSTORE_REC_SIZE)
  465. {
  466. iter.GetRec( pbDst );
  467. cbPart = SECSTORE_REC_SIZE;
  468. }
  469. else
  470. {
  471. iter.GetRec( temp );
  472. cbPart = (cb > SECSTORE_REC_SIZE) ? SECSTORE_REC_SIZE : cb;
  473. RtlCopyMemory( pbDst, pbSrc, cbPart );
  474. }
  475. pbDst += cbPart;
  476. cb -= cbPart;
  477. pbSrc = &temp[0];
  478. }
  479. Win4Assert( Entry._hdr.cbSD == GetSecurityDescriptorLength( pbSD.GetPointer() ) &&
  480. Entry._hdr.ulHash == Hash( pbSD.GetPointer(), Entry._hdr.cbSD ) );
  481. Entry._pSD = pbSD.Acquire();
  482. }
  483. //+---------------------------------------------------------------------------
  484. //
  485. // Method: CSdidLookupTable::AccessCheck, public
  486. //
  487. // Synopsis: Performs an access check for some SDID, access mask combination
  488. //
  489. // Arguments: [sdid] - SDID of file to be checked
  490. // [hToken] - security token to be checked against
  491. // [am] - access mode to be checked against
  492. // [fGranted] - TRUE is access is granted, FALSE otherwise
  493. //
  494. // Returns: BOOL - TRUE if access check was successful
  495. //
  496. // History: 05 Feb 1996 Alanw Created
  497. //
  498. // Notes:
  499. //
  500. //----------------------------------------------------------------------------
  501. GENERIC_MAPPING gmFile = {
  502. FILE_GENERIC_READ,
  503. FILE_GENERIC_WRITE,
  504. FILE_GENERIC_EXECUTE,
  505. FILE_ALL_ACCESS
  506. };
  507. BOOL CSdidLookupTable::AccessCheck(
  508. SDID sdid,
  509. HANDLE hToken,
  510. ACCESS_MASK am,
  511. BOOL & fGranted )
  512. {
  513. Win4Assert( sdidInvalid != sdid && sdidNull != sdid );
  514. CSdidLookupEntry * pSD = Lookup( sdid );
  515. fGranted = FALSE;
  516. if ( 0 == pSD )
  517. return FALSE;
  518. PRIVILEGE_SET ps;
  519. ULONG ulPrivSize = sizeof ps;
  520. ACCESS_MASK GrantedAccess;
  521. BOOL fResult = ::AccessCheck( pSD->GetSD(),
  522. hToken,
  523. am,
  524. &gmFile,
  525. &ps,
  526. &ulPrivSize,
  527. &GrantedAccess,
  528. &fGranted);
  529. {
  530. CLock lock ( _mutex );
  531. _cache.Add( pSD );
  532. }
  533. return fResult;
  534. }
  535. //+---------------------------------------------------------------------------
  536. //
  537. // Member: CSdidLookupTable::GetSecurityDescriptor
  538. //
  539. // Synopsis: Retrieves the security descriptor for the given SDID.
  540. //
  541. // Arguments: [sdid] - SDID to lookup
  542. // [pbData] - Pointer to the buffer to write the desc.
  543. // [cbIn] - Size of the pSD buffer
  544. // [cbOut] - Size of the security descriptor; if cbIn < cbOut,
  545. // then the buffer is not big enough to copy the data.
  546. //
  547. // Returns: S_OK if successfully returned.
  548. // S_FALSE if the buffer is not big enough to hold
  549. // the data. In this case cbOut will have the actual buffer
  550. // needed.
  551. // CI_E_NOT_FOUND the sdid is not valid.
  552. //
  553. // History: 7-18-97 srikants Created
  554. //
  555. //----------------------------------------------------------------------------
  556. HRESULT
  557. CSdidLookupTable::GetSecurityDescriptor(
  558. SDID sdid,
  559. PSECURITY_DESCRIPTOR pbData,
  560. ULONG cbIn,
  561. ULONG & cbOut )
  562. {
  563. Win4Assert( sdidInvalid != sdid && sdidNull != sdid );
  564. CSdidLookupEntry * pSD = Lookup( sdid );
  565. if ( 0 == pSD )
  566. return CI_E_NOT_FOUND;
  567. cbOut = pSD->Size();
  568. if ( cbOut > cbIn )
  569. return S_FALSE;
  570. RtlCopyMemory( pbData, pSD->GetSD(), cbOut );
  571. return S_OK;
  572. }
  573. //+---------------------------------------------------------------------------
  574. //
  575. // Member: CSdidLookupTable::Save
  576. //
  577. // Synopsis: Makes a copy of the current security table using the
  578. // destination storage object.
  579. //
  580. // Arguments: [pIProgressNotify] - Progress notification.
  581. // [fAbort] - Flag set to TRUE if the copy must
  582. // be aborted in the middle.
  583. // [dstStorage] - Destination storage object to use
  584. // for creating the bakcup.
  585. // [ppFileList] - List of files that constitute the
  586. // the security store.
  587. //
  588. // History: 7-14-97 srikants Created
  589. //
  590. //----------------------------------------------------------------------------
  591. void CSdidLookupTable::Save( IProgressNotify * pIProgressNotify,
  592. BOOL & fAbort,
  593. CiStorage & dstStorage,
  594. IEnumString **ppFileList )
  595. {
  596. dstStorage.RemoveSecStore( eSecStoreWid );
  597. XPtr<PRcovStorageObj> xObj( dstStorage.QuerySdidLookupTable( eSecStoreWid ) );
  598. // ===============================================================
  599. CLock lock ( _mutex );
  600. //
  601. // Make a copy of the security table.
  602. //
  603. Win4Assert( !_xrsoSdidTable.IsNull() );
  604. CCopyRcovObject copyRcov( xObj.GetReference(),
  605. _xrsoSdidTable.GetReference() );
  606. copyRcov.DoIt();
  607. //
  608. // Retrive the names of the files that constitute the security store.
  609. //
  610. CEnumString * pEnumString = new CEnumString();
  611. XInterface<IEnumString> xEnumStr(pEnumString);
  612. dstStorage.ListSecStoreFileNames( *pEnumString, 0 );
  613. *ppFileList = xEnumStr.Acquire();
  614. // ===============================================================
  615. }
  616. //+---------------------------------------------------------------------------
  617. //
  618. // Member: CSdidLookupTable::Load
  619. //
  620. // Synopsis: Loads the security store from a saved location into the
  621. // target directory.
  622. //
  623. // Arguments: [pwszDestDir] - Destination directory to load to
  624. // [pFileList] - List of the files.
  625. // [pProgressNotify] - Progress notification.
  626. // [fCallerOwnsFiles] - If the caller owns files.
  627. // [pfAbort] - Set to TRUE if must be aborted.
  628. //
  629. // History: 7-18-97 srikants Created
  630. //
  631. //----------------------------------------------------------------------------
  632. void CSdidLookupTable::Load( CiStorage * pobj,
  633. IEnumString * pFileList,
  634. IProgressNotify * pProgressNotify,
  635. BOOL fCallerOwnsFiles,
  636. BOOL * pfAbort )
  637. {
  638. // ===============================================================
  639. CLock lock ( _mutex );
  640. Win4Assert(pobj);
  641. Win4Assert(pFileList);
  642. Win4Assert(pfAbort);
  643. ULONG ulFetched;
  644. WCHAR * pwszFilePath;
  645. while ( !(*pfAbort) && (S_OK == pFileList->Next(1, &pwszFilePath, &ulFetched)) )
  646. {
  647. pobj->CopyGivenFile( pwszFilePath, !fCallerOwnsFiles );
  648. }
  649. }
  650. //+---------------------------------------------------------------------------
  651. //
  652. // Method: CSdidCache::Add, public
  653. //
  654. // Synopsis: Add an SDID record to the lookaside cache
  655. //
  656. // Arguments: [pEntry] - the item to be added to the cache
  657. //
  658. // Returns: Nothing
  659. //
  660. // History: 18 Apr 1996 Alanw Created
  661. //
  662. // Notes: The cache must be locked when this method is called.
  663. //
  664. //----------------------------------------------------------------------------
  665. void CSdidCache::Add( CSdidLookupEntry * pEntry )
  666. {
  667. //
  668. // If the cache is full, check to see if the item is in the cache. Another
  669. // copy may have been added while we were using this one.
  670. // If there is space in the cache, allow multiple copies of the same SDID.
  671. //
  672. if ( Count() >= _maxEntries )
  673. {
  674. for ( CSdidCacheIter iter( *this );
  675. !AtEnd( iter );
  676. Advance( iter ) )
  677. {
  678. if ( iter.GetEntry()->Sdid() == pEntry->Sdid() )
  679. {
  680. MoveToFront( iter.GetEntry() );
  681. delete pEntry;
  682. return;
  683. }
  684. }
  685. }
  686. //
  687. // Add the entry to the front of the list. If there are too many
  688. // items in the cache, delete the last entry.
  689. //
  690. Push( pEntry );
  691. if ( Count() > _maxEntries )
  692. {
  693. delete RemoveLast();
  694. }
  695. }
  696. //+---------------------------------------------------------------------------
  697. //
  698. // Method: CSdidCache::Empty, public
  699. //
  700. // Synopsis: Clean out the lookaside cache
  701. //
  702. // Arguments: NONE
  703. //
  704. // Returns: Nothing
  705. //
  706. // History: 18 Apr 1996 Alanw Created
  707. //
  708. // Notes:
  709. //
  710. //----------------------------------------------------------------------------
  711. void CSdidCache::Empty( )
  712. {
  713. CSdidLookupEntry * pEntry = 0;
  714. while ( pEntry = Pop() )
  715. delete pEntry;
  716. }