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.

235 lines
10 KiB

  1. /*
  2. * rhizome.h
  3. *
  4. * author: John R. Douceur
  5. * date: 28 April 1997
  6. *
  7. * This header file defines structures, function prototypes, and macros for
  8. * the rhizome database. The code is object-oriented C, transliterated from
  9. * a C++ implementation.
  10. *
  11. * The rhizome is a database that stores patterns containing wildcards.
  12. * Each pattern defines a set of keys that it matches; if a pattern contains
  13. * N wildcards, then it matches 2^N keys. Since each pattern can match
  14. * multiple keys, it is possible for a given key to match multiple patterns
  15. * in the database. The rhizome requires that all patterns stored therein
  16. * have a strict hierarchical interrelationship. Two patterns may match no
  17. * common keys (in which case the patterns are said to be independent), or
  18. * one pattern may match all the keys matched by a second pattern as well as
  19. * additonal keys (in which case the second pattern is said to be more general
  20. * than the first, and the first more specific than the second). The database
  21. * will not accept two patterns which match some keys in common but each of
  22. * which also matches additional keys that the other does not.
  23. *
  24. * The database can be searched for patterns that match a given search key.
  25. * When the database is searched for a given key, the most specifically
  26. * matching pattern is found. If no patterns in the database match the key,
  27. * an appropriate indication is returned.
  28. *
  29. * Because this code is C, rather than C++, it is not possible to hide as
  30. * much of the implementation from the client code as one might wish.
  31. * Nonetheless, there is an attempt to isolate the client from some of the
  32. * implementation details through the use of macros. Below is described each
  33. * of the functions and macros necessary to use the rhizome database.
  34. *
  35. */
  36. #ifndef _INC_RHIZOME
  37. #define _INC_RHIZOME
  38. #ifdef __cplusplus
  39. extern "C" {
  40. #endif
  41. //
  42. // Macros and definitions needed to duplicate GPC environment
  43. //
  44. #define GpcAllocMem(Addr, Len, _Tag) \
  45. *(Addr) = ExAllocatePoolWithTag(NonPagedPool, (Len), (_Tag))
  46. #define GpcFreeMem(Address, _Tag) \
  47. ExFreePool((Address))
  48. typedef NTSTATUS GPC_STATUS;
  49. #define GPC_STATUS_SUCCESS STATUS_SUCCESS
  50. #define GPC_STATUS_PENDING STATUS_PENDING
  51. #define GPC_STATUS_FAILURE STATUS_UNSUCCESSFUL
  52. #define GPC_STATUS_RESOURCES STATUS_INSUFFICIENT_RESOURCES
  53. #define GPC_STATUS_NOTREADY STATUS_DEVICE_NOT_READY
  54. #define GPC_STATUS_NOT_FOUND STATUS_NOT_FOUND
  55. #define GPC_STATUS_CONFLICT STATUS_DUPLICATE_NAME
  56. #define GPC_STATUS_INVALID_HANDLE STATUS_INVALID_HANDLE
  57. #define GPC_STATUS_INVALID_PARAMETER STATUS_INVALID_PARAMETER
  58. #define GPC_STATUS_NOT_SUPPORTED STATUS_NOT_SUPPORTED
  59. #define GPC_STATUS_NOT_EMPTY STATUS_DIRECTORY_NOT_EMPTY
  60. #define GPC_STATUS_TOO_MANY_HANDLES STATUS_TOO_MANY_OPENED_FILES
  61. #define GPC_STATUS_NOT_IMPLEMENTED STATUS_NOT_IMPLEMENTED
  62. #define GPC_STATUS_INSUFFICIENT_BUFFER STATUS_BUFFER_TOO_SMALL
  63. #define GPC_STATUS_NO_MEMORY STATUS_NO_MEMORY
  64. #define GPC_STATUS_IGNORED 1L
  65. /*
  66. * There are two basic structures employed: the RhizomeNode and the Rhizome.
  67. * Ideally, these would be completely hidden from the client, but the macro
  68. * GetReferenceFromPatternHandle requires knowledge of the structure's
  69. * definition. It is strongly urged that the client not directly refer to any
  70. * of the fields of either of these structures. To support the documentation
  71. * of the accompanying rhizome.c file, these structures are annotated with
  72. * internal comments, but these can be ignored by the reader who wishes only
  73. * to understand how to write client code for the rhizome.
  74. *
  75. * The client refers to a pattern by its PatternHandle. This is typedefed to
  76. * a pointer to RhizomeNode, but this fact should be ignored by the client,
  77. * since it is an implementation detail.
  78. *
  79. */
  80. //#include <stdlib.h>
  81. //#include <malloc.h>
  82. struct _RhizomeNode
  83. {
  84. // This structure is used for both branch nodes and leaf nodes. The two
  85. // are distinguished by the value of the pivot_bit field. For branch
  86. // nodes, pivot_bit < keybits, and for leaf nodes, pivot_bit == keybits.
  87. int pivot_bit; // for branch nodes, bit of key on which to branch
  88. union
  89. {
  90. struct // data for branch node
  91. {
  92. struct _RhizomeNode *children[2]; // pointers to children in search
  93. } branch;
  94. struct // data for leaf node
  95. {
  96. void *reference; // reference value supplied by client
  97. struct _RhizomeNode *godparent; // pointer to more general pattern
  98. } leaf;
  99. } udata;
  100. char cdata[1]; // space for storing value, mask, and imask fields
  101. };
  102. typedef struct _RhizomeNode RhizomeNode;
  103. struct _Rhizome
  104. {
  105. int keybits; // number of bits in key
  106. int keybytes; // number of bytes in key, calculated from keybits
  107. RhizomeNode *root; // root of search trie
  108. };
  109. typedef struct _Rhizome Rhizome;
  110. // The client uses PatternHandle to refer to patterns stored in the database.
  111. typedef RhizomeNode *PatternHandle;
  112. /*
  113. * The client interface to the rhizome is provided by five functions and two
  114. * macros. It is expected that the client will first instantiate a database,
  115. * either on the stack or the heap, and then insert patterns with corresponding
  116. * reference information into the database. When the client then performs a
  117. * search on a key, the client wishes to know which pattern most specifically
  118. * matches the key, and it ultimately wants the reference information
  119. * associated with the most specifically matching pattern.
  120. *
  121. */
  122. // A rhizome may be allocated on the stack simply by declaring a variable of
  123. // type Rhizome. To allocate it on the heap, the following macro returns a
  124. // pointer to a new Rhizome structure. If this macro is used, a corresponding
  125. // call to free() must be made to deallocate the structure from the heap.
  126. //
  127. //#define NEW_Rhizome ((Rhizome *)malloc(sizeof(Rhizome)))
  128. #define AllocateRhizome(_r) GpcAllocMem(&(_r), sizeof(Rhizome), NAT_TAG_RHIZOME)
  129. #define FreeRhizome(_r) GpcFreeMem((_r), NAT_TAG_RHIZOME)
  130. // Since this is not C++, the Rhizome structure is not self-constructing;
  131. // therefore, the following constructor code must be called on the Rhizome
  132. // structure after it is allocated. The argument keybits specifies the size
  133. // (in bits) of each pattern that will be stored in the database.
  134. //
  135. void
  136. constructRhizome(
  137. Rhizome *rhizome,
  138. int keybits);
  139. // Since this is not C++, the Rhizome structure is not self-destructing;
  140. // therefore, the following destructor code must be called on the Rhizome
  141. // structure before it is deallocated. However, if the client code can be
  142. // sure, based upon its usage of the database, that all patterns have been
  143. // removed before the structure is deallocated, then this function is
  144. // unnecessary.
  145. //
  146. void
  147. destructRhizome(
  148. Rhizome *rhizome);
  149. // Once the Rhizome structure has been allocated and constructed, patterns can
  150. // be inserted into the database. Each pattern is specified by a value and a
  151. // mask. Each bit of the mask determines whether the bit position is specified
  152. // or is a wildcard: A 1 in a mask bit indicates that the value of that bit is
  153. // specified by the pattern; a 0 indicates that the value of that bit is a
  154. // wildcard. If a mask bit is 1, then the corresponding bit in the value field
  155. // indicates the specified value of that bit. Value and mask fields are passed
  156. // as arrays of bytes.
  157. //
  158. // The client also specifies a reference value, as a void pointer, that it
  159. // wishes to associate with this pattern. When the pattern is installed, the
  160. // insertRhizome function returns a pointer to a PatternHandle. From the
  161. // PatternHandle can be gotten the reference value via the macro
  162. // GetReferenceFromPatternHandle.
  163. //
  164. // If the new pattern conflicts with a pattern already installed in the
  165. // database, meaning that the two patterns match some keys in common but each
  166. // also matches additional keys that the other does not, then the new pattern
  167. // is not inserted, and a value of 0 is returned as the PatternHandle.
  168. //
  169. PatternHandle
  170. insertRhizome(
  171. Rhizome *rhizome,
  172. char *value,
  173. char *mask,
  174. void *reference,
  175. ulong *status);
  176. // This function removes a pattern from the rhizome. The pattern is specified
  177. // by the PatternHandle that was returned by the insertRhizome function. No
  178. // checks are performed to insure that this is a valid handle, so the client
  179. // must discard the handle after it has called removeRhizome.
  180. //
  181. void
  182. removeRhizome(
  183. Rhizome *rhizome,
  184. PatternHandle phandle);
  185. // This function searches the database for the pattern that most specifically
  186. // matches the given key. The key is passed as an array of bytes. When the
  187. // most specific match is found, the PatternHandle of that matching pattern is
  188. // returned. From the PatternHandle can be gotten the reference value via the
  189. // macro GetReferenceFromPatternHandle. If no pattern in the database is found
  190. // to match the key, then a value of 0 is returned as the PatternHandle.
  191. //
  192. PatternHandle
  193. searchRhizome(
  194. Rhizome *rhizome,
  195. char *key);
  196. // To get the client-supplied reference value from a PatternHandle, the
  197. // following macro should be used. The client should not make assumptions
  198. // about the details of the RhizomeNode structure, nor should it even assume
  199. // that the PatternHandle is a pointer to a RhizomeNode.
  200. //
  201. #define GetReferenceFromPatternHandle(phandle) ((PatternHandle)phandle)->udata.leaf.reference
  202. #define GetKeyPtrFromPatternHandle(_r,phandle) (((PatternHandle)phandle)->cdata)
  203. #define GetMaskPtrFromPatternHandle(_r,phandle) (((PatternHandle)phandle)->cdata + (_r)->keybytes)
  204. #define GetKeySizeBytes(_r) ((_r)->keybytes)
  205. #define GetNextMostSpecificMatchingPatternHandle(phandle) ((phandle)->udata.leaf.godparent)
  206. #ifdef __cplusplus
  207. }
  208. #endif
  209. #endif /* _INC_RHIZOME */