|
|
/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name: frstable.c
Abstract: These routines manage the tables used by the FRS.
Author: Billy J. Fuller 19-Apr-1997
Environment User mode winnt
--*/
#include <ntreppch.h>
#pragma hdrstop
#define DEBSUB "FRSTABLE:"
#include <frs.h>
PVOID GTabAllocTableMem( IN PRTL_GENERIC_TABLE Table, IN DWORD NodeSize ) /*++
Routine Description: Allocate space for a table entry. The entry includes the user-defined struct and some overhead used by the generic table routines. The generic table routines call this function when they need memory.
Arguments: Table - Address of the table (not used). NodeSize - Bytes to allocate
Return Value: Address of newly allocated memory. --*/ { return FrsAlloc(NodeSize); }
VOID GTabFreeTableMem( IN PRTL_GENERIC_TABLE Table, IN PVOID Buffer ) /*++
Routine Description: Free the space allocated by GTAlloc(). The generic table routines call this function to free memory.
Arguments: Table - Address of the table (not used). Buffer - Address of previously allocated memory
Return Value: None. --*/ { FrsFree(Buffer); }
RTL_GENERIC_COMPARE_RESULTS GTabCmpTableEntry( IN PRTL_GENERIC_TABLE Table, IN PVOID TableEntry1, IN PVOID TableEntry2 ) /*++
Routine Description: Compare two entries in the table for guid/names.
Arguments: Table - Address of the table (not used). Entry1 - PGEN_ENTRY Entry2 - PGEN_ENTRY
Return Value: <0 First < Second =0 First == Second >0 First > Second --*/ { INT Cmp; PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1; PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
//
// Primary key must be present
//
FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
//
// Compare primary keys
//
Cmp = memcmp(Entry1->Key1, Entry2->Key1, sizeof(GUID)); if (Cmp < 0) { return (GenericLessThan); } if (Cmp > 0) { return (GenericGreaterThan); }
//
// No second key; done
//
if (!Entry1->Key2 || !Entry2->Key2) return GenericEqual;
//
// Compare secondary keys
//
Cmp = _wcsicmp(Entry1->Key2, Entry2->Key2); if (Cmp < 0) { return (GenericLessThan); } if (Cmp > 0){ return (GenericGreaterThan); }
return (GenericEqual); }
RTL_GENERIC_COMPARE_RESULTS GTabCmpTableNumberEntry( IN PRTL_GENERIC_TABLE Table, IN PVOID TableEntry1, IN PVOID TableEntry2 ) /*++
Routine Description: Compare two entries in the table for number
Arguments: Table - Address of the table (not used). Entry1 - PGEN_ENTRY Entry2 - PGEN_ENTRY
Return Value: <0 First < Second =0 First == Second >0 First > Second --*/ { INT Cmp; PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1; PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
//
// Primary key must be present
//
FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
//
// Compare primary keys
//
Cmp = memcmp(Entry1->Key1, Entry2->Key1, sizeof(ULONG)); if (Cmp < 0) { return (GenericLessThan); } if (Cmp > 0){ return (GenericGreaterThan); }
return GenericEqual; }
RTL_GENERIC_COMPARE_RESULTS GTabCmpTableFileTimeEntry( IN PRTL_GENERIC_TABLE Table, IN PVOID TableEntry1, IN PVOID TableEntry2 ) /*++
Routine Description: Compare two entries in the table for number
Arguments: Table - Address of the table (not used). Entry1 - PGEN_ENTRY Entry2 - PGEN_ENTRY
Return Value: <0 First < Second =0 First == Second >0 First > Second --*/ { INT Cmp; PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1; PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
//
// Primary key must be present
//
FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
//
// Compare primary keys
//
Cmp = CompareFileTime((PFILETIME)Entry1->Key1, (PFILETIME)Entry2->Key1); if (Cmp < 0) { return (GenericLessThan); } if (Cmp > 0){ return (GenericGreaterThan); }
return GenericEqual; }
RTL_GENERIC_COMPARE_RESULTS GTabCmpTableStringAndBoolEntry( IN PRTL_GENERIC_TABLE Table, IN PVOID TableEntry1, IN PVOID TableEntry2 ) /*++
Routine Description: Compare two entries in the table for data with strings used as key.
Arguments: Table - Address of the table (not used). Entry1 - PGEN_ENTRY Entry2 - PGEN_ENTRY
Return Value: <0 First < Second =0 First == Second >0 First > Second --*/ { INT Cmp; PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1; PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
//
// Primary key must be present
//
FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
//
// Compare primary keys
//
Cmp = _wcsicmp((PWCHAR)(Entry1->Key1), (PWCHAR)(Entry2->Key1)); if (Cmp < 0) { return (GenericLessThan); } if (Cmp > 0){ return (GenericGreaterThan); }
//
// Compare secondary keys if they exist.
//
if ((Entry1->Key2 == NULL) || (Entry2->Key2 == NULL)) { return GenericEqual; }
if (*(Entry1->Key2) == *(Entry2->Key2)) { return GenericEqual; } else if (*(Entry1->Key2) == FALSE) { return GenericLessThan; }
return GenericGreaterThan; }
RTL_GENERIC_COMPARE_RESULTS GTabCmpTableStringEntry( IN PRTL_GENERIC_TABLE Table, IN PVOID TableEntry1, IN PVOID TableEntry2 ) /*++
Routine Description: Compare two entries in the table for data with strings used as key.
Arguments: Table - Address of the table (not used). Entry1 - PGEN_ENTRY Entry2 - PGEN_ENTRY
Return Value: <0 First < Second =0 First == Second >0 First > Second --*/ { INT Cmp; PGEN_ENTRY Entry1 = (PGEN_ENTRY)TableEntry1; PGEN_ENTRY Entry2 = (PGEN_ENTRY)TableEntry2;
//
// Primary key must be present
//
FRS_ASSERT(Entry1->Key1 && Entry2->Key1);
//
// Compare primary keys
//
Cmp = _wcsicmp((PWCHAR)(Entry1->Key1), (PWCHAR)(Entry2->Key1)); if (Cmp < 0) { return (GenericLessThan); } if (Cmp > 0){ return (GenericGreaterThan); }
//
// Compare secondary keys if they exist.
//
if ((Entry1->Key2 == NULL) || (Entry2->Key2 == NULL)) { return GenericEqual; }
Cmp = _wcsicmp(Entry1->Key2, Entry2->Key2); if (Cmp < 0) { return (GenericLessThan); } if (Cmp > 0){ return (GenericGreaterThan); }
return GenericEqual; }
VOID GTabLockTable( PGEN_TABLE GTable ) /*++
Routine Description: Lock the table
Arguments: GTable - frs generic table
Return Value: None. --*/ { EnterCriticalSection(>able->Critical); }
VOID GTabUnLockTable( PGEN_TABLE GTable ) /*++
Routine Description: Unlock the table
Arguments: GTable - frs generic table
Return Value: None. --*/ { LeaveCriticalSection(>able->Critical); }
PGEN_TABLE GTabAllocNumberTable( VOID ) /*++
Routine Description: Initialize a generic table + lock for numbers.
Arguments: None.
Return Value: None. --*/ { PGEN_TABLE GTable;
GTable = FrsAllocType(GEN_TABLE_TYPE); INITIALIZE_CRITICAL_SECTION(>able->Critical); RtlInitializeGenericTable(>able->Table, GTabCmpTableNumberEntry, GTabAllocTableMem, GTabFreeTableMem, NULL); return GTable; }
PGEN_TABLE GTabAllocFileTimeTable( VOID ) /*++
Routine Description: Initialize a generic table + lock for file time.
Arguments: None.
Return Value: None. --*/ { PGEN_TABLE GTable;
GTable = FrsAllocType(GEN_TABLE_TYPE); INITIALIZE_CRITICAL_SECTION(>able->Critical); RtlInitializeGenericTable(>able->Table, GTabCmpTableFileTimeEntry, GTabAllocTableMem, GTabFreeTableMem, NULL); return GTable; }
PGEN_TABLE GTabAllocStringTable( VOID ) /*++
Routine Description: Initialize a generic table + lock for data with strings used as a key.
Arguments: None.
Return Value: None. --*/ { PGEN_TABLE GTable;
GTable = FrsAllocType(GEN_TABLE_TYPE); INITIALIZE_CRITICAL_SECTION(>able->Critical); RtlInitializeGenericTable(>able->Table, GTabCmpTableStringEntry, GTabAllocTableMem, GTabFreeTableMem, NULL); return GTable; }
PGEN_TABLE GTabAllocStringAndBoolTable( VOID ) /*++
Routine Description: Initialize a generic table + lock for data with a string and bool used as a key.
Arguments: None.
Return Value: None. --*/ { PGEN_TABLE GTable;
GTable = FrsAllocType(GEN_TABLE_TYPE); INITIALIZE_CRITICAL_SECTION(>able->Critical); RtlInitializeGenericTable(>able->Table, GTabCmpTableStringAndBoolEntry, GTabAllocTableMem, GTabFreeTableMem, NULL); return GTable; }
PGEN_TABLE GTabAllocTable( VOID ) /*++
Routine Description: Initialize a generic table + lock.
Arguments: None.
Return Value: None. --*/ { PGEN_TABLE GTable;
GTable = FrsAllocType(GEN_TABLE_TYPE); INITIALIZE_CRITICAL_SECTION(>able->Critical); RtlInitializeGenericTable(>able->Table, GTabCmpTableEntry, GTabAllocTableMem, GTabFreeTableMem, NULL); return GTable; }
VOID GTabEmptyTableNoLock( IN PGEN_TABLE GTable, IN PVOID (*CallerFree)(PVOID) ) /*++
Routine Description: Free every entry in the frs generic table. Caller has acquired the table lock.
Arguments:
GTable - frs generic table CallerFree - The free routine to use to free up the callers datum (optional)
Return Value: None. --*/ { PGEN_ENTRY Entry; // Next entry in table
PGEN_ENTRY Dup; // Next entry in table
PVOID Data;
//
// For every entry in the table
//
while (Entry = RtlEnumerateGenericTable(>able->Table, TRUE)) { //
// Delete the dups
//
while (Dup = Entry->Dups) { Entry->Dups = Dup->Dups; if (CallerFree) { //
// Free up the callers Datum
//
(*CallerFree)(Dup->Data); } Dup = FrsFree(Dup); }
//
// Delete the entry from the table
//
Data = Entry->Data; RtlDeleteElementGenericTable(>able->Table, Entry); if (CallerFree) { //
// Free up the callers Datum
//
(*CallerFree)(Data); } } }
VOID GTabEmptyTable( IN PGEN_TABLE GTable, IN PVOID (*CallerFree)(PVOID) ) /*++
Routine Description: Free every entry in the frs generic table.
Arguments:
GTable - frs generic table CallerFree - The free routine to use to free up the callers datum (optional)
Return Value: None. --*/ { GTabLockTable(GTable);
GTabEmptyTableNoLock(GTable, CallerFree);
GTabUnLockTable(GTable); }
PVOID GTabFreeTable( IN PGEN_TABLE GTable, IN PVOID (*CallerFree)(PVOID) ) /*++
Routine Description: Undo the work done by GenTableInitialize.
Arguments: GTTable - Address of the gen table. CallerFree - The free routine to use to free up the callers datum (optional)
Return Value: None. --*/ { if (GTable == NULL) { return NULL; }
//
// Empty the table
//
GTabEmptyTable(GTable, CallerFree);
DeleteCriticalSection(>able->Critical); return FrsFreeType(GTable); }
PVOID GTabLookupNoLock( IN PGEN_TABLE GTable, IN GUID *Key1, IN PWCHAR Key2 ) /*++
Routine Description: Find the entry in the table.
Arguments: GTable - frs generic table Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: Data for an entry or NULL --*/ { PVOID Data; PGEN_ENTRY Entry; // entry in table
GEN_ENTRY Key; // Search key
FRS_ASSERT(Key1);
//
// Set up a search key that is suitable for any table
//
Key.Key1 = Key1; Key.Key2 = Key2;
//
// Search the table
//
Entry = (PVOID)RtlLookupElementGenericTable(>able->Table, &Key); Data = (Entry) ? Entry->Data : NULL; return Data; }
PVOID GTabLookup( IN PGEN_TABLE GTable, IN GUID *Key1, IN PWCHAR Key2 ) /*++
Routine Description: Find the data for an entry in the table.
Arguments: GTable - frs generic table Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: Data for an entry or NULL --*/ { PVOID Data; PGEN_ENTRY Entry; // entry in table
GEN_ENTRY Key; // Search key
FRS_ASSERT(Key1);
//
// Set up a search key that is suitable for any table
//
Key.Key1 = Key1; Key.Key2 = Key2;
//
// Search the table
//
GTabLockTable(GTable); Entry = (PVOID)RtlLookupElementGenericTable(>able->Table, &Key); Data = (Entry) ? Entry->Data : NULL; GTabUnLockTable(GTable); return Data; }
BOOL GTabIsEntryPresent( IN PGEN_TABLE GTable, IN GUID *Key1, IN PWCHAR Key2 ) /*++
Routine Description: Find the entry in the table and return TRUE if found.
Arguments: GTable - frs generic table Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: Boolean --*/ { PVOID Data; PGEN_ENTRY Entry; // entry in table
GEN_ENTRY Key; // Search key
FRS_ASSERT(Key1);
//
// Set up a search key that is suitable for any table
//
Key.Key1 = Key1; Key.Key2 = Key2;
//
// Search the table
//
GTabLockTable(GTable); Entry = (PVOID)RtlLookupElementGenericTable(>able->Table, &Key); GTabUnLockTable(GTable); return (Entry != NULL); }
PVOID GTabLookupTableString( IN PGEN_TABLE GTable, IN PWCHAR Key1, IN PWCHAR Key2 ) /*++
Routine Description: Find the data for an entry in the table that is indexed by string.
Arguments: GTable - frs generic table Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: Data for an entry or NULL --*/ { PVOID Data; PGEN_ENTRY Entry; // entry in table
GEN_ENTRY Key; // Search key
FRS_ASSERT(Key1);
//
// Set up a search key that is suitable for any table
//
Key.Key1 = (GUID *)Key1; Key.Key2 = Key2;
//
// Search the table
//
GTabLockTable(GTable); Entry = (PVOID)RtlLookupElementGenericTable(>able->Table, &Key); Data = (Entry) ? Entry->Data : NULL; GTabUnLockTable(GTable); return Data; }
PGEN_ENTRY GTabLookupEntryNoLock( IN PGEN_TABLE GTable, IN GUID *Key1, IN PWCHAR Key2 ) /*++
Routine Description: Find the data for an entry in the table.
Arguments: GTable - frs generic table Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: Data for an entry or NULL --*/ { PGEN_ENTRY Entry; // entry in table
GEN_ENTRY Key; // Search key
FRS_ASSERT(Key1);
//
// Set up a search key that is suitable for any table
//
Key.Key1 = Key1; Key.Key2 = Key2;
//
// Search the table
//
Entry = (PVOID)RtlLookupElementGenericTable(>able->Table, &Key); return Entry; }
PGEN_ENTRY GTabNextEntryNoLock( PGEN_TABLE GTable, PVOID *Key ) /*++
Routine Description: Return the entry for Key in GTable. The caller is responsible for insuring synchronization.
Arguments: GTable - frs generic table Key - NULL on first call
Return Value: The address of an entry in the table or NULL. --*/ { PGEN_ENTRY Entry; //
// Return the entry's address
//
Entry = (PVOID)RtlEnumerateGenericTableWithoutSplaying(>able->Table, Key); return Entry; }
PVOID GTabNextDatumNoLock( PGEN_TABLE GTable, PVOID *Key ) /*++
Routine Description: Return the data for the entry for Key in GTable. Caller acquires the table lock.
Arguments: GTable - frs generic table Key - NULL on first call GetData - return the entry or the data for the entry
Return Value: The address of an entry in the table or NULL. --*/ { PVOID Data; PGEN_ENTRY Entry;
//
// Return the address of the entry's data
//
Entry = GTabNextEntryNoLock(GTable, Key); Data = (Entry) ? Entry->Data : NULL; return Data; }
PVOID GTabNextDatum( PGEN_TABLE GTable, PVOID *Key ) /*++
Routine Description: Return the data for the entry for Key in GTable.
Arguments: GTable - frs generic table Key - NULL on first call GetData - return the entry or the data for the entry
Return Value: The address of an entry in the table or NULL. --*/ { PVOID Data; PGEN_ENTRY Entry;
//
// Return the address of the entry's data
//
GTabLockTable(GTable); Entry = GTabNextEntryNoLock(GTable, Key); Data = (Entry) ? Entry->Data : NULL; GTabUnLockTable(GTable); return Data; }
DWORD GTabNumberInTable( PGEN_TABLE GTable ) /*++
Routine Description: Return the number of entries in a table.
Arguments: GTable - frs generic table
Return Value: Number of entries in the table. --*/ { if (GTable) { return RtlNumberGenericTableElements(>able->Table); } else { return 0; } }
PVOID GTabInsertUniqueEntry( IN PGEN_TABLE GTable, IN PVOID NewData, IN PVOID Key1, IN PVOID Key2 ) /*++
Routine Description: Insert an entry into the table. If a duplicate is found then return the original entry. Do not insert in that case.
Arguments: GTable - frs generic table NewData - data for the entry to insert Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: NULL if the entry was successfully inserted in the table. Pointer to the data from old entry if a collision is found. --*/ { PGEN_ENTRY OldEntry; // Existing entry in the table
BOOLEAN IsNew; // TRUE if insert found existing entry
GEN_ENTRY NewEntry; // new entry to insert.
PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
//
// Init the new entry. Have to typecast here becasue the GEN_ENTRY expects a GUID* and PWCHAR.
//
NewEntry.Data = NewData; NewEntry.Key1 = (GUID*)Key1; NewEntry.Key2 = (PWCHAR)Key2; NewEntry.Dups = NULL;
//
// Lock the table and Insert the entry
//
GTabLockTable(GTable); OldEntry = RtlInsertElementGenericTable(>able->Table, &NewEntry, sizeof(NewEntry), &IsNew);
GTabUnLockTable(GTable);
if (!IsNew) { return OldEntry; }
return NULL;
}
PVOID GTabInsertUniqueEntryNoLock( IN PGEN_TABLE GTable, IN PVOID NewData, IN PVOID Key1, IN PVOID Key2 ) /*++
Routine Description: Insert an entry into the table. If a duplicate is found then return the original entry. Do not insert in that case.
Arguments: GTable - frs generic table NewData - data for the entry to insert Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: NULL if the entry was successfully inserted in the table. Pointer to the data from old entry if a collision is found. --*/ { PGEN_ENTRY OldEntry; // Existing entry in the table
BOOLEAN IsNew; // TRUE if insert found existing entry
GEN_ENTRY NewEntry; // new entry to insert.
PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
//
// Init the new entry. Have to typecast here becasue the GEN_ENTRY expects a GUID* and PWCHAR.
//
NewEntry.Data = NewData; NewEntry.Key1 = (GUID*)Key1; NewEntry.Key2 = (PWCHAR)Key2; NewEntry.Dups = NULL;
OldEntry = RtlInsertElementGenericTable(>able->Table, &NewEntry, sizeof(NewEntry), &IsNew);
if (!IsNew) { return OldEntry; }
return NULL;
}
VOID GTabInsertEntry( IN PGEN_TABLE GTable, IN PVOID NewData, IN GUID *Key1, IN PWCHAR Key2 ) /*++
Routine Description: Insert an entry into the table. Duplicates are simply linked to the current entry.
Arguments: GTable - frs generic table NewData - data for the entry to insert Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: None. --*/ { PGEN_ENTRY OldEntry; // Existing entry in the table
BOOLEAN IsNew; // TRUE if insert found existing entry
GEN_ENTRY NewEntry; // new entry to insert.
PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
//
// Init the new entry.
//
NewEntry.Data = NewData; NewEntry.Key1 = Key1; NewEntry.Key2 = Key2; NewEntry.Dups = NULL;
//
// Lock the table and Insert the entry
//
GTabLockTable(GTable); OldEntry = RtlInsertElementGenericTable(>able->Table, &NewEntry, sizeof(NewEntry), &IsNew); if (!IsNew) { //
// Duplicate entry; add to list
//
DupEntry = FrsAlloc(sizeof(GEN_ENTRY)); CopyMemory(DupEntry, &NewEntry, sizeof(NewEntry)); DupEntry->Dups = OldEntry->Dups; OldEntry->Dups = DupEntry; } GTabUnLockTable(GTable); }
VOID GTabInsertEntryNoLock( IN PGEN_TABLE GTable, IN PVOID NewData, IN GUID *Key1, IN PWCHAR Key2 ) /*++
Routine Description: Insert an entry into the table. Duplicates are simply linked to the current entry.
Caller acquires the table lock.
Arguments: GTable - frs generic table NewData - data for the entry to insert Key1 - primary key Key2 - secondary key (may be NULL)
Return Value: None. --*/ { PGEN_ENTRY OldEntry; // Existing entry in the table
BOOLEAN IsNew; // TRUE if insert found existing entry
GEN_ENTRY NewEntry; // new entry to insert.
PGEN_ENTRY DupEntry; // Newly allocated table entry for duplicate.
//
// Init the new entry.
//
NewEntry.Data = NewData; NewEntry.Key1 = Key1; NewEntry.Key2 = Key2; NewEntry.Dups = NULL;
//
// Lock the table and Insert the entry
//
OldEntry = RtlInsertElementGenericTable(>able->Table, &NewEntry, sizeof(NewEntry), &IsNew); if (!IsNew) { //
// Duplicate entry; add to list
//
DupEntry = FrsAlloc(sizeof(GEN_ENTRY)); CopyMemory(DupEntry, &NewEntry, sizeof(NewEntry)); DupEntry->Dups = OldEntry->Dups; OldEntry->Dups = DupEntry; } }
VOID GTabDelete( IN PGEN_TABLE GTable, IN GUID *Key1, IN PWCHAR Key2, IN PVOID (*CallerFree)(PVOID) ) /*++
Routine Description: Delete the entry in the table.
Arguments: GTable - frs generic table Key1 - primary key Key2 - secondary key (may be NULL) CallerFree - The free routine to use to free up the callers datum (optional)
Return Value: None. --*/ { GEN_ENTRY Key; // Search key
PGEN_ENTRY Entry; // entry in table
PGEN_ENTRY Dup; // dup entry in table
PVOID Data;
FRS_ASSERT(Key1);
//
// Set up a search key that is suitable for either table
//
Key.Key1 = Key1; Key.Key2 = Key2;
//
// Find the entry
//
GTabLockTable(GTable); Entry = (PVOID)RtlLookupElementGenericTable(>able->Table, &Key); if (Entry == NULL) { goto out; }
//
// Delete the dups
//
while (Dup = Entry->Dups) { Entry->Dups = Dup->Dups; if (CallerFree) { //
// Free up the callers Datum
//
(*CallerFree)(Dup->Data); } Dup = FrsFree(Dup); }
//
// Delete entry
//
Data = Entry->Data; RtlDeleteElementGenericTable(>able->Table, Entry); if (CallerFree) { //
// Free up the callers Datum
//
(*CallerFree)(Data); }
out: GTabUnLockTable(GTable); }
VOID GTabDeleteNoLock( IN PGEN_TABLE GTable, IN GUID *Key1, IN PWCHAR Key2, IN PVOID (*CallerFree)(PVOID) ) /*++
Routine Description: Delete the entry in the table.
Arguments: GTable - frs generic table Key1 - primary key Key2 - secondary key (may be NULL) CallerFree - The free routine to use to free up the callers datum (optional)
Return Value: None. --*/ { GEN_ENTRY Key; // Search key
PGEN_ENTRY Entry; // entry in table
PGEN_ENTRY Dup; // dup entry in table
PVOID Data;
FRS_ASSERT(Key1);
//
// Set up a search key that is suitable for either table
//
Key.Key1 = Key1; Key.Key2 = Key2;
//
// Find the entry
//
Entry = (PVOID)RtlLookupElementGenericTable(>able->Table, &Key); if (Entry == NULL) { return; }
//
// Delete the dups
//
while (Dup = Entry->Dups) { Entry->Dups = Dup->Dups; if (CallerFree) { //
// Free up the callers Datum
//
(*CallerFree)(Dup->Data); } Dup = FrsFree(Dup); }
//
// Delete entry
//
Data = Entry->Data; RtlDeleteElementGenericTable(>able->Table, Entry); if (CallerFree) { //
// Free up the callers Datum
//
(*CallerFree)(Data); } }
VOID GTabPrintTable( IN PGEN_TABLE GTable ) /*++
Routine Description: Print the table and all of its dups.
Arguments: GTable - frs generic table
Return Value: None. --*/ { PGEN_ENTRY Entry; PGEN_ENTRY Dup; PVOID Key; CHAR Guid[GUID_CHAR_LEN + 1];
//
// print the entries
//
GTabLockTable(GTable); Key = NULL;
while (Entry = GTabNextEntryNoLock(GTable, &Key)) {
GuidToStr(Entry->Key1, &Guid[0]); if (Entry->Key2) { DPRINT3(0, "\t0x%x %s %ws\n", Entry->Data, Guid, Entry->Key2); } else { DPRINT2(0, "\t0x%x %s NULL\n", Entry->Data, Guid); }
for (Dup = Entry->Dups; Dup; Dup = Dup->Dups) {
GuidToStr(Entry->Key1, &Guid[0]); if (Dup->Key2) { DPRINT3(0, "\t0x%x %s %ws\n", Dup->Data, Guid, Dup->Key2); } else { DPRINT2(0, "\t0x%x %s NULL\n", Dup->Data, Guid); } } }
GTabUnLockTable(GTable); }
|