Export (0) Print
Expand All
Expand Minimize

RtlEnumerateGenericTableLikeADirectory routine

The RtlEnumerateGenericTableLikeADirectory routine returns the elements of a generic table, one-by-one, in collation order.

Syntax


PVOID RtlEnumerateGenericTableLikeADirectory(
  _In_      PRTL_AVL_TABLE Table,
  _In_opt_  PRTL_AVL_MATCH_FUNCTION MatchFunction,
  _In_opt_  PVOID MatchData,
  _In_      ULONG NextFlag,
  _Inout_   PVOID *RestartKey,
  _Inout_   PULONG DeleteCount,
  _In_      PVOID Buffer
);

Parameters

Table [in]

A pointer to the Adelson-Velsky/Landis (AVL) table (RTL_AVL_TABLE) that will be enumerated.

MatchFunction [in, optional]

A match function that determines which entries to return. If not specified, all nodes are returned.

MatchData [in, optional]

The data to pass to the match function.

NextFlag [in]

If RestartKey is not NULL, a value of TRUE indicates that the enumeration will skip an element. If FALSE the enumeration resumes where it left off in the previous call to RtlEnumerateGenericTableLikeADirectory. If RestartKey is NULL, a value of TRUE instructs RtlEnumerateGenericTableLikeADirectory to return the next entry in the tree after the entry that matches the data in Buffer. A value of FALSE instructs RtlEnumerateGenericTableLikeADirectory to return the entry in the tree that matches the data in Buffer.

RestartKey [in, out]

A value that determines where to begin or resume the enumeration of generic table elements. If RestartKey is NULL, the enumeration begins or resumes from the position that is described in Buffer. If not NULL, the enumeration resumes from the point that RestartKey indicates. On return, the RestartKey holds a value that indicates the place in the tree where the enumeration left off. On the next call to RtlEnumerateGenericTableLikeADirectory caller should pass the same value back in to inform RtlEnumerateGenericTableLikeADirectory where to resume the enumeration. The following code example illustrates how to do this:


NextFlag = FALSE;
RestartKey = NULL;
DeleteCount = 0;
// Initialize Buffer for start/resume point
Buffer = ...
for (ptr = NULL; ptr != NULL;  ) {
  // Value returned in RestartKey will be passed back in
  // on following call (iteration):
  ptr = RtlEnumerateGenericTableLikeADirectory(
      &MyTable, NULL, NULL, TRUE, &RestartKey,
      &DeleteCount, &Buffer, sizeof(LONG) );
      ...
  // The value output in RestartKey will still be in
  // RestartKey when the
  // RtlEnumerationGenericTableLikeADirectory routine
  // is called in the next iteration of this loop.
  // This ensures that the enumeration will pick up
  // where it left off.
}

If a node is deleted from the tree between calls to RtlEnumerateGenericTableLikeADirectory, enumeration resumes from the position in the tree that is described in Buffer, no matter what the value of RestartKey.

DeleteCount [in, out]

On output, a value that indicates the current count of entries deleted from the table. Caller must pass this value back in on the next call to RtlEnumerateGenericTableLikeADirectory. This value helps the RtlEnumerateGenericTableLikeADirectory routine determine if deletions from the table have occurred between calls to RtlEnumerateGenericTableLikeADirectory. If deletions have occurred, the enumeration resumes with the table entry that matches the data in Buffer, and not with the table entry indicated by RestartKey. If RestartKey is NULL, this parameter has no effect on the enumeration..

Buffer [in]

A key expression that determines where to begin the enumeration, when RestartKey is NULL. Caller can pass in a saved key that matches a particular entry in the table and the enumeration will begin at the entry specified by the saved key, provided RestartKey is NULL and NextFlag is FALSE. To return the key that immediately follows a saved key, pass in the key here, set RestartKey to NULL and NextFlag to TRUE. If the saved key has been deleted, enumeration will begin with the next matched key.

Return value

The RtlEnumerateGenericTableLikeADirectory routine returns a pointer to a user-defined structure that is associated with the next table element in the enumeration. If there are no more new elements to return the return value is NULL.

Remarks

The RtlEnumerateGenericTableLikeADirectory routine provides a safe means to enumerate a generic table across intermixed insert and delete operations. Starting with the first matched key name, RtlEnumerateGenericTableLikeADirectory returns each name in the table exactly once, unless the name was inserted or deleted during the enumeration. When a key name is inserted or deleted during an enumeration (i.e. between calls to RtlEnumerateGenericTableLikeADirectory) it might or might not be included in the enumeration. Whether such names are included depends on the state of the name when RtlEnumerateGenericTableLikeADirectory processes the directory range in which the name is found.

There are four routines you can use to enumerate a generic table:

RtlEnumerateGenericTable

The RtlEnumerateGenericTable routine enumerates a generic table in collation order safely across insertions and deletions. However, this routine is not reentrant, so a caller that uses RtlEnumerateGenericTable must acquire exclusive access to the table during the entire enumeration. This routine often used by a caller that is deleting all the elements of a table.

RtlEnumerateGenericTableWithoutSplaying

The RtlEnumerateGenericTableWithoutSplayingroutine enumerates a generic table in collation order, and it is reentrant, so different threads can use it to read the table. However, it is not safe to use RtlEnumerateGenericTableWithoutSplayingacross insertions and deletions. Callers that use RtlEnumerateGenericTableWithoutSplayingcan share access to the table, but they must lock out changes by other threads during the entire enumeration.

RtlGetElementGenericTable

The RtlGetElementGenericTable routine enumerates a generic table in collation order, and it is reentrant, so different threads can use it to read the table. Furthermore, multiple threads can do insertions and deletions during an enumeration. A thread must obtain shared access for each individual call, but is not required to lock out changes to the table for the entire duration of the enumeration. However, insertions and deletions can cause table entries to be enumerated more than once or dropped completely. For this reason, the RtlGetElementGenericTable routine is not recommended.

RtlEnumerateGenericTableLikeADirectory

The RtlEnumerateGenericTableLikeADirectory routine enumerates a generic table in collation order; it is reentrant, and it allows multiple threads to do insertions and deletions during the enumeration without dropping or repeating key names in the enumeration. Caller must acquire shared access that locks out changes to the table across each call to the routine, but it is not necessary to hold a lock for the entire duration of the enumeration.

By default, the operating system uses splay trees to implement generic tables, but the RtlEnumerateGenericTableLikeADirectory routine only works with Adelson-Velsky/Landis (AVL) trees. To configure the generic table routines to use AVL trees instead of splay trees in your driver, insert the following define statement in a common header file before including Ntddk.h:


 #define RTL_USE_AVL_TABLES 0

If RTL_USE_AVL_TABLES is not defined, you must use the AVL form of the generic table routines.

Callers of RtlEnumerateGenericTableLikeADirectory must be running at IRQL <= APC_LEVEL if either of the following conditions holds:

  • The caller-allocated memory at Table or at Buffer is pageable.

  • The caller-supplied MatchFunction contains pageable code.

Requirements

Version

This routine is available starting with Windows XP.

Header

Ntddk.h (include Ntddk.h, Ntifs.h, or FltKernel.h)

Library

Ntoskrnl.lib

IRQL

<= APC_LEVEL (See Remarks section)

See also

RtlEnumerateGenericTable
RtlEnumerateGenericTableWithoutSplaying
RtlGetElementGenericTable

 

 

Send comments about this topic to Microsoft

Show:
© 2014 Microsoft