RtlEnumerateGenericTableLikeADirectory routine

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


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


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.


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:


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.


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.


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.


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:


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.


Target platform



This routine is available starting with Windows XP.


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






<= APC_LEVEL (See Remarks section)

See also




Send comments about this topic to Microsoft