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.

1257 lines
25 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. GTabCmpTableStringAndBoolEntry(
  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 data with strings used as key.
  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 = _wcsicmp((PWCHAR)(Entry1->Key1), (PWCHAR)(Entry2->Key1));
  174. if (Cmp < 0) {
  175. return (GenericLessThan);
  176. }
  177. if (Cmp > 0){
  178. return (GenericGreaterThan);
  179. }
  180. //
  181. // Compare secondary keys if they exist.
  182. //
  183. if ((Entry1->Key2 == NULL) || (Entry2->Key2 == NULL)) {
  184. return GenericEqual;
  185. }
  186. if (*(Entry1->Key2) == *(Entry2->Key2)) {
  187. return GenericEqual;
  188. } else if (*(Entry1->Key2) == FALSE) {
  189. return GenericLessThan;
  190. }
  191. return GenericGreaterThan;
  192. }
  193. RTL_GENERIC_COMPARE_RESULTS
  194. GTabCmpTableStringEntry(
  195. IN PRTL_GENERIC_TABLE Table,
  196. IN PVOID TableEntry1,
  197. IN PVOID TableEntry2
  198. )
  199. /*++
  200. Routine Description:
  201. Compare two entries in the table for data with strings used as key.
  202. Arguments:
  203. Table - Address of the table (not used).
  204. Entry1 - PGEN_ENTRY
  205. Entry2 - PGEN_ENTRY
  206. Return Value:
  207. <0 First < Second
  208. =0 First == Second
  209. >0 First > Second
  210. --*/
  211. {
  212. INT Cmp;
  213. PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1;
  214. PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
  215. //
  216. // Primary key must be present
  217. //
  218. FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
  219. //
  220. // Compare primary keys
  221. //
  222. Cmp = _wcsicmp((PWCHAR)(Entry1->Key1), (PWCHAR)(Entry2->Key1));
  223. if (Cmp < 0) {
  224. return (GenericLessThan);
  225. }
  226. if (Cmp > 0){
  227. return (GenericGreaterThan);
  228. }
  229. //
  230. // Compare secondary keys if they exist.
  231. //
  232. if ((Entry1->Key2 == NULL) || (Entry2->Key2 == NULL)) {
  233. return GenericEqual;
  234. }
  235. Cmp = _wcsicmp(Entry1->Key2, Entry2->Key2);
  236. if (Cmp < 0) {
  237. return (GenericLessThan);
  238. }
  239. if (Cmp > 0){
  240. return (GenericGreaterThan);
  241. }
  242. return GenericEqual;
  243. }
  244. VOID
  245. GTabLockTable(
  246. PGEN_TABLE GTable
  247. )
  248. /*++
  249. Routine Description:
  250. Lock the table
  251. Arguments:
  252. GTable - frs generic table
  253. Return Value:
  254. None.
  255. --*/
  256. {
  257. EnterCriticalSection(&GTable->Critical);
  258. }
  259. VOID
  260. GTabUnLockTable(
  261. PGEN_TABLE GTable
  262. )
  263. /*++
  264. Routine Description:
  265. Unlock the table
  266. Arguments:
  267. GTable - frs generic table
  268. Return Value:
  269. None.
  270. --*/
  271. {
  272. LeaveCriticalSection(&GTable->Critical);
  273. }
  274. PGEN_TABLE
  275. GTabAllocNumberTable(
  276. VOID
  277. )
  278. /*++
  279. Routine Description:
  280. Initialize a generic table + lock for numbers.
  281. Arguments:
  282. None.
  283. Return Value:
  284. None.
  285. --*/
  286. {
  287. PGEN_TABLE GTable;
  288. GTable = FrsAllocType(GEN_TABLE_TYPE);
  289. InitializeCriticalSection(&GTable->Critical);
  290. RtlInitializeGenericTable(&GTable->Table,
  291. GTabCmpTableNumberEntry,
  292. GTabAllocTableMem,
  293. GTabFreeTableMem,
  294. NULL);
  295. return GTable;
  296. }
  297. PGEN_TABLE
  298. GTabAllocStringTable(
  299. VOID
  300. )
  301. /*++
  302. Routine Description:
  303. Initialize a generic table + lock for data with strings
  304. used as a key.
  305. Arguments:
  306. None.
  307. Return Value:
  308. None.
  309. --*/
  310. {
  311. PGEN_TABLE GTable;
  312. GTable = FrsAllocType(GEN_TABLE_TYPE);
  313. InitializeCriticalSection(&GTable->Critical);
  314. RtlInitializeGenericTable(&GTable->Table,
  315. GTabCmpTableStringEntry,
  316. GTabAllocTableMem,
  317. GTabFreeTableMem,
  318. NULL);
  319. return GTable;
  320. }
  321. PGEN_TABLE
  322. GTabAllocStringAndBoolTable(
  323. VOID
  324. )
  325. /*++
  326. Routine Description:
  327. Initialize a generic table + lock for data with a string and bool
  328. used as a key.
  329. Arguments:
  330. None.
  331. Return Value:
  332. None.
  333. --*/
  334. {
  335. PGEN_TABLE GTable;
  336. GTable = FrsAllocType(GEN_TABLE_TYPE);
  337. InitializeCriticalSection(&GTable->Critical);
  338. RtlInitializeGenericTable(&GTable->Table,
  339. GTabCmpTableStringAndBoolEntry,
  340. GTabAllocTableMem,
  341. GTabFreeTableMem,
  342. NULL);
  343. return GTable;
  344. }
  345. PGEN_TABLE
  346. GTabAllocTable(
  347. VOID
  348. )
  349. /*++
  350. Routine Description:
  351. Initialize a generic table + lock.
  352. Arguments:
  353. None.
  354. Return Value:
  355. None.
  356. --*/
  357. {
  358. PGEN_TABLE GTable;
  359. GTable = FrsAllocType(GEN_TABLE_TYPE);
  360. InitializeCriticalSection(&GTable->Critical);
  361. RtlInitializeGenericTable(&GTable->Table,
  362. GTabCmpTableEntry,
  363. GTabAllocTableMem,
  364. GTabFreeTableMem,
  365. NULL);
  366. return GTable;
  367. }
  368. VOID
  369. GTabEmptyTableNoLock(
  370. IN PGEN_TABLE GTable,
  371. IN PVOID (*CallerFree)(PVOID)
  372. )
  373. /*++
  374. Routine Description:
  375. Free every entry in the frs generic table. Caller has acquired the table lock.
  376. Arguments:
  377. GTable - frs generic table
  378. CallerFree - The free routine to use to free up the callers datum (optional)
  379. Return Value:
  380. None.
  381. --*/
  382. {
  383. PGEN_ENTRY Entry; // Next entry in table
  384. PGEN_ENTRY Dup; // Next entry in table
  385. PVOID Data;
  386. //
  387. // For every entry in the table
  388. //
  389. while (Entry = RtlEnumerateGenericTable(&GTable->Table, TRUE)) {
  390. //
  391. // Delete the dups
  392. //
  393. while (Dup = Entry->Dups) {
  394. Entry->Dups = Dup->Dups;
  395. if (CallerFree) {
  396. //
  397. // Free up the callers Datum
  398. //
  399. (*CallerFree)(Dup->Data);
  400. }
  401. Dup = FrsFree(Dup);
  402. }
  403. //
  404. // Delete the entry from the table
  405. //
  406. Data = Entry->Data;
  407. RtlDeleteElementGenericTable(&GTable->Table, Entry);
  408. if (CallerFree) {
  409. //
  410. // Free up the callers Datum
  411. //
  412. (*CallerFree)(Data);
  413. }
  414. }
  415. }
  416. VOID
  417. GTabEmptyTable(
  418. IN PGEN_TABLE GTable,
  419. IN PVOID (*CallerFree)(PVOID)
  420. )
  421. /*++
  422. Routine Description:
  423. Free every entry in the frs generic table.
  424. Arguments:
  425. GTable - frs generic table
  426. CallerFree - The free routine to use to free up the callers datum (optional)
  427. Return Value:
  428. None.
  429. --*/
  430. {
  431. GTabLockTable(GTable);
  432. GTabEmptyTableNoLock(GTable, CallerFree);
  433. GTabUnLockTable(GTable);
  434. }
  435. PVOID
  436. GTabFreeTable(
  437. IN PGEN_TABLE GTable,
  438. IN PVOID (*CallerFree)(PVOID)
  439. )
  440. /*++
  441. Routine Description:
  442. Undo the work done by GenTableInitialize.
  443. Arguments:
  444. GTTable - Address of the gen table.
  445. CallerFree - The free routine to use to free up the callers datum (optional)
  446. Return Value:
  447. None.
  448. --*/
  449. {
  450. if (GTable == NULL) {
  451. return NULL;
  452. }
  453. //
  454. // Empty the table
  455. //
  456. GTabEmptyTable(GTable, CallerFree);
  457. DeleteCriticalSection(&GTable->Critical);
  458. return FrsFreeType(GTable);
  459. }
  460. PVOID
  461. GTabLookupNoLock(
  462. IN PGEN_TABLE GTable,
  463. IN GUID *Key1,
  464. IN PWCHAR Key2
  465. )
  466. /*++
  467. Routine Description:
  468. Find the entry in the table.
  469. Arguments:
  470. GTable - frs generic table
  471. Key1 - primary key
  472. Key2 - secondary key (may be NULL)
  473. Return Value:
  474. Data for an entry or NULL
  475. --*/
  476. {
  477. PVOID Data;
  478. PGEN_ENTRY Entry; // entry in table
  479. GEN_ENTRY Key; // Search key
  480. FRS_ASSERT(Key1);
  481. //
  482. // Set up a search key that is suitable for any table
  483. //
  484. Key.Key1 = Key1;
  485. Key.Key2 = Key2;
  486. //
  487. // Search the table
  488. //
  489. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  490. Data = (Entry) ? Entry->Data : NULL;
  491. return Data;
  492. }
  493. PVOID
  494. GTabLookup(
  495. IN PGEN_TABLE GTable,
  496. IN GUID *Key1,
  497. IN PWCHAR Key2
  498. )
  499. /*++
  500. Routine Description:
  501. Find the data for an entry in the table.
  502. Arguments:
  503. GTable - frs generic table
  504. Key1 - primary key
  505. Key2 - secondary key (may be NULL)
  506. Return Value:
  507. Data for an entry or NULL
  508. --*/
  509. {
  510. PVOID Data;
  511. PGEN_ENTRY Entry; // entry in table
  512. GEN_ENTRY Key; // Search key
  513. FRS_ASSERT(Key1);
  514. //
  515. // Set up a search key that is suitable for any table
  516. //
  517. Key.Key1 = Key1;
  518. Key.Key2 = Key2;
  519. //
  520. // Search the table
  521. //
  522. GTabLockTable(GTable);
  523. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  524. Data = (Entry) ? Entry->Data : NULL;
  525. GTabUnLockTable(GTable);
  526. return Data;
  527. }
  528. BOOL
  529. GTabIsEntryPresent(
  530. IN PGEN_TABLE GTable,
  531. IN GUID *Key1,
  532. IN PWCHAR Key2
  533. )
  534. /*++
  535. Routine Description:
  536. Find the entry in the table and return TRUE if found.
  537. Arguments:
  538. GTable - frs generic table
  539. Key1 - primary key
  540. Key2 - secondary key (may be NULL)
  541. Return Value:
  542. Boolean
  543. --*/
  544. {
  545. PVOID Data;
  546. PGEN_ENTRY Entry; // entry in table
  547. GEN_ENTRY Key; // Search key
  548. FRS_ASSERT(Key1);
  549. //
  550. // Set up a search key that is suitable for any table
  551. //
  552. Key.Key1 = Key1;
  553. Key.Key2 = Key2;
  554. //
  555. // Search the table
  556. //
  557. GTabLockTable(GTable);
  558. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  559. GTabUnLockTable(GTable);
  560. return (Entry != NULL);
  561. }
  562. PVOID
  563. GTabLookupTableString(
  564. IN PGEN_TABLE GTable,
  565. IN PWCHAR Key1,
  566. IN PWCHAR Key2
  567. )
  568. /*++
  569. Routine Description:
  570. Find the data for an entry in the table that is indexed by string.
  571. Arguments:
  572. GTable - frs generic table
  573. Key1 - primary key
  574. Key2 - secondary key (may be NULL)
  575. Return Value:
  576. Data for an entry or NULL
  577. --*/
  578. {
  579. PVOID Data;
  580. PGEN_ENTRY Entry; // entry in table
  581. GEN_ENTRY Key; // Search key
  582. FRS_ASSERT(Key1);
  583. //
  584. // Set up a search key that is suitable for any table
  585. //
  586. Key.Key1 = (GUID *)Key1;
  587. Key.Key2 = Key2;
  588. //
  589. // Search the table
  590. //
  591. GTabLockTable(GTable);
  592. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  593. Data = (Entry) ? Entry->Data : NULL;
  594. GTabUnLockTable(GTable);
  595. return Data;
  596. }
  597. PGEN_ENTRY
  598. GTabLookupEntryNoLock(
  599. IN PGEN_TABLE GTable,
  600. IN GUID *Key1,
  601. IN PWCHAR Key2
  602. )
  603. /*++
  604. Routine Description:
  605. Find the data for an entry in the table.
  606. Arguments:
  607. GTable - frs generic table
  608. Key1 - primary key
  609. Key2 - secondary key (may be NULL)
  610. Return Value:
  611. Data for an entry or NULL
  612. --*/
  613. {
  614. PGEN_ENTRY Entry; // entry in table
  615. GEN_ENTRY Key; // Search key
  616. FRS_ASSERT(Key1);
  617. //
  618. // Set up a search key that is suitable for any table
  619. //
  620. Key.Key1 = Key1;
  621. Key.Key2 = Key2;
  622. //
  623. // Search the table
  624. //
  625. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  626. return Entry;
  627. }
  628. PGEN_ENTRY
  629. GTabNextEntryNoLock(
  630. PGEN_TABLE GTable,
  631. PVOID *Key
  632. )
  633. /*++
  634. Routine Description:
  635. Return the entry for Key in GTable. The caller is responsible for
  636. insuring synchronization.
  637. Arguments:
  638. GTable - frs generic table
  639. Key - NULL on first call
  640. Return Value:
  641. The address of an entry in the table or NULL.
  642. --*/
  643. {
  644. PGEN_ENTRY Entry;
  645. //
  646. // Return the entry's address
  647. //
  648. Entry = (PVOID)RtlEnumerateGenericTableWithoutSplaying(&GTable->Table, Key);
  649. return Entry;
  650. }
  651. PVOID
  652. GTabNextDatumNoLock(
  653. PGEN_TABLE GTable,
  654. PVOID *Key
  655. )
  656. /*++
  657. Routine Description:
  658. Return the data for the entry for Key in GTable.
  659. Caller acquires the table lock.
  660. Arguments:
  661. GTable - frs generic table
  662. Key - NULL on first call
  663. GetData - return the entry or the data for the entry
  664. Return Value:
  665. The address of an entry in the table or NULL.
  666. --*/
  667. {
  668. PVOID Data;
  669. PGEN_ENTRY Entry;
  670. //
  671. // Return the address of the entry's data
  672. //
  673. Entry = GTabNextEntryNoLock(GTable, Key);
  674. Data = (Entry) ? Entry->Data : NULL;
  675. return Data;
  676. }
  677. PVOID
  678. GTabNextDatum(
  679. PGEN_TABLE GTable,
  680. PVOID *Key
  681. )
  682. /*++
  683. Routine Description:
  684. Return the data for the entry for Key in GTable.
  685. Arguments:
  686. GTable - frs generic table
  687. Key - NULL on first call
  688. GetData - return the entry or the data for the entry
  689. Return Value:
  690. The address of an entry in the table or NULL.
  691. --*/
  692. {
  693. PVOID Data;
  694. PGEN_ENTRY Entry;
  695. //
  696. // Return the address of the entry's data
  697. //
  698. GTabLockTable(GTable);
  699. Entry = GTabNextEntryNoLock(GTable, Key);
  700. Data = (Entry) ? Entry->Data : NULL;
  701. GTabUnLockTable(GTable);
  702. return Data;
  703. }
  704. DWORD
  705. GTabNumberInTable(
  706. PGEN_TABLE GTable
  707. )
  708. /*++
  709. Routine Description:
  710. Return the number of entries in a table.
  711. Arguments:
  712. GTable - frs generic table
  713. Return Value:
  714. Number of entries in the table.
  715. --*/
  716. {
  717. if (GTable) {
  718. return RtlNumberGenericTableElements(&GTable->Table);
  719. } else {
  720. return 0;
  721. }
  722. }
  723. PVOID
  724. GTabInsertUniqueEntry(
  725. IN PGEN_TABLE GTable,
  726. IN PVOID NewData,
  727. IN PVOID Key1,
  728. IN PVOID Key2
  729. )
  730. /*++
  731. Routine Description:
  732. Insert an entry into the table. If a duplicate is found then
  733. return the original entry. Do not insert in that case.
  734. Arguments:
  735. GTable - frs generic table
  736. NewData - data for the entry to insert
  737. Key1 - primary key
  738. Key2 - secondary key (may be NULL)
  739. Return Value:
  740. NULL if the entry was successfully inserted in the table.
  741. Pointer to the data from old entry if a collision is found.
  742. --*/
  743. {
  744. PGEN_ENTRY OldEntry; // Existing entry in the table
  745. BOOLEAN IsNew; // TRUE if insert found existing entry
  746. GEN_ENTRY NewEntry; // new entry to insert.
  747. PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
  748. //
  749. // Init the new entry. Have to typecast here becasue the GEN_ENTRY expects a GUID* and PWCHAR.
  750. //
  751. NewEntry.Data = NewData;
  752. NewEntry.Key1 = (GUID*)Key1;
  753. NewEntry.Key2 = (PWCHAR)Key2;
  754. NewEntry.Dups = NULL;
  755. //
  756. // Lock the table and Insert the entry
  757. //
  758. GTabLockTable(GTable);
  759. OldEntry = RtlInsertElementGenericTable(&GTable->Table,
  760. &NewEntry,
  761. sizeof(NewEntry),
  762. &IsNew);
  763. GTabUnLockTable(GTable);
  764. if (!IsNew) {
  765. return OldEntry;
  766. }
  767. return NULL;
  768. }
  769. VOID
  770. GTabInsertEntry(
  771. IN PGEN_TABLE GTable,
  772. IN PVOID NewData,
  773. IN GUID *Key1,
  774. IN PWCHAR Key2
  775. )
  776. /*++
  777. Routine Description:
  778. Insert an entry into the table. Duplicates are simply linked
  779. to the current entry.
  780. Arguments:
  781. GTable - frs generic table
  782. NewData - data for the entry to insert
  783. Key1 - primary key
  784. Key2 - secondary key (may be NULL)
  785. Return Value:
  786. None.
  787. --*/
  788. {
  789. PGEN_ENTRY OldEntry; // Existing entry in the table
  790. BOOLEAN IsNew; // TRUE if insert found existing entry
  791. GEN_ENTRY NewEntry; // new entry to insert.
  792. PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
  793. //
  794. // Init the new entry.
  795. //
  796. NewEntry.Data = NewData;
  797. NewEntry.Key1 = Key1;
  798. NewEntry.Key2 = Key2;
  799. NewEntry.Dups = NULL;
  800. //
  801. // Lock the table and Insert the entry
  802. //
  803. GTabLockTable(GTable);
  804. OldEntry = RtlInsertElementGenericTable(&GTable->Table,
  805. &NewEntry,
  806. sizeof(NewEntry),
  807. &IsNew);
  808. if (!IsNew) {
  809. //
  810. // Duplicate entry; add to list
  811. //
  812. DupEntry = FrsAlloc(sizeof(GEN_ENTRY));
  813. CopyMemory(DupEntry, &NewEntry, sizeof(NewEntry));
  814. DupEntry->Dups = OldEntry->Dups;
  815. OldEntry->Dups = DupEntry;
  816. }
  817. GTabUnLockTable(GTable);
  818. }
  819. VOID
  820. GTabInsertEntryNoLock(
  821. IN PGEN_TABLE GTable,
  822. IN PVOID NewData,
  823. IN GUID *Key1,
  824. IN PWCHAR Key2
  825. )
  826. /*++
  827. Routine Description:
  828. Insert an entry into the table. Duplicates are simply linked
  829. to the current entry.
  830. Caller acquires the table lock.
  831. Arguments:
  832. GTable - frs generic table
  833. NewData - data for the entry to insert
  834. Key1 - primary key
  835. Key2 - secondary key (may be NULL)
  836. Return Value:
  837. None.
  838. --*/
  839. {
  840. PGEN_ENTRY OldEntry; // Existing entry in the table
  841. BOOLEAN IsNew; // TRUE if insert found existing entry
  842. GEN_ENTRY NewEntry; // new entry to insert.
  843. PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
  844. //
  845. // Init the new entry.
  846. //
  847. NewEntry.Data = NewData;
  848. NewEntry.Key1 = Key1;
  849. NewEntry.Key2 = Key2;
  850. NewEntry.Dups = NULL;
  851. //
  852. // Lock the table and Insert the entry
  853. //
  854. OldEntry = RtlInsertElementGenericTable(&GTable->Table,
  855. &NewEntry,
  856. sizeof(NewEntry),
  857. &IsNew);
  858. if (!IsNew) {
  859. //
  860. // Duplicate entry; add to list
  861. //
  862. DupEntry = FrsAlloc(sizeof(GEN_ENTRY));
  863. CopyMemory(DupEntry, &NewEntry, sizeof(NewEntry));
  864. DupEntry->Dups = OldEntry->Dups;
  865. OldEntry->Dups = DupEntry;
  866. }
  867. }
  868. VOID
  869. GTabDelete(
  870. IN PGEN_TABLE GTable,
  871. IN GUID *Key1,
  872. IN PWCHAR Key2,
  873. IN PVOID (*CallerFree)(PVOID)
  874. )
  875. /*++
  876. Routine Description:
  877. Delete the entry in the table.
  878. Arguments:
  879. GTable - frs generic table
  880. Key1 - primary key
  881. Key2 - secondary key (may be NULL)
  882. CallerFree - The free routine to use to free up the callers datum (optional)
  883. Return Value:
  884. None.
  885. --*/
  886. {
  887. GEN_ENTRY Key; // Search key
  888. PGEN_ENTRY Entry; // entry in table
  889. PGEN_ENTRY Dup; // dup entry in table
  890. PVOID Data;
  891. FRS_ASSERT(Key1);
  892. //
  893. // Set up a search key that is suitable for either table
  894. //
  895. Key.Key1 = Key1;
  896. Key.Key2 = Key2;
  897. //
  898. // Find the entry
  899. //
  900. GTabLockTable(GTable);
  901. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  902. if (Entry == NULL) {
  903. goto out;
  904. }
  905. //
  906. // Delete the dups
  907. //
  908. while (Dup = Entry->Dups) {
  909. Entry->Dups = Dup->Dups;
  910. if (CallerFree) {
  911. //
  912. // Free up the callers Datum
  913. //
  914. (*CallerFree)(Dup->Data);
  915. }
  916. Dup = FrsFree(Dup);
  917. }
  918. //
  919. // Delete entry
  920. //
  921. Data = Entry->Data;
  922. RtlDeleteElementGenericTable(&GTable->Table, Entry);
  923. if (CallerFree) {
  924. //
  925. // Free up the callers Datum
  926. //
  927. (*CallerFree)(Data);
  928. }
  929. out:
  930. GTabUnLockTable(GTable);
  931. }
  932. VOID
  933. GTabDeleteNoLock(
  934. IN PGEN_TABLE GTable,
  935. IN GUID *Key1,
  936. IN PWCHAR Key2,
  937. IN PVOID (*CallerFree)(PVOID)
  938. )
  939. /*++
  940. Routine Description:
  941. Delete the entry in the table.
  942. Arguments:
  943. GTable - frs generic table
  944. Key1 - primary key
  945. Key2 - secondary key (may be NULL)
  946. CallerFree - The free routine to use to free up the callers datum (optional)
  947. Return Value:
  948. None.
  949. --*/
  950. {
  951. GEN_ENTRY Key; // Search key
  952. PGEN_ENTRY Entry; // entry in table
  953. PGEN_ENTRY Dup; // dup entry in table
  954. PVOID Data;
  955. FRS_ASSERT(Key1);
  956. //
  957. // Set up a search key that is suitable for either table
  958. //
  959. Key.Key1 = Key1;
  960. Key.Key2 = Key2;
  961. //
  962. // Find the entry
  963. //
  964. Entry = (PVOID)RtlLookupElementGenericTable(&GTable->Table, &Key);
  965. if (Entry == NULL) {
  966. return;
  967. }
  968. //
  969. // Delete the dups
  970. //
  971. while (Dup = Entry->Dups) {
  972. Entry->Dups = Dup->Dups;
  973. if (CallerFree) {
  974. //
  975. // Free up the callers Datum
  976. //
  977. (*CallerFree)(Dup->Data);
  978. }
  979. Dup = FrsFree(Dup);
  980. }
  981. //
  982. // Delete entry
  983. //
  984. Data = Entry->Data;
  985. RtlDeleteElementGenericTable(&GTable->Table, Entry);
  986. if (CallerFree) {
  987. //
  988. // Free up the callers Datum
  989. //
  990. (*CallerFree)(Data);
  991. }
  992. }
  993. VOID
  994. GTabPrintTable(
  995. IN PGEN_TABLE GTable
  996. )
  997. /*++
  998. Routine Description:
  999. Print the table and all of its dups.
  1000. Arguments:
  1001. GTable - frs generic table
  1002. Return Value:
  1003. None.
  1004. --*/
  1005. {
  1006. PGEN_ENTRY Entry;
  1007. PGEN_ENTRY Dup;
  1008. PVOID Key;
  1009. CHAR Guid[GUID_CHAR_LEN + 1];
  1010. //
  1011. // print the entries
  1012. //
  1013. GTabLockTable(GTable);
  1014. Key = NULL;
  1015. while (Entry = GTabNextEntryNoLock(GTable, &Key)) {
  1016. GuidToStr(Entry->Key1, &Guid[0]);
  1017. if (Entry->Key2) {
  1018. DPRINT3(0, "\t0x%x %s %ws\n", Entry->Data, Guid, Entry->Key2);
  1019. } else {
  1020. DPRINT2(0, "\t0x%x %s NULL\n", Entry->Data, Guid);
  1021. }
  1022. for (Dup = Entry->Dups; Dup; Dup = Dup->Dups) {
  1023. GuidToStr(Entry->Key1, &Guid[0]);
  1024. if (Dup->Key2) {
  1025. DPRINT3(0, "\t0x%x %s %ws\n", Dup->Data, Guid, Dup->Key2);
  1026. } else {
  1027. DPRINT2(0, "\t0x%x %s NULL\n", Dup->Data, Guid);
  1028. }
  1029. }
  1030. }
  1031. GTabUnLockTable(GTable);
  1032. }