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.

834 lines
19 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 = RtlInitializeCriticalSection( &Table->Lock );
  146. if (!NT_SUCCESS(Status))
  147. {
  148. if ( !HandleTable )
  149. {
  150. LsapFreePrivateHeap( Table );
  151. }
  152. Table = NULL ;
  153. }
  154. }
  155. }
  156. if ( Table )
  157. {
  158. for ( i = 0 ; i < HANDLE_TABLE_SIZE ; i++ )
  159. {
  160. SmallHandlePackage.Create( Flags | HANDLE_PACKAGE_NO_SERIALIZE,
  161. & Table->Lists[i],
  162. Callback );
  163. }
  164. }
  165. return Table ;
  166. }
  167. //+---------------------------------------------------------------------------
  168. //
  169. // Function: LhtpDeleteTable
  170. //
  171. // Synopsis: Delete table worker function
  172. //
  173. // Arguments: [Table] --
  174. // [Callback] --
  175. //
  176. // History: 4-15-97 RichardW Created
  177. //
  178. // Notes:
  179. //
  180. //----------------------------------------------------------------------------
  181. VOID
  182. LhtpDeleteTable(
  183. PLARGE_HANDLE_TABLE Table,
  184. PHP_ENUM_CALLBACK_FN Callback
  185. )
  186. {
  187. ULONG Index ;
  188. PSEC_HANDLE_ENTRY Entry ;
  189. PLIST_ENTRY Scan ;
  190. LhtLockTable( Table );
  191. for ( Index = 0 ; Index < HANDLE_TABLE_SIZE ; Index++ )
  192. {
  193. if ( Table->Lists[Index].Flags & LHT_SUB_TABLE )
  194. {
  195. LhtpDeleteTable( (PLARGE_HANDLE_TABLE) Table->Lists[Index].List.Flink,
  196. Callback );
  197. }
  198. else
  199. {
  200. SmallHandlePackage.Delete( &Table->Lists[ Index ], Callback );
  201. }
  202. }
  203. LhtUnlockTable( Table );
  204. if ( (Table->Flags & LHT_NO_SERIALIZE) == 0 )
  205. {
  206. RtlDeleteCriticalSection( &Table->Lock );
  207. }
  208. if ( ( Table->Flags & LHT_NO_FREE ) == 0 )
  209. {
  210. LsapFreePrivateHeap( Table );
  211. }
  212. }
  213. //+---------------------------------------------------------------------------
  214. //
  215. // Function: LhtDelete
  216. //
  217. // Synopsis: Delete a table
  218. //
  219. // Arguments: [HandleTable] --
  220. // [Callback] --
  221. //
  222. // History: 4-15-97 RichardW Created
  223. //
  224. // Notes:
  225. //
  226. //----------------------------------------------------------------------------
  227. BOOL
  228. LhtDelete(
  229. PVOID HandleTable,
  230. PHP_ENUM_CALLBACK_FN Callback
  231. )
  232. {
  233. PLARGE_HANDLE_TABLE Table ;
  234. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  235. LhtLockTable( Table );
  236. Table->Flags |= LHT_DELETE_PENDING ;
  237. LhtpDeleteTable( Table, Callback );
  238. return TRUE ;
  239. }
  240. //+---------------------------------------------------------------------------
  241. //
  242. // Function: LhtpFindHandle
  243. //
  244. // Synopsis: Worker function that grovels a handle table
  245. //
  246. // Arguments: [HandleTable] -- Table to scan
  247. // [Handle] -- handle to search for
  248. // [Action] -- action to take on the handle record
  249. //
  250. // History: 2-03-97 RichardW Created
  251. //
  252. // Notes:
  253. //
  254. //----------------------------------------------------------------------------
  255. PSEC_HANDLE_ENTRY
  256. LhtpFindHandle(
  257. PVOID HandleTable,
  258. PSecHandle Handle,
  259. ULONG Action,
  260. PBOOL Removed,
  261. PVOID * FinalTable OPTIONAL
  262. )
  263. {
  264. PLARGE_HANDLE_TABLE Table ;
  265. PSEC_HANDLE_ENTRY Entry ;
  266. PLIST_ENTRY Scan ;
  267. ULONG Index ;
  268. BOOL Locked ;
  269. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  270. LhtLockTable( Table );
  271. Entry = NULL ;
  272. while ( TRUE )
  273. {
  274. Index = (ULONG) IndexFromHandle( Table->Depth, Handle );
  275. if ( Table->Lists[ Index ].Flags & LHT_SUB_TABLE )
  276. {
  277. Table = (PLARGE_HANDLE_TABLE) Table->Lists[ Index ].List.Flink ;
  278. continue;
  279. }
  280. Entry = ShtpFindHandle( &Table->Lists[ Index ], Handle, Action, Removed );
  281. if ( FinalTable )
  282. {
  283. *FinalTable = &Table->Lists[ Index ] ;
  284. }
  285. break;
  286. }
  287. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  288. LhtUnlockTable( Table );
  289. return Entry ;
  290. }
  291. //+---------------------------------------------------------------------------
  292. //
  293. // Function: LhtpConvertSmallToLarge
  294. //
  295. // Synopsis: Worker to convert small tables to large
  296. //
  297. // Arguments: [Small] --
  298. // [Large] --
  299. //
  300. // History: 7-08-97 RichardW Created
  301. //
  302. // Notes:
  303. //
  304. //----------------------------------------------------------------------------
  305. BOOL
  306. LhtpConvertSmallToLarge(
  307. PSMALL_HANDLE_TABLE Small,
  308. PLARGE_HANDLE_TABLE Large
  309. )
  310. {
  311. ULONG NewIndex ;
  312. PSEC_HANDLE_ENTRY Entry ;
  313. while ( Entry = ShtpPopHandle( Small ) )
  314. {
  315. NewIndex = (ULONG) IndexFromHandle( Large->Depth, &(Entry->Handle) );
  316. ShtpInsertHandle( &Large->Lists[ NewIndex ], Entry );
  317. }
  318. return TRUE ;
  319. }
  320. //+---------------------------------------------------------------------------
  321. //
  322. // Function: LhtpExpandTable
  323. //
  324. // Synopsis: Expands the given index into its own table
  325. //
  326. // Effects: New table associated with given index
  327. //
  328. // Arguments: [Table] -- Source table
  329. // [Index] -- Source index
  330. //
  331. // Requires: Table must be write-locked
  332. //
  333. // History: 1-31-97 RichardW Created
  334. //
  335. // Notes:
  336. //
  337. //----------------------------------------------------------------------------
  338. BOOL
  339. LhtpExpandTable(
  340. PLARGE_HANDLE_TABLE Table,
  341. ULONG Index
  342. )
  343. {
  344. PLARGE_HANDLE_TABLE NewTable ;
  345. PLIST_ENTRY List;
  346. ULONG NewFlags ;
  347. NewFlags = HANDLE_PACKAGE_NO_SERIALIZE ;
  348. if ( Table->DeleteCallback )
  349. {
  350. NewFlags |= HANDLE_PACKAGE_CALLBACK_ON_DELETE ;
  351. }
  352. NewTable = (PLARGE_HANDLE_TABLE) LhtCreate( NewFlags |
  353. LHT_CHILD,
  354. NULL,
  355. Table->DeleteCallback );
  356. if ( !NewTable )
  357. {
  358. return FALSE ;
  359. }
  360. NewTable->Depth = Table->Depth + 1 ;
  361. NewTable->Parent = Table ;
  362. NewTable->IndexOfParent = Index ;
  363. LhtpConvertSmallToLarge( &Table->Lists[ Index ], NewTable );
  364. Table->Lists[ Index ].List.Flink = (PLIST_ENTRY) NewTable ;
  365. Table->Lists[ Index ].Flags = LHT_SUB_TABLE ;
  366. return TRUE ;
  367. }
  368. //+---------------------------------------------------------------------------
  369. //
  370. // Function: LhtConvertSmallToLarge
  371. //
  372. // Synopsis: Converts a small handle table to a large one
  373. //
  374. // Arguments: [Small] --
  375. //
  376. // History: 7-08-97 RichardW Created
  377. //
  378. // Notes:
  379. //
  380. //----------------------------------------------------------------------------
  381. PVOID
  382. LhtConvertSmallToLarge(
  383. PVOID Small
  384. )
  385. {
  386. PLARGE_HANDLE_TABLE Large ;
  387. PSMALL_HANDLE_TABLE SmallTable = (PSMALL_HANDLE_TABLE) Small ;
  388. PULONG Tag ;
  389. Tag = (PULONG) Small ;
  390. if ( *Tag == LHT_TAG )
  391. {
  392. return Small ;
  393. }
  394. if ( *Tag != SHT_TAG )
  395. {
  396. return NULL ;
  397. }
  398. Large = (PLARGE_HANDLE_TABLE) LhtCreate( (SmallTable->DeleteCallback ?
  399. HANDLE_PACKAGE_CALLBACK_ON_DELETE : 0),
  400. NULL,
  401. SmallTable->DeleteCallback );
  402. if ( Large )
  403. {
  404. LhtpConvertSmallToLarge( SmallTable, Large );
  405. ShtDelete( Small, NULL );
  406. return Large ;
  407. }
  408. return NULL ;
  409. }
  410. //+---------------------------------------------------------------------------
  411. //
  412. // Function: LhtAddHandle
  413. //
  414. // Synopsis: Add a handle to a handle table
  415. //
  416. // Arguments: [HandleTable] -- Table to add the handle to
  417. // [Handle] -- Handle to add
  418. //
  419. // History: 2-03-97 RichardW Created
  420. //
  421. // Notes:
  422. //
  423. //----------------------------------------------------------------------------
  424. BOOL
  425. LhtAddHandle(
  426. PVOID HandleTable,
  427. PSecHandle Handle,
  428. PVOID Context,
  429. ULONG Flags
  430. )
  431. {
  432. PSEC_HANDLE_ENTRY Entry ;
  433. PLARGE_HANDLE_TABLE Table ;
  434. ULONG Index ;
  435. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  436. LhtLockTable( Table );
  437. Entry = LhtpFindHandle( HandleTable,
  438. Handle,
  439. LHT_ACTION_ADDHANDLE,
  440. NULL,
  441. NULL );
  442. if ( Entry )
  443. {
  444. LhtUnlockTable( Table );
  445. return TRUE ;
  446. }
  447. //
  448. // No entry, need to insert one.
  449. //
  450. while ( TRUE )
  451. {
  452. Index = (ULONG) IndexFromHandle( Table->Depth, Handle );
  453. if ( Table->Lists[ Index ].Flags & LHT_SUB_TABLE )
  454. {
  455. Table = (PLARGE_HANDLE_TABLE) Table->Lists[ Index ].List.Flink ;
  456. continue;
  457. }
  458. if(SmallHandlePackage.AddHandle( &Table->Lists[ Index ], Handle, Context, Flags ))
  459. {
  460. if ( Table->Lists[ Index ].Count > HANDLE_SPLIT_THRESHOLD )
  461. {
  462. LhtpExpandTable( Table, Index );
  463. }
  464. break;
  465. }
  466. LhtUnlockTable( (PLARGE_HANDLE_TABLE)HandleTable );
  467. return FALSE;
  468. }
  469. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  470. Table->Count++;
  471. LhtUnlockTable( Table );
  472. return TRUE ;
  473. }
  474. //+---------------------------------------------------------------------------
  475. //
  476. // Function: LhtDeleteHandle
  477. //
  478. // Synopsis: Delete a handle from the table
  479. //
  480. // Arguments: [HandleTable] -- Table
  481. // [Handle] -- Handle to delete
  482. // [Force] -- Force delete, even if handle is not ref'd to zero
  483. //
  484. // History: 2-03-97 RichardW Created
  485. //
  486. // Notes:
  487. //
  488. //----------------------------------------------------------------------------
  489. BOOL
  490. LhtDeleteHandle(
  491. PVOID HandleTable,
  492. PSecHandle Handle,
  493. ULONG Options
  494. )
  495. {
  496. PSEC_HANDLE_ENTRY Entry ;
  497. PLARGE_HANDLE_TABLE Table ;
  498. BOOL Removed;
  499. ULONG Action ;
  500. if ( Options & DELHANDLE_FORCE )
  501. {
  502. Action = LHT_ACTION_FORCEDEL ;
  503. }
  504. else if ( Options & LHTP_DEREF_NOT_DEL )
  505. {
  506. Action = LHT_ACTION_DELREF | LHTP_HANDLE_CHECKED ;
  507. }
  508. else
  509. {
  510. Action = LHT_ACTION_DELHANDLE ;
  511. }
  512. Entry = LhtpFindHandle( HandleTable,
  513. Handle,
  514. Action,
  515. &Removed,
  516. NULL );
  517. if ( Entry )
  518. {
  519. if ( Removed )
  520. {
  521. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  522. LhtLockTable( Table );
  523. Table->Count--;
  524. LhtUnlockTable( Table );
  525. if ( (Table->DeleteCallback) &&
  526. ((Options & DELHANDLE_NO_CALLBACK) == 0 ) &&
  527. ((Entry->Flags & SEC_HANDLE_FLAG_NO_CALLBACK ) == 0 ) )
  528. {
  529. Table->DeleteCallback(
  530. &Entry->Handle,
  531. Entry->Context,
  532. Entry->HandleIssuedCount // Entry->RefCount
  533. );
  534. }
  535. if ( ( Entry->Flags & SEC_HANDLE_FLAG_DELETE_PENDING ) == 0 )
  536. {
  537. LsapFreePrivateHeap( Entry );
  538. }
  539. }
  540. return TRUE ;
  541. }
  542. return FALSE ;
  543. }
  544. //+---------------------------------------------------------------------------
  545. //
  546. // Function: LhtValidateHandle
  547. //
  548. // Synopsis: Validate that a handle is within the table
  549. //
  550. // Arguments: [HandleTable] --
  551. // [Handle] --
  552. //
  553. // History: 2-03-97 RichardW Created
  554. //
  555. // Notes:
  556. //
  557. //----------------------------------------------------------------------------
  558. BOOL
  559. LhtValidateHandle(
  560. PVOID HandleTable,
  561. PSecHandle Handle,
  562. BOOL Deref
  563. )
  564. {
  565. PSEC_HANDLE_ENTRY Entry ;
  566. PLARGE_HANDLE_TABLE Table ;
  567. BOOL Removed ;
  568. Entry = LhtpFindHandle(
  569. HandleTable,
  570. Handle,
  571. (Deref ? LHT_ACTION_DELHANDLE : LHT_ACTION_VALIDATE),
  572. &Removed,
  573. NULL );
  574. if ( Entry )
  575. {
  576. if ( Removed )
  577. {
  578. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  579. LhtLockTable( Table );
  580. Table->Count--;
  581. LhtUnlockTable( Table );
  582. if ( ( Table->DeleteCallback ) &&
  583. ( ( Entry->Flags & SEC_HANDLE_FLAG_NO_CALLBACK) == 0 ) )
  584. {
  585. Table->DeleteCallback(
  586. &Entry->Handle,
  587. Entry->Context,
  588. Entry->HandleIssuedCount // Entry->RefCount
  589. );
  590. }
  591. if ( ( Entry->Flags & SEC_HANDLE_FLAG_DELETE_PENDING ) == 0 )
  592. {
  593. LsapFreePrivateHeap( Entry );
  594. }
  595. }
  596. return TRUE ;
  597. }
  598. else
  599. {
  600. return FALSE ;
  601. }
  602. }
  603. PVOID
  604. LhtRefHandle(
  605. PVOID HandleTable,
  606. PSecHandle Handle
  607. )
  608. {
  609. PSEC_HANDLE_ENTRY Entry ;
  610. Entry = LhtpFindHandle(
  611. HandleTable,
  612. Handle,
  613. LHT_ACTION_ADDREF,
  614. NULL,
  615. NULL );
  616. return Entry ;
  617. }
  618. VOID
  619. LhtDerefHandleKey(
  620. PVOID HandleTable,
  621. PVOID HandleKey
  622. )
  623. {
  624. PSEC_HANDLE_ENTRY Entry = (PSEC_HANDLE_ENTRY) HandleKey ;
  625. LhtDeleteHandle( HandleTable, &Entry->Handle, LHTP_DEREF_NOT_DEL );
  626. }
  627. PVOID
  628. LhtGetHandleContext(
  629. PVOID HandleTable,
  630. PSecHandle Handle
  631. )
  632. {
  633. PSEC_HANDLE_ENTRY Entry ;
  634. Entry = LhtpFindHandle(
  635. HandleTable,
  636. Handle,
  637. LHT_ACTION_ADDREF,
  638. NULL,
  639. NULL );
  640. if ( Entry )
  641. {
  642. return Entry->Context ;
  643. }
  644. else
  645. {
  646. return NULL ;
  647. }
  648. }
  649. BOOL
  650. LhtReleaseContext(
  651. PVOID HandleTable,
  652. PSecHandle Handle
  653. )
  654. {
  655. PSEC_HANDLE_ENTRY Entry ;
  656. PLARGE_HANDLE_TABLE Table ;
  657. BOOL Removed;
  658. Entry = LhtpFindHandle( HandleTable,
  659. Handle,
  660. LHT_ACTION_DELREF,
  661. &Removed,
  662. NULL );
  663. if ( Entry )
  664. {
  665. if ( Removed )
  666. {
  667. Table = (PLARGE_HANDLE_TABLE) HandleTable ;
  668. LhtLockTable( Table );
  669. Table->Count--;
  670. LhtUnlockTable( Table );
  671. if ( ( Table->DeleteCallback ) &&
  672. ( ( Entry->Flags & SEC_HANDLE_FLAG_NO_CALLBACK ) == 0 ) )
  673. {
  674. Table->DeleteCallback( &Entry->Handle, Entry->Context, Entry->RefCount );
  675. }
  676. if ( ( Entry->Flags & SEC_HANDLE_FLAG_DELETE_PENDING ) == 0 )
  677. {
  678. LsapFreePrivateHeap( Entry );
  679. }
  680. }
  681. return TRUE ;
  682. }
  683. return FALSE ;
  684. }