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.

837 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: lht.cxx
  7. //
  8. // Contents: Context handle management for servers
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 1-31-97 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <lsapch.hxx>
  18. #include "sht.hxx"
  19. #include "lht.hxx"
  20. //
  21. // Due to the high number of connections for servers, the client context list
  22. // for a particular session could grow into the thousands. At that stage, a
  23. // linear list that is searched to validate a handle is prohibitively expensive.
  24. //
  25. // Thus, the faster, if more expensive to set up and add handle package
  26. //
  27. HP_INITIALIZE_FN LhtInitialize ;
  28. HP_CREATE_FN LhtCreate ;
  29. HP_DELETE_FN LhtDelete ;
  30. HP_ADD_HANDLE_FN LhtAddHandle ;
  31. HP_DELETE_HANDLE_FN LhtDeleteHandle ;
  32. HP_VALIDATE_HANDLE_FN LhtValidateHandle ;
  33. HP_REF_HANDLE_FN LhtRefHandle ;
  34. HP_DEREF_HANDLE_KEY_FN LhtDerefHandleKey ;
  35. HP_GET_HANDLE_CONTEXT_FN LhtGetHandleContext ;
  36. HP_RELEASE_CONTEXT_FN LhtReleaseContext ;
  37. HANDLE_PACKAGE LargeHandlePackage = {
  38. sizeof( LARGE_HANDLE_TABLE ),
  39. LhtInitialize,
  40. LhtCreate,
  41. LhtDelete,
  42. LhtAddHandle,
  43. LhtDeleteHandle,
  44. LhtValidateHandle,
  45. LhtRefHandle,
  46. LhtDerefHandleKey,
  47. LhtGetHandleContext,
  48. LhtReleaseContext
  49. };
  50. ULONG LhtFastMem ;
  51. ULONG LhtShiftValues[] = { 4, 12, 16, 20 };
  52. #define IndexFromHandle( Level, Handle ) \
  53. ( ( ((PSecHandle) Handle)->dwUpper >> LhtShiftValues[ Level ] ) & HANDLE_TABLE_MASK )
  54. #define LhtLockTable( t ) \
  55. if ( (((PLARGE_HANDLE_TABLE) t)->Flags & LHT_NO_SERIALIZE ) == 0 ) \
  56. { \
  57. RtlEnterCriticalSection( &((PLARGE_HANDLE_TABLE)t)->Lock ); \
  58. }
  59. #define LhtUnlockTable( t ) \
  60. if ( (((PLARGE_HANDLE_TABLE) t)->Flags & LHT_NO_SERIALIZE ) == 0 ) \
  61. { \
  62. RtlLeaveCriticalSection( &((PLARGE_HANDLE_TABLE)t)->Lock ); \
  63. }
  64. #define LHT_ACTION_ADDREF 0
  65. #define LHT_ACTION_DELREF 1
  66. #define LHT_ACTION_FORCEDEL 2
  67. #define LHT_ACTION_VALIDATE 3
  68. #define LHT_ACTION_ADDHANDLE 4
  69. #define LHT_ACTION_DELHANDLE 5
  70. #define LHT_ACTION_MASK 0x0000FFFF
  71. #define LHT_ACTION_LOCKED 0x00010000
  72. #define LHTP_DEREF_NOT_DEL 0x10000000
  73. #define LHTP_HANDLE_CHECKED 0x20000000
  74. //+---------------------------------------------------------------------------
  75. //
  76. // Function: LhtInitialize
  77. //
  78. // Synopsis: Initializes the LHT handle package
  79. //
  80. // Arguments: (none)
  81. //
  82. // History: 2-03-97 RichardW Created
  83. //
  84. // Notes:
  85. //
  86. //----------------------------------------------------------------------------
  87. BOOL
  88. LhtInitialize(
  89. VOID
  90. )
  91. {
  92. return TRUE ;
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Function: LhtCreate
  97. //
  98. // Synopsis: Creates a large handle table. The table is referenced through
  99. // the returned pointer
  100. //
  101. // Arguments: [Flags] -- Flags as defined by handle.hxx
  102. //
  103. // History: 2-03-97 RichardW Created
  104. //
  105. // Notes:
  106. //
  107. //----------------------------------------------------------------------------
  108. PVOID
  109. LhtCreate(
  110. IN ULONG Flags,
  111. IN PVOID HandleTable,
  112. IN PHP_ENUM_CALLBACK_FN Callback
  113. )
  114. {
  115. PLARGE_HANDLE_TABLE Table ;
  116. ULONG i;
  117. if ( HandleTable )
  118. {
  119. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  120. }
  121. else
  122. {
  123. Table = (PLARGE_HANDLE_TABLE) LsapAllocatePrivateHeap( sizeof( LARGE_HANDLE_TABLE ) );
  124. }
  125. if ( Table )
  126. {
  127. Table->Tag = LHT_TAG ;
  128. Table->Flags = 0 ;
  129. Table->Flags = (Flags & HANDLE_PACKAGE_GENERAL_FLAGS);
  130. if ( Flags & HANDLE_PACKAGE_CALLBACK_ON_DELETE )
  131. {
  132. Table->DeleteCallback = Callback ;
  133. }
  134. else
  135. {
  136. Table->DeleteCallback = NULL ;
  137. }
  138. if ( HandleTable )
  139. {
  140. Table->Flags |= LHT_NO_FREE ;
  141. }
  142. Table->Depth = 0 ;
  143. if ( ( Flags & LHT_NO_SERIALIZE ) == 0 )
  144. {
  145. NTSTATUS Status = RtlInitializeCriticalSectionAndSpinCount(
  146. &Table->Lock,
  147. LsaTuningParameters.CritSecSpinCount
  148. );
  149. if (!NT_SUCCESS(Status))
  150. {
  151. if ( !HandleTable )
  152. {
  153. LsapFreePrivateHeap( Table );
  154. }
  155. Table = NULL ;
  156. }
  157. }
  158. }
  159. if ( Table )
  160. {
  161. for ( i = 0 ; i < HANDLE_TABLE_SIZE ; i++ )
  162. {
  163. SmallHandlePackage.Create( Flags | HANDLE_PACKAGE_NO_SERIALIZE,
  164. & Table->Lists[i],
  165. Callback );
  166. }
  167. }
  168. return Table ;
  169. }
  170. //+---------------------------------------------------------------------------
  171. //
  172. // Function: LhtpDeleteTable
  173. //
  174. // Synopsis: Delete table worker function
  175. //
  176. // Arguments: [Table] --
  177. // [Callback] --
  178. //
  179. // History: 4-15-97 RichardW Created
  180. //
  181. // Notes:
  182. //
  183. //----------------------------------------------------------------------------
  184. VOID
  185. LhtpDeleteTable(
  186. PLARGE_HANDLE_TABLE Table,
  187. PHP_ENUM_CALLBACK_FN Callback
  188. )
  189. {
  190. ULONG Index ;
  191. PSEC_HANDLE_ENTRY Entry ;
  192. PLIST_ENTRY Scan ;
  193. LhtLockTable( Table );
  194. for ( Index = 0 ; Index < HANDLE_TABLE_SIZE ; Index++ )
  195. {
  196. if ( Table->Lists[Index].Flags & LHT_SUB_TABLE )
  197. {
  198. LhtpDeleteTable( (PLARGE_HANDLE_TABLE) Table->Lists[Index].List.Flink,
  199. Callback );
  200. }
  201. else
  202. {
  203. SmallHandlePackage.Delete( &Table->Lists[ Index ], Callback );
  204. }
  205. }
  206. LhtUnlockTable( Table );
  207. if ( (Table->Flags & LHT_NO_SERIALIZE) == 0 )
  208. {
  209. RtlDeleteCriticalSection( &Table->Lock );
  210. }
  211. if ( ( Table->Flags & LHT_NO_FREE ) == 0 )
  212. {
  213. LsapFreePrivateHeap( Table );
  214. }
  215. }
  216. //+---------------------------------------------------------------------------
  217. //
  218. // Function: LhtDelete
  219. //
  220. // Synopsis: Delete a table
  221. //
  222. // Arguments: [HandleTable] --
  223. // [Callback] --
  224. //
  225. // History: 4-15-97 RichardW Created
  226. //
  227. // Notes:
  228. //
  229. //----------------------------------------------------------------------------
  230. BOOL
  231. LhtDelete(
  232. PVOID HandleTable,
  233. PHP_ENUM_CALLBACK_FN Callback
  234. )
  235. {
  236. PLARGE_HANDLE_TABLE Table ;
  237. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  238. LhtLockTable( Table );
  239. Table->Flags |= LHT_DELETE_PENDING ;
  240. LhtpDeleteTable( Table, Callback );
  241. return TRUE ;
  242. }
  243. //+---------------------------------------------------------------------------
  244. //
  245. // Function: LhtpFindHandle
  246. //
  247. // Synopsis: Worker function that grovels a handle table
  248. //
  249. // Arguments: [HandleTable] -- Table to scan
  250. // [Handle] -- handle to search for
  251. // [Action] -- action to take on the handle record
  252. //
  253. // History: 2-03-97 RichardW Created
  254. //
  255. // Notes:
  256. //
  257. //----------------------------------------------------------------------------
  258. PSEC_HANDLE_ENTRY
  259. LhtpFindHandle(
  260. PVOID HandleTable,
  261. PSecHandle Handle,
  262. ULONG Action,
  263. PBOOL Removed,
  264. PVOID * FinalTable OPTIONAL
  265. )
  266. {
  267. PLARGE_HANDLE_TABLE Table ;
  268. PSEC_HANDLE_ENTRY Entry ;
  269. PLIST_ENTRY Scan ;
  270. ULONG Index ;
  271. BOOL Locked ;
  272. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  273. LhtLockTable( Table );
  274. Entry = NULL ;
  275. while ( TRUE )
  276. {
  277. Index = (ULONG) IndexFromHandle( Table->Depth, Handle );
  278. if ( Table->Lists[ Index ].Flags & LHT_SUB_TABLE )
  279. {
  280. Table = (PLARGE_HANDLE_TABLE) Table->Lists[ Index ].List.Flink ;
  281. continue;
  282. }
  283. Entry = ShtpFindHandle( &Table->Lists[ Index ], Handle, Action, Removed );
  284. if ( FinalTable )
  285. {
  286. *FinalTable = &Table->Lists[ Index ] ;
  287. }
  288. break;
  289. }
  290. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  291. LhtUnlockTable( Table );
  292. return Entry ;
  293. }
  294. //+---------------------------------------------------------------------------
  295. //
  296. // Function: LhtpConvertSmallToLarge
  297. //
  298. // Synopsis: Worker to convert small tables to large
  299. //
  300. // Arguments: [Small] --
  301. // [Large] --
  302. //
  303. // History: 7-08-97 RichardW Created
  304. //
  305. // Notes:
  306. //
  307. //----------------------------------------------------------------------------
  308. BOOL
  309. LhtpConvertSmallToLarge(
  310. PSMALL_HANDLE_TABLE Small,
  311. PLARGE_HANDLE_TABLE Large
  312. )
  313. {
  314. ULONG NewIndex ;
  315. PSEC_HANDLE_ENTRY Entry ;
  316. while ( Entry = ShtpPopHandle( Small ) )
  317. {
  318. NewIndex = (ULONG) IndexFromHandle( Large->Depth, &(Entry->Handle) );
  319. ShtpInsertHandle( &Large->Lists[ NewIndex ], Entry );
  320. }
  321. return TRUE ;
  322. }
  323. //+---------------------------------------------------------------------------
  324. //
  325. // Function: LhtpExpandTable
  326. //
  327. // Synopsis: Expands the given index into its own table
  328. //
  329. // Effects: New table associated with given index
  330. //
  331. // Arguments: [Table] -- Source table
  332. // [Index] -- Source index
  333. //
  334. // Requires: Table must be write-locked
  335. //
  336. // History: 1-31-97 RichardW Created
  337. //
  338. // Notes:
  339. //
  340. //----------------------------------------------------------------------------
  341. BOOL
  342. LhtpExpandTable(
  343. PLARGE_HANDLE_TABLE Table,
  344. ULONG Index
  345. )
  346. {
  347. PLARGE_HANDLE_TABLE NewTable ;
  348. PLIST_ENTRY List;
  349. ULONG NewFlags ;
  350. NewFlags = HANDLE_PACKAGE_NO_SERIALIZE ;
  351. if ( Table->DeleteCallback )
  352. {
  353. NewFlags |= HANDLE_PACKAGE_CALLBACK_ON_DELETE ;
  354. }
  355. NewTable = (PLARGE_HANDLE_TABLE) LhtCreate( NewFlags |
  356. LHT_CHILD,
  357. NULL,
  358. Table->DeleteCallback );
  359. if ( !NewTable )
  360. {
  361. return FALSE ;
  362. }
  363. NewTable->Depth = Table->Depth + 1 ;
  364. NewTable->Parent = Table ;
  365. NewTable->IndexOfParent = Index ;
  366. LhtpConvertSmallToLarge( &Table->Lists[ Index ], NewTable );
  367. Table->Lists[ Index ].List.Flink = (PLIST_ENTRY) NewTable ;
  368. Table->Lists[ Index ].Flags = LHT_SUB_TABLE ;
  369. return TRUE ;
  370. }
  371. //+---------------------------------------------------------------------------
  372. //
  373. // Function: LhtConvertSmallToLarge
  374. //
  375. // Synopsis: Converts a small handle table to a large one
  376. //
  377. // Arguments: [Small] --
  378. //
  379. // History: 7-08-97 RichardW Created
  380. //
  381. // Notes:
  382. //
  383. //----------------------------------------------------------------------------
  384. PVOID
  385. LhtConvertSmallToLarge(
  386. PVOID Small
  387. )
  388. {
  389. PLARGE_HANDLE_TABLE Large ;
  390. PSMALL_HANDLE_TABLE SmallTable = (PSMALL_HANDLE_TABLE) Small ;
  391. PULONG Tag ;
  392. Tag = (PULONG) Small ;
  393. if ( *Tag == LHT_TAG )
  394. {
  395. return Small ;
  396. }
  397. if ( *Tag != SHT_TAG )
  398. {
  399. return NULL ;
  400. }
  401. Large = (PLARGE_HANDLE_TABLE) LhtCreate( (SmallTable->DeleteCallback ?
  402. HANDLE_PACKAGE_CALLBACK_ON_DELETE : 0),
  403. NULL,
  404. SmallTable->DeleteCallback );
  405. if ( Large )
  406. {
  407. LhtpConvertSmallToLarge( SmallTable, Large );
  408. ShtDelete( Small, NULL );
  409. return Large ;
  410. }
  411. return NULL ;
  412. }
  413. //+---------------------------------------------------------------------------
  414. //
  415. // Function: LhtAddHandle
  416. //
  417. // Synopsis: Add a handle to a handle table
  418. //
  419. // Arguments: [HandleTable] -- Table to add the handle to
  420. // [Handle] -- Handle to add
  421. //
  422. // History: 2-03-97 RichardW Created
  423. //
  424. // Notes:
  425. //
  426. //----------------------------------------------------------------------------
  427. BOOL
  428. LhtAddHandle(
  429. PVOID HandleTable,
  430. PSecHandle Handle,
  431. PVOID Context,
  432. ULONG Flags
  433. )
  434. {
  435. PSEC_HANDLE_ENTRY Entry ;
  436. PLARGE_HANDLE_TABLE Table ;
  437. ULONG Index ;
  438. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  439. LhtLockTable( Table );
  440. Entry = LhtpFindHandle( HandleTable,
  441. Handle,
  442. LHT_ACTION_ADDHANDLE,
  443. NULL,
  444. NULL );
  445. if ( Entry )
  446. {
  447. LhtUnlockTable( Table );
  448. return TRUE ;
  449. }
  450. //
  451. // No entry, need to insert one.
  452. //
  453. while ( TRUE )
  454. {
  455. Index = (ULONG) IndexFromHandle( Table->Depth, Handle );
  456. if ( Table->Lists[ Index ].Flags & LHT_SUB_TABLE )
  457. {
  458. Table = (PLARGE_HANDLE_TABLE) Table->Lists[ Index ].List.Flink ;
  459. continue;
  460. }
  461. if(SmallHandlePackage.AddHandle( &Table->Lists[ Index ], Handle, Context, Flags ))
  462. {
  463. if ( Table->Lists[ Index ].Count > HANDLE_SPLIT_THRESHOLD )
  464. {
  465. LhtpExpandTable( Table, Index );
  466. }
  467. break;
  468. }
  469. LhtUnlockTable( (PLARGE_HANDLE_TABLE)HandleTable );
  470. return FALSE;
  471. }
  472. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  473. Table->Count++;
  474. LhtUnlockTable( Table );
  475. return TRUE ;
  476. }
  477. //+---------------------------------------------------------------------------
  478. //
  479. // Function: LhtDeleteHandle
  480. //
  481. // Synopsis: Delete a handle from the table
  482. //
  483. // Arguments: [HandleTable] -- Table
  484. // [Handle] -- Handle to delete
  485. // [Force] -- Force delete, even if handle is not ref'd to zero
  486. //
  487. // History: 2-03-97 RichardW Created
  488. //
  489. // Notes:
  490. //
  491. //----------------------------------------------------------------------------
  492. BOOL
  493. LhtDeleteHandle(
  494. PVOID HandleTable,
  495. PSecHandle Handle,
  496. ULONG Options
  497. )
  498. {
  499. PSEC_HANDLE_ENTRY Entry ;
  500. PLARGE_HANDLE_TABLE Table ;
  501. BOOL Removed;
  502. ULONG Action ;
  503. if ( Options & DELHANDLE_FORCE )
  504. {
  505. Action = LHT_ACTION_FORCEDEL ;
  506. }
  507. else if ( Options & LHTP_DEREF_NOT_DEL )
  508. {
  509. Action = LHT_ACTION_DELREF | LHTP_HANDLE_CHECKED ;
  510. }
  511. else
  512. {
  513. Action = LHT_ACTION_DELHANDLE ;
  514. }
  515. Entry = LhtpFindHandle( HandleTable,
  516. Handle,
  517. Action,
  518. &Removed,
  519. NULL );
  520. if ( Entry )
  521. {
  522. if ( Removed )
  523. {
  524. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  525. LhtLockTable( Table );
  526. Table->Count--;
  527. LhtUnlockTable( Table );
  528. if ( (Table->DeleteCallback) &&
  529. ((Options & DELHANDLE_NO_CALLBACK) == 0 ) &&
  530. ((Entry->Flags & SEC_HANDLE_FLAG_NO_CALLBACK ) == 0 ) )
  531. {
  532. Table->DeleteCallback(
  533. &Entry->Handle,
  534. Entry->Context,
  535. Entry->HandleIssuedCount // Entry->RefCount
  536. );
  537. }
  538. if ( ( Entry->Flags & SEC_HANDLE_FLAG_DELETE_PENDING ) == 0 )
  539. {
  540. LsapFreePrivateHeap( Entry );
  541. }
  542. }
  543. return TRUE ;
  544. }
  545. return FALSE ;
  546. }
  547. //+---------------------------------------------------------------------------
  548. //
  549. // Function: LhtValidateHandle
  550. //
  551. // Synopsis: Validate that a handle is within the table
  552. //
  553. // Arguments: [HandleTable] --
  554. // [Handle] --
  555. //
  556. // History: 2-03-97 RichardW Created
  557. //
  558. // Notes:
  559. //
  560. //----------------------------------------------------------------------------
  561. BOOL
  562. LhtValidateHandle(
  563. PVOID HandleTable,
  564. PSecHandle Handle,
  565. BOOL Deref
  566. )
  567. {
  568. PSEC_HANDLE_ENTRY Entry ;
  569. PLARGE_HANDLE_TABLE Table ;
  570. BOOL Removed ;
  571. Entry = LhtpFindHandle(
  572. HandleTable,
  573. Handle,
  574. (Deref ? LHT_ACTION_DELHANDLE : LHT_ACTION_VALIDATE),
  575. &Removed,
  576. NULL );
  577. if ( Entry )
  578. {
  579. if ( Removed )
  580. {
  581. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  582. LhtLockTable( Table );
  583. Table->Count--;
  584. LhtUnlockTable( Table );
  585. if ( ( Table->DeleteCallback ) &&
  586. ( ( Entry->Flags & SEC_HANDLE_FLAG_NO_CALLBACK) == 0 ) )
  587. {
  588. Table->DeleteCallback(
  589. &Entry->Handle,
  590. Entry->Context,
  591. Entry->HandleIssuedCount // Entry->RefCount
  592. );
  593. }
  594. if ( ( Entry->Flags & SEC_HANDLE_FLAG_DELETE_PENDING ) == 0 )
  595. {
  596. LsapFreePrivateHeap( Entry );
  597. }
  598. }
  599. return TRUE ;
  600. }
  601. else
  602. {
  603. return FALSE ;
  604. }
  605. }
  606. PVOID
  607. LhtRefHandle(
  608. PVOID HandleTable,
  609. PSecHandle Handle
  610. )
  611. {
  612. PSEC_HANDLE_ENTRY Entry ;
  613. Entry = LhtpFindHandle(
  614. HandleTable,
  615. Handle,
  616. LHT_ACTION_ADDREF,
  617. NULL,
  618. NULL );
  619. return Entry ;
  620. }
  621. VOID
  622. LhtDerefHandleKey(
  623. PVOID HandleTable,
  624. PVOID HandleKey
  625. )
  626. {
  627. PSEC_HANDLE_ENTRY Entry = (PSEC_HANDLE_ENTRY) HandleKey ;
  628. LhtDeleteHandle( HandleTable, &Entry->Handle, LHTP_DEREF_NOT_DEL );
  629. }
  630. PVOID
  631. LhtGetHandleContext(
  632. PVOID HandleTable,
  633. PSecHandle Handle
  634. )
  635. {
  636. PSEC_HANDLE_ENTRY Entry ;
  637. Entry = LhtpFindHandle(
  638. HandleTable,
  639. Handle,
  640. LHT_ACTION_ADDREF,
  641. NULL,
  642. NULL );
  643. if ( Entry )
  644. {
  645. return Entry->Context ;
  646. }
  647. else
  648. {
  649. return NULL ;
  650. }
  651. }
  652. BOOL
  653. LhtReleaseContext(
  654. PVOID HandleTable,
  655. PSecHandle Handle
  656. )
  657. {
  658. PSEC_HANDLE_ENTRY Entry ;
  659. PLARGE_HANDLE_TABLE Table ;
  660. BOOL Removed;
  661. Entry = LhtpFindHandle( HandleTable,
  662. Handle,
  663. LHT_ACTION_DELREF,
  664. &Removed,
  665. NULL );
  666. if ( Entry )
  667. {
  668. if ( Removed )
  669. {
  670. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  671. LhtLockTable( Table );
  672. Table->Count--;
  673. LhtUnlockTable( Table );
  674. if ( ( Table->DeleteCallback ) &&
  675. ( ( Entry->Flags & SEC_HANDLE_FLAG_NO_CALLBACK ) == 0 ) )
  676. {
  677. Table->DeleteCallback( &Entry->Handle, Entry->Context, Entry->RefCount );
  678. }
  679. if ( ( Entry->Flags & SEC_HANDLE_FLAG_DELETE_PENDING ) == 0 )
  680. {
  681. LsapFreePrivateHeap( Entry );
  682. }
  683. }
  684. return TRUE ;
  685. }
  686. return FALSE ;
  687. }