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.

1381 lines
29 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. frstable.c
  5. Abstract:
  6. These routines manage the tables used by the FRS.
  7. Author:
  8. Billy J. Fuller 19-Apr-1997
  9. Environment
  10. User mode winnt
  11. --*/
  12. #include <ntreppch.h>
  13. #pragma hdrstop
  14. #define DEBSUB "FRSTABLE:"
  15. #include <frs.h>
  16. PVOID
  17. GTabAllocTableMem(
  18. IN PRTL_GENERIC_TABLE Table,
  19. IN DWORD NodeSize
  20. )
  21. /*++
  22. Routine Description:
  23. Allocate space for a table entry. The entry includes the user-defined
  24. struct and some overhead used by the generic table routines. The
  25. generic table routines call this function when they need memory.
  26. Arguments:
  27. Table - Address of the table (not used).
  28. NodeSize - Bytes to allocate
  29. Return Value:
  30. Address of newly allocated memory.
  31. --*/
  32. {
  33. return FrsAlloc(NodeSize);
  34. }
  35. VOID
  36. GTabFreeTableMem(
  37. IN PRTL_GENERIC_TABLE Table,
  38. IN PVOID Buffer
  39. )
  40. /*++
  41. Routine Description:
  42. Free the space allocated by GTAlloc(). The generic table
  43. routines call this function to free memory.
  44. Arguments:
  45. Table - Address of the table (not used).
  46. Buffer - Address of previously allocated memory
  47. Return Value:
  48. None.
  49. --*/
  50. {
  51. FrsFree(Buffer);
  52. }
  53. RTL_GENERIC_COMPARE_RESULTS
  54. GTabCmpTableEntry(
  55. IN PRTL_GENERIC_TABLE Table,
  56. IN PVOID TableEntry1,
  57. IN PVOID TableEntry2
  58. )
  59. /*++
  60. Routine Description:
  61. Compare two entries in the table for guid/names.
  62. Arguments:
  63. Table - Address of the table (not used).
  64. Entry1 - PGEN_ENTRY
  65. Entry2 - PGEN_ENTRY
  66. Return Value:
  67. <0 First < Second
  68. =0 First == Second
  69. >0 First > Second
  70. --*/
  71. {
  72. INT Cmp;
  73. PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1;
  74. PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
  75. //
  76. // Primary key must be present
  77. //
  78. FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
  79. //
  80. // Compare primary keys
  81. //
  82. Cmp = memcmp(Entry1->Key1, Entry2->Key1, sizeof(GUID));
  83. if (Cmp < 0) {
  84. return (GenericLessThan);
  85. }
  86. if (Cmp > 0) {
  87. return (GenericGreaterThan);
  88. }
  89. //
  90. // No second key; done
  91. //
  92. if (!Entry1->Key2 || !Entry2->Key2)
  93. return GenericEqual;
  94. //
  95. // Compare secondary keys
  96. //
  97. Cmp = _wcsicmp(Entry1->Key2, Entry2->Key2);
  98. if (Cmp < 0) {
  99. return (GenericLessThan);
  100. }
  101. if (Cmp > 0){
  102. return (GenericGreaterThan);
  103. }
  104. return (GenericEqual);
  105. }
  106. RTL_GENERIC_COMPARE_RESULTS
  107. GTabCmpTableNumberEntry(
  108. IN PRTL_GENERIC_TABLE Table,
  109. IN PVOID TableEntry1,
  110. IN PVOID TableEntry2
  111. )
  112. /*++
  113. Routine Description:
  114. Compare two entries in the table for number
  115. Arguments:
  116. Table - Address of the table (not used).
  117. Entry1 - PGEN_ENTRY
  118. Entry2 - PGEN_ENTRY
  119. Return Value:
  120. <0 First < Second
  121. =0 First == Second
  122. >0 First > Second
  123. --*/
  124. {
  125. INT Cmp;
  126. PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1;
  127. PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
  128. //
  129. // Primary key must be present
  130. //
  131. FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
  132. //
  133. // Compare primary keys
  134. //
  135. Cmp = memcmp(Entry1->Key1, Entry2->Key1, sizeof(ULONG));
  136. if (Cmp < 0) {
  137. return (GenericLessThan);
  138. }
  139. if (Cmp > 0){
  140. return (GenericGreaterThan);
  141. }
  142. return GenericEqual;
  143. }
  144. RTL_GENERIC_COMPARE_RESULTS
  145. GTabCmpTableFileTimeEntry(
  146. IN PRTL_GENERIC_TABLE Table,
  147. IN PVOID TableEntry1,
  148. IN PVOID TableEntry2
  149. )
  150. /*++
  151. Routine Description:
  152. Compare two entries in the table for number
  153. Arguments:
  154. Table - Address of the table (not used).
  155. Entry1 - PGEN_ENTRY
  156. Entry2 - PGEN_ENTRY
  157. Return Value:
  158. <0 First < Second
  159. =0 First == Second
  160. >0 First > Second
  161. --*/
  162. {
  163. INT Cmp;
  164. PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1;
  165. PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
  166. //
  167. // Primary key must be present
  168. //
  169. FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
  170. //
  171. // Compare primary keys
  172. //
  173. Cmp = CompareFileTime((PFILETIME)Entry1->Key1, (PFILETIME)Entry2->Key1);
  174. if (Cmp < 0) {
  175. return (GenericLessThan);
  176. }
  177. if (Cmp > 0){
  178. return (GenericGreaterThan);
  179. }
  180. return GenericEqual;
  181. }
  182. RTL_GENERIC_COMPARE_RESULTS
  183. GTabCmpTableStringAndBoolEntry(
  184. IN PRTL_GENERIC_TABLE Table,
  185. IN PVOID TableEntry1,
  186. IN PVOID TableEntry2
  187. )
  188. /*++
  189. Routine Description:
  190. Compare two entries in the table for data with strings used as key.
  191. Arguments:
  192. Table - Address of the table (not used).
  193. Entry1 - PGEN_ENTRY
  194. Entry2 - PGEN_ENTRY
  195. Return Value:
  196. <0 First < Second
  197. =0 First == Second
  198. >0 First > Second
  199. --*/
  200. {
  201. INT Cmp;
  202. PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1;
  203. PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
  204. //
  205. // Primary key must be present
  206. //
  207. FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
  208. //
  209. // Compare primary keys
  210. //
  211. Cmp = _wcsicmp((PWCHAR)(Entry1->Key1), (PWCHAR)(Entry2->Key1));
  212. if (Cmp < 0) {
  213. return (GenericLessThan);
  214. }
  215. if (Cmp > 0){
  216. return (GenericGreaterThan);
  217. }
  218. //
  219. // Compare secondary keys if they exist.
  220. //
  221. if ((Entry1->Key2 == NULL) || (Entry2->Key2 == NULL)) {
  222. return GenericEqual;
  223. }
  224. if (*(Entry1->Key2) == *(Entry2->Key2)) {
  225. return GenericEqual;
  226. } else if (*(Entry1->Key2) == FALSE) {
  227. return GenericLessThan;
  228. }
  229. return GenericGreaterThan;
  230. }
  231. RTL_GENERIC_COMPARE_RESULTS
  232. GTabCmpTableStringEntry(
  233. IN PRTL_GENERIC_TABLE Table,
  234. IN PVOID TableEntry1,
  235. IN PVOID TableEntry2
  236. )
  237. /*++
  238. Routine Description:
  239. Compare two entries in the table for data with strings used as key.
  240. Arguments:
  241. Table - Address of the table (not used).
  242. Entry1 - PGEN_ENTRY
  243. Entry2 - PGEN_ENTRY
  244. Return Value:
  245. <0 First < Second
  246. =0 First == Second
  247. >0 First > Second
  248. --*/
  249. {
  250. INT Cmp;
  251. PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1;
  252. PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
  253. //
  254. // Primary key must be present
  255. //
  256. FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
  257. //
  258. // Compare primary keys
  259. //
  260. Cmp = _wcsicmp((PWCHAR)(Entry1->Key1), (PWCHAR)(Entry2->Key1));
  261. if (Cmp < 0) {
  262. return (GenericLessThan);
  263. }
  264. if (Cmp > 0){
  265. return (GenericGreaterThan);
  266. }
  267. //
  268. // Compare secondary keys if they exist.
  269. //
  270. if ((Entry1->Key2 == NULL) || (Entry2->Key2 == NULL)) {
  271. return GenericEqual;
  272. }
  273. Cmp = _wcsicmp(Entry1->Key2, Entry2->Key2);
  274. if (Cmp < 0) {
  275. return (GenericLessThan);
  276. }
  277. if (Cmp > 0){
  278. return (GenericGreaterThan);
  279. }
  280. return GenericEqual;
  281. }
  282. VOID
  283. GTabLockTable(
  284. PGEN_TABLE GTable
  285. )
  286. /*++
  287. Routine Description:
  288. Lock the table
  289. Arguments:
  290. GTable - frs generic table
  291. Return Value:
  292. None.
  293. --*/
  294. {
  295. EnterCriticalSection(&GTable->Critical);
  296. }
  297. VOID
  298. GTabUnLockTable(
  299. PGEN_TABLE GTable
  300. )
  301. /*++
  302. Routine Description:
  303. Unlock the table
  304. Arguments:
  305. GTable - frs generic table
  306. Return Value:
  307. None.
  308. --*/
  309. {
  310. LeaveCriticalSection(&GTable->Critical);
  311. }
  312. PGEN_TABLE
  313. GTabAllocNumberTable(
  314. VOID
  315. )
  316. /*++
  317. Routine Description:
  318. Initialize a generic table + lock for numbers.
  319. Arguments:
  320. None.
  321. Return Value:
  322. None.
  323. --*/
  324. {
  325. PGEN_TABLE GTable;
  326. GTable = FrsAllocType(GEN_TABLE_TYPE);
  327. INITIALIZE_CRITICAL_SECTION(&GTable->Critical);
  328. RtlInitializeGenericTable(&GTable->Table,
  329. GTabCmpTableNumberEntry,
  330. GTabAllocTableMem,
  331. GTabFreeTableMem,
  332. NULL);
  333. return GTable;
  334. }
  335. PGEN_TABLE
  336. GTabAllocFileTimeTable(
  337. VOID
  338. )
  339. /*++
  340. Routine Description:
  341. Initialize a generic table + lock for file time.
  342. Arguments:
  343. None.
  344. Return Value:
  345. None.
  346. --*/
  347. {
  348. PGEN_TABLE GTable;
  349. GTable = FrsAllocType(GEN_TABLE_TYPE);
  350. INITIALIZE_CRITICAL_SECTION(&GTable->Critical);
  351. RtlInitializeGenericTable(&GTable->Table,
  352. GTabCmpTableFileTimeEntry,
  353. GTabAllocTableMem,
  354. GTabFreeTableMem,
  355. NULL);
  356. return GTable;
  357. }
  358. PGEN_TABLE
  359. GTabAllocStringTable(
  360. VOID
  361. )
  362. /*++
  363. Routine Description:
  364. Initialize a generic table + lock for data with strings
  365. used as a key.
  366. Arguments:
  367. None.
  368. Return Value:
  369. None.
  370. --*/
  371. {
  372. PGEN_TABLE GTable;
  373. GTable = FrsAllocType(GEN_TABLE_TYPE);
  374. INITIALIZE_CRITICAL_SECTION(&GTable->Critical);
  375. RtlInitializeGenericTable(&GTable->Table,
  376. GTabCmpTableStringEntry,
  377. GTabAllocTableMem,
  378. GTabFreeTableMem,
  379. NULL);
  380. return GTable;
  381. }
  382. PGEN_TABLE
  383. GTabAllocStringAndBoolTable(
  384. VOID
  385. )
  386. /*++
  387. Routine Description:
  388. Initialize a generic table + lock for data with a string and bool
  389. used as a key.
  390. Arguments:
  391. None.
  392. Return Value:
  393. None.
  394. --*/
  395. {
  396. PGEN_TABLE GTable;
  397. GTable = FrsAllocType(GEN_TABLE_TYPE);
  398. INITIALIZE_CRITICAL_SECTION(&GTable->Critical);
  399. RtlInitializeGenericTable(&GTable->Table,
  400. GTabCmpTableStringAndBoolEntry,
  401. GTabAllocTableMem,
  402. GTabFreeTableMem,
  403. NULL);
  404. return GTable;
  405. }
  406. PGEN_TABLE
  407. GTabAllocTable(
  408. VOID
  409. )
  410. /*++
  411. Routine Description:
  412. Initialize a generic table + lock.
  413. Arguments:
  414. None.
  415. Return Value:
  416. None.
  417. --*/
  418. {
  419. PGEN_TABLE GTable;
  420. GTable = FrsAllocType(GEN_TABLE_TYPE);
  421. INITIALIZE_CRITICAL_SECTION(&GTable->Critical);
  422. RtlInitializeGenericTable(&GTable->Table,
  423. GTabCmpTableEntry,
  424. GTabAllocTableMem,
  425. GTabFreeTableMem,
  426. NULL);
  427. return GTable;
  428. }
  429. VOID
  430. GTabEmptyTableNoLock(
  431. IN PGEN_TABLE GTable,
  432. IN PVOID (*CallerFree)(PVOID)
  433. )
  434. /*++
  435. Routine Description:
  436. Free every entry in the frs generic table. Caller has acquired the table lock.
  437. Arguments:
  438. GTable - frs generic table
  439. CallerFree - The free routine to use to free up the callers datum (optional)
  440. Return Value:
  441. None.
  442. --*/
  443. {
  444. PGEN_ENTRY Entry; // Next entry in table
  445. PGEN_ENTRY Dup; // Next entry in table
  446. PVOID Data;
  447. //
  448. // For every entry in the table
  449. //
  450. while (Entry = RtlEnumerateGenericTable(&GTable->Table, TRUE)) {
  451. //
  452. // Delete the dups
  453. //
  454. while (Dup = Entry->Dups) {
  455. Entry->Dups = Dup->Dups;
  456. if (CallerFree) {
  457. //
  458. // Free up the callers Datum
  459. //
  460. (*CallerFree)(Dup->Data);
  461. }
  462. Dup = FrsFree(Dup);
  463. }
  464. //
  465. // Delete the entry from the table
  466. //
  467. Data = Entry->Data;
  468. RtlDeleteElementGenericTable(&GTable->Table, Entry);
  469. if (CallerFree) {
  470. //
  471. // Free up the callers Datum
  472. //
  473. (*CallerFree)(Data);
  474. }
  475. }
  476. }
  477. VOID
  478. GTabEmptyTable(
  479. IN PGEN_TABLE GTable,
  480. IN PVOID (*CallerFree)(PVOID)
  481. )
  482. /*++
  483. Routine Description:
  484. Free every entry in the frs generic table.
  485. Arguments:
  486. GTable - frs generic table
  487. CallerFree - The free routine to use to free up the callers datum (optional)
  488. Return Value:
  489. None.
  490. --*/
  491. {
  492. GTabLockTable(GTable);
  493. GTabEmptyTableNoLock(GTable, CallerFree);
  494. GTabUnLockTable(GTable);
  495. }
  496. PVOID
  497. GTabFreeTable(
  498. IN PGEN_TABLE GTable,
  499. IN PVOID (*CallerFree)(PVOID)
  500. )
  501. /*++
  502. Routine Description:
  503. Undo the work done by GenTableInitialize.
  504. Arguments:
  505. GTTable - Address of the gen table.
  506. CallerFree - The free routine to use to free up the callers datum (optional)
  507. Return Value:
  508. None.
  509. --*/
  510. {
  511. if (GTable == NULL) {
  512. return NULL;
  513. }
  514. //
  515. // Empty the table
  516. //
  517. GTabEmptyTable(GTable, CallerFree);
  518. DeleteCriticalSection(&GTable->Critical);
  519. return FrsFreeType(GTable);
  520. }
  521. PVOID
  522. GTabLookupNoLock(
  523. IN PGEN_TABLE GTable,
  524. IN GUID *Key1,
  525. IN PWCHAR Key2
  526. )
  527. /*++
  528. Routine Description:
  529. Find the entry in the table.
  530. Arguments:
  531. GTable - frs generic table
  532. Key1 - primary key
  533. Key2 - secondary key (may be NULL)
  534. Return Value:
  535. Data for an entry or NULL
  536. --*/
  537. {
  538. PVOID Data;
  539. PGEN_ENTRY Entry; // entry in table
  540. GEN_ENTRY Key; // Search key
  541. FRS_ASSERT(Key1);
  542. //
  543. // Set up a search key that is suitable for any table
  544. //
  545. Key.Key1 = Key1;
  546. Key.Key2 = Key2;
  547. //
  548. // Search the table
  549. //
  550. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  551. Data = (Entry) ? Entry->Data : NULL;
  552. return Data;
  553. }
  554. PVOID
  555. GTabLookup(
  556. IN PGEN_TABLE GTable,
  557. IN GUID *Key1,
  558. IN PWCHAR Key2
  559. )
  560. /*++
  561. Routine Description:
  562. Find the data for an entry in the table.
  563. Arguments:
  564. GTable - frs generic table
  565. Key1 - primary key
  566. Key2 - secondary key (may be NULL)
  567. Return Value:
  568. Data for an entry or NULL
  569. --*/
  570. {
  571. PVOID Data;
  572. PGEN_ENTRY Entry; // entry in table
  573. GEN_ENTRY Key; // Search key
  574. FRS_ASSERT(Key1);
  575. //
  576. // Set up a search key that is suitable for any table
  577. //
  578. Key.Key1 = Key1;
  579. Key.Key2 = Key2;
  580. //
  581. // Search the table
  582. //
  583. GTabLockTable(GTable);
  584. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  585. Data = (Entry) ? Entry->Data : NULL;
  586. GTabUnLockTable(GTable);
  587. return Data;
  588. }
  589. BOOL
  590. GTabIsEntryPresent(
  591. IN PGEN_TABLE GTable,
  592. IN GUID *Key1,
  593. IN PWCHAR Key2
  594. )
  595. /*++
  596. Routine Description:
  597. Find the entry in the table and return TRUE if found.
  598. Arguments:
  599. GTable - frs generic table
  600. Key1 - primary key
  601. Key2 - secondary key (may be NULL)
  602. Return Value:
  603. Boolean
  604. --*/
  605. {
  606. PVOID Data;
  607. PGEN_ENTRY Entry; // entry in table
  608. GEN_ENTRY Key; // Search key
  609. FRS_ASSERT(Key1);
  610. //
  611. // Set up a search key that is suitable for any table
  612. //
  613. Key.Key1 = Key1;
  614. Key.Key2 = Key2;
  615. //
  616. // Search the table
  617. //
  618. GTabLockTable(GTable);
  619. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  620. GTabUnLockTable(GTable);
  621. return (Entry != NULL);
  622. }
  623. PVOID
  624. GTabLookupTableString(
  625. IN PGEN_TABLE GTable,
  626. IN PWCHAR Key1,
  627. IN PWCHAR Key2
  628. )
  629. /*++
  630. Routine Description:
  631. Find the data for an entry in the table that is indexed by string.
  632. Arguments:
  633. GTable - frs generic table
  634. Key1 - primary key
  635. Key2 - secondary key (may be NULL)
  636. Return Value:
  637. Data for an entry or NULL
  638. --*/
  639. {
  640. PVOID Data;
  641. PGEN_ENTRY Entry; // entry in table
  642. GEN_ENTRY Key; // Search key
  643. FRS_ASSERT(Key1);
  644. //
  645. // Set up a search key that is suitable for any table
  646. //
  647. Key.Key1 = (GUID *)Key1;
  648. Key.Key2 = Key2;
  649. //
  650. // Search the table
  651. //
  652. GTabLockTable(GTable);
  653. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  654. Data = (Entry) ? Entry->Data : NULL;
  655. GTabUnLockTable(GTable);
  656. return Data;
  657. }
  658. PGEN_ENTRY
  659. GTabLookupEntryNoLock(
  660. IN PGEN_TABLE GTable,
  661. IN GUID *Key1,
  662. IN PWCHAR Key2
  663. )
  664. /*++
  665. Routine Description:
  666. Find the data for an entry in the table.
  667. Arguments:
  668. GTable - frs generic table
  669. Key1 - primary key
  670. Key2 - secondary key (may be NULL)
  671. Return Value:
  672. Data for an entry or NULL
  673. --*/
  674. {
  675. PGEN_ENTRY Entry; // entry in table
  676. GEN_ENTRY Key; // Search key
  677. FRS_ASSERT(Key1);
  678. //
  679. // Set up a search key that is suitable for any table
  680. //
  681. Key.Key1 = Key1;
  682. Key.Key2 = Key2;
  683. //
  684. // Search the table
  685. //
  686. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  687. return Entry;
  688. }
  689. PGEN_ENTRY
  690. GTabNextEntryNoLock(
  691. PGEN_TABLE GTable,
  692. PVOID *Key
  693. )
  694. /*++
  695. Routine Description:
  696. Return the entry for Key in GTable. The caller is responsible for
  697. insuring synchronization.
  698. Arguments:
  699. GTable - frs generic table
  700. Key - NULL on first call
  701. Return Value:
  702. The address of an entry in the table or NULL.
  703. --*/
  704. {
  705. PGEN_ENTRY Entry;
  706. //
  707. // Return the entry's address
  708. //
  709. Entry = (PVOID)RtlEnumerateGenericTableWithoutSplaying(&GTable->Table, Key);
  710. return Entry;
  711. }
  712. PVOID
  713. GTabNextDatumNoLock(
  714. PGEN_TABLE GTable,
  715. PVOID *Key
  716. )
  717. /*++
  718. Routine Description:
  719. Return the data for the entry for Key in GTable.
  720. Caller acquires the table lock.
  721. Arguments:
  722. GTable - frs generic table
  723. Key - NULL on first call
  724. GetData - return the entry or the data for the entry
  725. Return Value:
  726. The address of an entry in the table or NULL.
  727. --*/
  728. {
  729. PVOID Data;
  730. PGEN_ENTRY Entry;
  731. //
  732. // Return the address of the entry's data
  733. //
  734. Entry = GTabNextEntryNoLock(GTable, Key);
  735. Data = (Entry) ? Entry->Data : NULL;
  736. return Data;
  737. }
  738. PVOID
  739. GTabNextDatum(
  740. PGEN_TABLE GTable,
  741. PVOID *Key
  742. )
  743. /*++
  744. Routine Description:
  745. Return the data for the entry for Key in GTable.
  746. Arguments:
  747. GTable - frs generic table
  748. Key - NULL on first call
  749. GetData - return the entry or the data for the entry
  750. Return Value:
  751. The address of an entry in the table or NULL.
  752. --*/
  753. {
  754. PVOID Data;
  755. PGEN_ENTRY Entry;
  756. //
  757. // Return the address of the entry's data
  758. //
  759. GTabLockTable(GTable);
  760. Entry = GTabNextEntryNoLock(GTable, Key);
  761. Data = (Entry) ? Entry->Data : NULL;
  762. GTabUnLockTable(GTable);
  763. return Data;
  764. }
  765. DWORD
  766. GTabNumberInTable(
  767. PGEN_TABLE GTable
  768. )
  769. /*++
  770. Routine Description:
  771. Return the number of entries in a table.
  772. Arguments:
  773. GTable - frs generic table
  774. Return Value:
  775. Number of entries in the table.
  776. --*/
  777. {
  778. if (GTable) {
  779. return RtlNumberGenericTableElements(&GTable->Table);
  780. } else {
  781. return 0;
  782. }
  783. }
  784. PVOID
  785. GTabInsertUniqueEntry(
  786. IN PGEN_TABLE GTable,
  787. IN PVOID NewData,
  788. IN PVOID Key1,
  789. IN PVOID Key2
  790. )
  791. /*++
  792. Routine Description:
  793. Insert an entry into the table. If a duplicate is found then
  794. return the original entry. Do not insert in that case.
  795. Arguments:
  796. GTable - frs generic table
  797. NewData - data for the entry to insert
  798. Key1 - primary key
  799. Key2 - secondary key (may be NULL)
  800. Return Value:
  801. NULL if the entry was successfully inserted in the table.
  802. Pointer to the data from old entry if a collision is found.
  803. --*/
  804. {
  805. PGEN_ENTRY OldEntry; // Existing entry in the table
  806. BOOLEAN IsNew; // TRUE if insert found existing entry
  807. GEN_ENTRY NewEntry; // new entry to insert.
  808. PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
  809. //
  810. // Init the new entry. Have to typecast here becasue the GEN_ENTRY expects a GUID* and PWCHAR.
  811. //
  812. NewEntry.Data = NewData;
  813. NewEntry.Key1 = (GUID*)Key1;
  814. NewEntry.Key2 = (PWCHAR)Key2;
  815. NewEntry.Dups = NULL;
  816. //
  817. // Lock the table and Insert the entry
  818. //
  819. GTabLockTable(GTable);
  820. OldEntry = RtlInsertElementGenericTable(&GTable->Table,
  821. &NewEntry,
  822. sizeof(NewEntry),
  823. &IsNew);
  824. GTabUnLockTable(GTable);
  825. if (!IsNew) {
  826. return OldEntry;
  827. }
  828. return NULL;
  829. }
  830. PVOID
  831. GTabInsertUniqueEntryNoLock(
  832. IN PGEN_TABLE GTable,
  833. IN PVOID NewData,
  834. IN PVOID Key1,
  835. IN PVOID Key2
  836. )
  837. /*++
  838. Routine Description:
  839. Insert an entry into the table. If a duplicate is found then
  840. return the original entry. Do not insert in that case.
  841. Arguments:
  842. GTable - frs generic table
  843. NewData - data for the entry to insert
  844. Key1 - primary key
  845. Key2 - secondary key (may be NULL)
  846. Return Value:
  847. NULL if the entry was successfully inserted in the table.
  848. Pointer to the data from old entry if a collision is found.
  849. --*/
  850. {
  851. PGEN_ENTRY OldEntry; // Existing entry in the table
  852. BOOLEAN IsNew; // TRUE if insert found existing entry
  853. GEN_ENTRY NewEntry; // new entry to insert.
  854. PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
  855. //
  856. // Init the new entry. Have to typecast here becasue the GEN_ENTRY expects a GUID* and PWCHAR.
  857. //
  858. NewEntry.Data = NewData;
  859. NewEntry.Key1 = (GUID*)Key1;
  860. NewEntry.Key2 = (PWCHAR)Key2;
  861. NewEntry.Dups = NULL;
  862. OldEntry = RtlInsertElementGenericTable(&GTable->Table,
  863. &NewEntry,
  864. sizeof(NewEntry),
  865. &IsNew);
  866. if (!IsNew) {
  867. return OldEntry;
  868. }
  869. return NULL;
  870. }
  871. VOID
  872. GTabInsertEntry(
  873. IN PGEN_TABLE GTable,
  874. IN PVOID NewData,
  875. IN GUID *Key1,
  876. IN PWCHAR Key2
  877. )
  878. /*++
  879. Routine Description:
  880. Insert an entry into the table. Duplicates are simply linked
  881. to the current entry.
  882. Arguments:
  883. GTable - frs generic table
  884. NewData - data for the entry to insert
  885. Key1 - primary key
  886. Key2 - secondary key (may be NULL)
  887. Return Value:
  888. None.
  889. --*/
  890. {
  891. PGEN_ENTRY OldEntry; // Existing entry in the table
  892. BOOLEAN IsNew; // TRUE if insert found existing entry
  893. GEN_ENTRY NewEntry; // new entry to insert.
  894. PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
  895. //
  896. // Init the new entry.
  897. //
  898. NewEntry.Data = NewData;
  899. NewEntry.Key1 = Key1;
  900. NewEntry.Key2 = Key2;
  901. NewEntry.Dups = NULL;
  902. //
  903. // Lock the table and Insert the entry
  904. //
  905. GTabLockTable(GTable);
  906. OldEntry = RtlInsertElementGenericTable(&GTable->Table,
  907. &NewEntry,
  908. sizeof(NewEntry),
  909. &IsNew);
  910. if (!IsNew) {
  911. //
  912. // Duplicate entry; add to list
  913. //
  914. DupEntry = FrsAlloc(sizeof(GEN_ENTRY));
  915. CopyMemory(DupEntry, &NewEntry, sizeof(NewEntry));
  916. DupEntry->Dups = OldEntry->Dups;
  917. OldEntry->Dups = DupEntry;
  918. }
  919. GTabUnLockTable(GTable);
  920. }
  921. VOID
  922. GTabInsertEntryNoLock(
  923. IN PGEN_TABLE GTable,
  924. IN PVOID NewData,
  925. IN GUID *Key1,
  926. IN PWCHAR Key2
  927. )
  928. /*++
  929. Routine Description:
  930. Insert an entry into the table. Duplicates are simply linked
  931. to the current entry.
  932. Caller acquires the table lock.
  933. Arguments:
  934. GTable - frs generic table
  935. NewData - data for the entry to insert
  936. Key1 - primary key
  937. Key2 - secondary key (may be NULL)
  938. Return Value:
  939. None.
  940. --*/
  941. {
  942. PGEN_ENTRY OldEntry; // Existing entry in the table
  943. BOOLEAN IsNew; // TRUE if insert found existing entry
  944. GEN_ENTRY NewEntry; // new entry to insert.
  945. PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
  946. //
  947. // Init the new entry.
  948. //
  949. NewEntry.Data = NewData;
  950. NewEntry.Key1 = Key1;
  951. NewEntry.Key2 = Key2;
  952. NewEntry.Dups = NULL;
  953. //
  954. // Lock the table and Insert the entry
  955. //
  956. OldEntry = RtlInsertElementGenericTable(&GTable->Table,
  957. &NewEntry,
  958. sizeof(NewEntry),
  959. &IsNew);
  960. if (!IsNew) {
  961. //
  962. // Duplicate entry; add to list
  963. //
  964. DupEntry = FrsAlloc(sizeof(GEN_ENTRY));
  965. CopyMemory(DupEntry, &NewEntry, sizeof(NewEntry));
  966. DupEntry->Dups = OldEntry->Dups;
  967. OldEntry->Dups = DupEntry;
  968. }
  969. }
  970. VOID
  971. GTabDelete(
  972. IN PGEN_TABLE GTable,
  973. IN GUID *Key1,
  974. IN PWCHAR Key2,
  975. IN PVOID (*CallerFree)(PVOID)
  976. )
  977. /*++
  978. Routine Description:
  979. Delete the entry in the table.
  980. Arguments:
  981. GTable - frs generic table
  982. Key1 - primary key
  983. Key2 - secondary key (may be NULL)
  984. CallerFree - The free routine to use to free up the callers datum (optional)
  985. Return Value:
  986. None.
  987. --*/
  988. {
  989. GEN_ENTRY Key; // Search key
  990. PGEN_ENTRY Entry; // entry in table
  991. PGEN_ENTRY Dup; // dup entry in table
  992. PVOID Data;
  993. FRS_ASSERT(Key1);
  994. //
  995. // Set up a search key that is suitable for either table
  996. //
  997. Key.Key1 = Key1;
  998. Key.Key2 = Key2;
  999. //
  1000. // Find the entry
  1001. //
  1002. GTabLockTable(GTable);
  1003. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  1004. if (Entry == NULL) {
  1005. goto out;
  1006. }
  1007. //
  1008. // Delete the dups
  1009. //
  1010. while (Dup = Entry->Dups) {
  1011. Entry->Dups = Dup->Dups;
  1012. if (CallerFree) {
  1013. //
  1014. // Free up the callers Datum
  1015. //
  1016. (*CallerFree)(Dup->Data);
  1017. }
  1018. Dup = FrsFree(Dup);
  1019. }
  1020. //
  1021. // Delete entry
  1022. //
  1023. Data = Entry->Data;
  1024. RtlDeleteElementGenericTable(&GTable->Table, Entry);
  1025. if (CallerFree) {
  1026. //
  1027. // Free up the callers Datum
  1028. //
  1029. (*CallerFree)(Data);
  1030. }
  1031. out:
  1032. GTabUnLockTable(GTable);
  1033. }
  1034. VOID
  1035. GTabDeleteNoLock(
  1036. IN PGEN_TABLE GTable,
  1037. IN GUID *Key1,
  1038. IN PWCHAR Key2,
  1039. IN PVOID (*CallerFree)(PVOID)
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. Delete the entry in the table.
  1044. Arguments:
  1045. GTable - frs generic table
  1046. Key1 - primary key
  1047. Key2 - secondary key (may be NULL)
  1048. CallerFree - The free routine to use to free up the callers datum (optional)
  1049. Return Value:
  1050. None.
  1051. --*/
  1052. {
  1053. GEN_ENTRY Key; // Search key
  1054. PGEN_ENTRY Entry; // entry in table
  1055. PGEN_ENTRY Dup; // dup entry in table
  1056. PVOID Data;
  1057. FRS_ASSERT(Key1);
  1058. //
  1059. // Set up a search key that is suitable for either table
  1060. //
  1061. Key.Key1 = Key1;
  1062. Key.Key2 = Key2;
  1063. //
  1064. // Find the entry
  1065. //
  1066. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  1067. if (Entry == NULL) {
  1068. return;
  1069. }
  1070. //
  1071. // Delete the dups
  1072. //
  1073. while (Dup = Entry->Dups) {
  1074. Entry->Dups = Dup->Dups;
  1075. if (CallerFree) {
  1076. //
  1077. // Free up the callers Datum
  1078. //
  1079. (*CallerFree)(Dup->Data);
  1080. }
  1081. Dup = FrsFree(Dup);
  1082. }
  1083. //
  1084. // Delete entry
  1085. //
  1086. Data = Entry->Data;
  1087. RtlDeleteElementGenericTable(&GTable->Table, Entry);
  1088. if (CallerFree) {
  1089. //
  1090. // Free up the callers Datum
  1091. //
  1092. (*CallerFree)(Data);
  1093. }
  1094. }
  1095. VOID
  1096. GTabPrintTable(
  1097. IN PGEN_TABLE GTable
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. Print the table and all of its dups.
  1102. Arguments:
  1103. GTable - frs generic table
  1104. Return Value:
  1105. None.
  1106. --*/
  1107. {
  1108. PGEN_ENTRY Entry;
  1109. PGEN_ENTRY Dup;
  1110. PVOID Key;
  1111. CHAR Guid[GUID_CHAR_LEN + 1];
  1112. //
  1113. // print the entries
  1114. //
  1115. GTabLockTable(GTable);
  1116. Key = NULL;
  1117. while (Entry = GTabNextEntryNoLock(GTable, &Key)) {
  1118. GuidToStr(Entry->Key1, &Guid[0]);
  1119. if (Entry->Key2) {
  1120. DPRINT3(0, "\t0x%x %s %ws\n", Entry->Data, Guid, Entry->Key2);
  1121. } else {
  1122. DPRINT2(0, "\t0x%x %s NULL\n", Entry->Data, Guid);
  1123. }
  1124. for (Dup = Entry->Dups; Dup; Dup = Dup->Dups) {
  1125. GuidToStr(Entry->Key1, &Guid[0]);
  1126. if (Dup->Key2) {
  1127. DPRINT3(0, "\t0x%x %s %ws\n", Dup->Data, Guid, Dup->Key2);
  1128. } else {
  1129. DPRINT2(0, "\t0x%x %s NULL\n", Dup->Data, Guid);
  1130. }
  1131. }
  1132. }
  1133. GTabUnLockTable(GTable);
  1134. }