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.

580 lines
16 KiB

  1. /*++ BUILD Version: 0005 // Increment this if a change has global effects
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. llsrtl.h
  5. Abstract:
  6. Include file for NT runtime routines that are callable by both
  7. kernel mode code in the executive and user mode code in various
  8. NT subsystems.
  9. Author:
  10. Steve Wood (stevewo) 31-Mar-1989
  11. Environment:
  12. These routines are statically linked in the caller's executable and
  13. are callable in either kernel mode or user mode.
  14. Revision History:
  15. --*/
  16. #ifndef _LLSRTL_
  17. #define _LLSRTL_
  18. #if defined (_MSC_VER)
  19. #if ( _MSC_VER >= 800 )
  20. #pragma warning(disable:4514)
  21. #if _MSC_VER >= 1200
  22. #pragma warning(push)
  23. #endif
  24. #pragma warning(disable:4001)
  25. #pragma warning(disable:4201)
  26. #pragma warning(disable:4214)
  27. #endif
  28. #if (_MSC_VER > 1020)
  29. #pragma once
  30. #endif
  31. #endif
  32. // begin_ntddk begin_wdm begin_winnt begin_ntifs begin_nthal
  33. //
  34. // for move macros
  35. //
  36. #ifdef _MAC
  37. #ifndef _INC_STRING
  38. #include <string.h>
  39. #endif /* _INC_STRING */
  40. #else
  41. #include <string.h>
  42. #endif // _MAC
  43. // end_ntddk end_wdm end_winnt end_ntifs end_nthal
  44. #ifdef __cplusplus
  45. extern "C" {
  46. #endif
  47. // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntndis
  48. //
  49. // If debugging support enabled, define an ASSERT macro that works. Otherwise
  50. // define the ASSERT macro to expand to an empty expression.
  51. //
  52. #if DBG
  53. NTSYSAPI
  54. VOID
  55. NTAPI
  56. RtlAssert(
  57. PVOID FailedAssertion,
  58. PVOID FileName,
  59. ULONG LineNumber,
  60. PCHAR Message
  61. );
  62. #ifndef ASSERT
  63. #define ASSERT( exp ) \
  64. ((!(exp)) ? \
  65. RtlAssert( #exp, __FILE__, __LINE__, NULL ) : \
  66. ((void)0))
  67. #endif
  68. #ifndef ASSERTMSG
  69. #define ASSERTMSG( msg, exp ) \
  70. ((!(exp)) ? \
  71. RtlAssert( #exp, __FILE__, __LINE__, msg ) : \
  72. ((void)0))
  73. #endif
  74. #else
  75. #ifndef ASSERT
  76. #define ASSERT( exp ) ((void)0)
  77. #endif
  78. #ifndef ASSERTMSG
  79. #define ASSERTMSG( msg, exp ) ((void)0)
  80. #endif
  81. #endif // DBG
  82. // end_ntddk end_wdm end_nthal end_ntifs end_ntndis
  83. // begin_ntddk begin_wdm begin_nthal begin_ntifs begin_ntndis
  84. //
  85. // Doubly-linked list manipulation routines. Implemented as macros
  86. // but logically these are procedures.
  87. //
  88. //
  89. // VOID
  90. // InitializeListHead(
  91. // PLIST_ENTRY ListHead
  92. // );
  93. //
  94. #define InitializeListHead(ListHead) (\
  95. (ListHead)->Flink = (ListHead)->Blink = (ListHead))
  96. //
  97. // BOOLEAN
  98. // IsListEmpty(
  99. // PLIST_ENTRY ListHead
  100. // );
  101. //
  102. #define IsListEmpty(ListHead) \
  103. ((ListHead)->Flink == (ListHead))
  104. //
  105. // PLIST_ENTRY
  106. // RemoveHeadList(
  107. // PLIST_ENTRY ListHead
  108. // );
  109. //
  110. #define RemoveHeadList(ListHead) \
  111. (ListHead)->Flink;\
  112. {RemoveEntryList((ListHead)->Flink)}
  113. //
  114. // PLIST_ENTRY
  115. // RemoveTailList(
  116. // PLIST_ENTRY ListHead
  117. // );
  118. //
  119. #define RemoveTailList(ListHead) \
  120. (ListHead)->Blink;\
  121. {RemoveEntryList((ListHead)->Blink)}
  122. //
  123. // VOID
  124. // RemoveEntryList(
  125. // PLIST_ENTRY Entry
  126. // );
  127. //
  128. #define RemoveEntryList(Entry) {\
  129. PLIST_ENTRY _EX_Blink;\
  130. PLIST_ENTRY _EX_Flink;\
  131. _EX_Flink = (Entry)->Flink;\
  132. _EX_Blink = (Entry)->Blink;\
  133. _EX_Blink->Flink = _EX_Flink;\
  134. _EX_Flink->Blink = _EX_Blink;\
  135. }
  136. //
  137. // VOID
  138. // InsertTailList(
  139. // PLIST_ENTRY ListHead,
  140. // PLIST_ENTRY Entry
  141. // );
  142. //
  143. #define InsertTailList(ListHead,Entry) {\
  144. PLIST_ENTRY _EX_Blink;\
  145. PLIST_ENTRY _EX_ListHead;\
  146. _EX_ListHead = (ListHead);\
  147. _EX_Blink = _EX_ListHead->Blink;\
  148. (Entry)->Flink = _EX_ListHead;\
  149. (Entry)->Blink = _EX_Blink;\
  150. _EX_Blink->Flink = (Entry);\
  151. _EX_ListHead->Blink = (Entry);\
  152. }
  153. //
  154. // VOID
  155. // InsertHeadList(
  156. // PLIST_ENTRY ListHead,
  157. // PLIST_ENTRY Entry
  158. // );
  159. //
  160. #define InsertHeadList(ListHead,Entry) {\
  161. PLIST_ENTRY _EX_Flink;\
  162. PLIST_ENTRY _EX_ListHead;\
  163. _EX_ListHead = (ListHead);\
  164. _EX_Flink = _EX_ListHead->Flink;\
  165. (Entry)->Flink = _EX_Flink;\
  166. (Entry)->Blink = _EX_ListHead;\
  167. _EX_Flink->Blink = (Entry);\
  168. _EX_ListHead->Flink = (Entry);\
  169. }
  170. //
  171. //
  172. // PSINGLE_LIST_ENTRY
  173. // PopEntryList(
  174. // PSINGLE_LIST_ENTRY ListHead
  175. // );
  176. //
  177. #define PopEntryList(ListHead) \
  178. (ListHead)->Next;\
  179. {\
  180. PSINGLE_LIST_ENTRY FirstEntry;\
  181. FirstEntry = (ListHead)->Next;\
  182. if (FirstEntry != NULL) { \
  183. (ListHead)->Next = FirstEntry->Next;\
  184. } \
  185. }
  186. //
  187. // VOID
  188. // PushEntryList(
  189. // PSINGLE_LIST_ENTRY ListHead,
  190. // PSINGLE_LIST_ENTRY Entry
  191. // );
  192. //
  193. #define PushEntryList(ListHead,Entry) \
  194. (Entry)->Next = (ListHead)->Next; \
  195. (ListHead)->Next = (Entry)
  196. // end_wdm end_nthal end_ntifs end_ntndis
  197. // end_ntddk
  198. //
  199. // Define the generic table package. Note a generic table should really
  200. // be an opaque type. We provide routines to manipulate the structure.
  201. //
  202. // A generic table is package for inserting, deleting, and looking up elements
  203. // in a table (e.g., in a symbol table). To use this package the user
  204. // defines the structure of the elements stored in the table, provides a
  205. // comparison function, a memory allocation function, and a memory
  206. // deallocation function.
  207. //
  208. // Note: the user compare function must impose a complete ordering among
  209. // all of the elements, and the table does not allow for duplicate entries.
  210. //
  211. //
  212. // Add an empty typedef so that functions can reference the
  213. // a pointer to the generic table struct before it is declared.
  214. //
  215. struct _LLS_GENERIC_TABLE;
  216. //
  217. // The results of a compare can be less than, equal, or greater than.
  218. //
  219. typedef enum _LLS_GENERIC_COMPARE_RESULTS {
  220. LLSGenericLessThan,
  221. LLSGenericGreaterThan,
  222. LLSGenericEqual
  223. } LLS_GENERIC_COMPARE_RESULTS;
  224. //
  225. // The comparison function takes as input pointers to elements containing
  226. // user defined structures and returns the results of comparing the two
  227. // elements.
  228. //
  229. typedef
  230. LLS_GENERIC_COMPARE_RESULTS
  231. (NTAPI *PLLS_GENERIC_COMPARE_ROUTINE) (
  232. struct _LLS_GENERIC_TABLE *Table,
  233. PVOID FirstStruct,
  234. PVOID SecondStruct
  235. );
  236. //
  237. // The allocation function is called by the generic table package whenever
  238. // it needs to allocate memory for the table.
  239. //
  240. typedef
  241. PVOID
  242. (NTAPI *PLLS_GENERIC_ALLOCATE_ROUTINE) (
  243. struct _LLS_GENERIC_TABLE *Table,
  244. CLONG ByteSize
  245. );
  246. //
  247. // The deallocation function is called by the generic table package whenever
  248. // it needs to deallocate memory from the table that was allocated by calling
  249. // the user supplied allocation function.
  250. //
  251. typedef
  252. VOID
  253. (NTAPI *PLLS_GENERIC_FREE_ROUTINE) (
  254. struct _LLS_GENERIC_TABLE *Table,
  255. PVOID Buffer
  256. );
  257. //
  258. // To use the generic table package the user declares a variable of type
  259. // GENERIC_TABLE and then uses the routines described below to initialize
  260. // the table and to manipulate the table. Note that the generic table
  261. // should really be an opaque type.
  262. //
  263. typedef struct _LLS_GENERIC_TABLE {
  264. PRTL_SPLAY_LINKS TableRoot;
  265. LIST_ENTRY InsertOrderList;
  266. PLIST_ENTRY OrderedPointer;
  267. ULONG WhichOrderedElement;
  268. ULONG NumberGenericTableElements;
  269. PLLS_GENERIC_COMPARE_ROUTINE CompareRoutine;
  270. PLLS_GENERIC_ALLOCATE_ROUTINE AllocateRoutine;
  271. PLLS_GENERIC_FREE_ROUTINE FreeRoutine;
  272. PVOID TableContext;
  273. } LLS_GENERIC_TABLE;
  274. typedef LLS_GENERIC_TABLE *PLLS_GENERIC_TABLE;
  275. //
  276. // This enumerated type is used as the function return value of the function
  277. // that is used to search the tree for a key. FoundNode indicates that the
  278. // function found the key. Insert as left indicates that the key was not found
  279. // and the node should be inserted as the left child of the parent. Insert as
  280. // right indicates that the key was not found and the node should be inserted
  281. // as the right child of the parent.
  282. //
  283. typedef enum _LLS_TABLE_SEARCH_RESULT{
  284. LLSTableEmptyTree,
  285. LLSTableFoundNode,
  286. LLSTableInsertAsLeft,
  287. LLSTableInsertAsRight
  288. } LLS_TABLE_SEARCH_RESULT;
  289. //
  290. // The procedure InitializeGenericTable takes as input an uninitialized
  291. // generic table variable and pointers to the three user supplied routines.
  292. // This must be called for every individual generic table variable before
  293. // it can be used.
  294. //
  295. VOID
  296. NTAPI
  297. LLSInitializeGenericTable (
  298. PLLS_GENERIC_TABLE Table,
  299. PLLS_GENERIC_COMPARE_ROUTINE CompareRoutine,
  300. PLLS_GENERIC_ALLOCATE_ROUTINE AllocateRoutine,
  301. PLLS_GENERIC_FREE_ROUTINE FreeRoutine,
  302. PVOID TableContext
  303. );
  304. //
  305. // The function InsertElementGenericTable will insert a new element
  306. // in a table. It does this by allocating space for the new element
  307. // (this includes splay links), inserting the element in the table, and
  308. // then returning to the user a pointer to the new element. If an element
  309. // with the same key already exists in the table the return value is a pointer
  310. // to the old element. The optional output parameter NewElement is used
  311. // to indicate if the element previously existed in the table. Note: the user
  312. // supplied Buffer is only used for searching the table, upon insertion its
  313. // contents are copied to the newly created element. This means that
  314. // pointer to the input buffer will not point to the new element.
  315. //
  316. PVOID
  317. NTAPI
  318. LLSInsertElementGenericTable (
  319. PLLS_GENERIC_TABLE Table,
  320. PVOID Buffer,
  321. CLONG BufferSize,
  322. PBOOLEAN NewElement OPTIONAL
  323. );
  324. //
  325. // The function InsertElementGenericTableFull will insert a new element
  326. // in a table. It does this by allocating space for the new element
  327. // (this includes splay links), inserting the element in the table, and
  328. // then returning to the user a pointer to the new element. If an element
  329. // with the same key already exists in the table the return value is a pointer
  330. // to the old element. The optional output parameter NewElement is used
  331. // to indicate if the element previously existed in the table. Note: the user
  332. // supplied Buffer is only used for searching the table, upon insertion its
  333. // contents are copied to the newly created element. This means that
  334. // pointer to the input buffer will not point to the new element.
  335. // This routine is passed the NodeOrParent and SearchResult from a
  336. // previous RtlLookupElementGenericTableFull.
  337. //
  338. PVOID
  339. NTAPI
  340. LLSInsertElementGenericTableFull (
  341. PLLS_GENERIC_TABLE Table,
  342. PVOID Buffer,
  343. CLONG BufferSize,
  344. PBOOLEAN NewElement OPTIONAL,
  345. PVOID NodeOrParent,
  346. LLS_TABLE_SEARCH_RESULT SearchResult
  347. );
  348. //
  349. // The function DeleteElementGenericTable will find and delete an element
  350. // from a generic table. If the element is located and deleted the return
  351. // value is TRUE, otherwise if the element is not located the return value
  352. // is FALSE. The user supplied input buffer is only used as a key in
  353. // locating the element in the table.
  354. //
  355. BOOLEAN
  356. NTAPI
  357. LLSDeleteElementGenericTable (
  358. PLLS_GENERIC_TABLE Table,
  359. PVOID Buffer
  360. );
  361. //
  362. // The function LookupElementGenericTable will find an element in a generic
  363. // table. If the element is located the return value is a pointer to
  364. // the user defined structure associated with the element, otherwise if
  365. // the element is not located the return value is NULL. The user supplied
  366. // input buffer is only used as a key in locating the element in the table.
  367. //
  368. PVOID
  369. NTAPI
  370. LLSLookupElementGenericTable (
  371. PLLS_GENERIC_TABLE Table,
  372. PVOID Buffer
  373. );
  374. //
  375. // The function LookupElementGenericTableFull will find an element in a generic
  376. // table. If the element is located the return value is a pointer to
  377. // the user defined structure associated with the element. If the element is not
  378. // located then a pointer to the parent for the insert location is returned. The
  379. // user must look at the SearchResult value to determine which is being returned.
  380. // The user can use the SearchResult and parent for a subsequent FullInsertElement
  381. // call to optimize the insert.
  382. //
  383. PVOID
  384. NTAPI
  385. LLSLookupElementGenericTableFull (
  386. PLLS_GENERIC_TABLE Table,
  387. PVOID Buffer,
  388. OUT PVOID *NodeOrParent,
  389. OUT LLS_TABLE_SEARCH_RESULT *SearchResult
  390. );
  391. //
  392. // The function EnumerateGenericTable will return to the caller one-by-one
  393. // the elements of of a table. The return value is a pointer to the user
  394. // defined structure associated with the element. The input parameter
  395. // Restart indicates if the enumeration should start from the beginning
  396. // or should return the next element. If the are no more new elements to
  397. // return the return value is NULL. As an example of its use, to enumerate
  398. // all of the elements in a table the user would write:
  399. //
  400. // for (ptr = EnumerateGenericTable(Table, TRUE);
  401. // ptr != NULL;
  402. // ptr = EnumerateGenericTable(Table, FALSE)) {
  403. // :
  404. // }
  405. //
  406. //
  407. // PLEASE NOTE:
  408. //
  409. // If you enumerate a GenericTable using RtlEnumerateGenericTable, you
  410. // will flatten the table, turning it into a sorted linked list.
  411. // To enumerate the table without perturbing the splay links, use
  412. // RtlEnumerateGenericTableWithoutSplaying
  413. PVOID
  414. NTAPI
  415. LLSEnumerateGenericTable (
  416. PLLS_GENERIC_TABLE Table,
  417. BOOLEAN Restart
  418. );
  419. //
  420. // The function EnumerateGenericTableWithoutSplaying will return to the
  421. // caller one-by-one the elements of of a table. The return value is a
  422. // pointer to the user defined structure associated with the element.
  423. // The input parameter RestartKey indicates if the enumeration should
  424. // start from the beginning or should return the next element. If the
  425. // are no more new elements to return the return value is NULL. As an
  426. // example of its use, to enumerate all of the elements in a table the
  427. // user would write:
  428. //
  429. // RestartKey = NULL;
  430. // for (ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey);
  431. // ptr != NULL;
  432. // ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey)) {
  433. // :
  434. // }
  435. //
  436. // If RestartKey is NULL, the package will start from the least entry in the
  437. // table, otherwise it will start from the last entry returned.
  438. //
  439. //
  440. // Note that unlike RtlEnumerateGenericTable, this routine will NOT perturb
  441. // the splay order of the tree.
  442. //
  443. PVOID
  444. NTAPI
  445. LLSEnumerateGenericTableWithoutSplaying (
  446. PLLS_GENERIC_TABLE Table,
  447. PVOID *RestartKey
  448. );
  449. //
  450. // The function GetElementGenericTable will return the i'th element
  451. // inserted in the generic table. I = 0 implies the first element,
  452. // I = (RtlNumberGenericTableElements(Table)-1) will return the last element
  453. // inserted into the generic table. The type of I is ULONG. Values
  454. // of I > than (NumberGenericTableElements(Table)-1) will return NULL. If
  455. // an arbitrary element is deleted from the generic table it will cause
  456. // all elements inserted after the deleted element to "move up".
  457. PVOID
  458. NTAPI
  459. LLSGetElementGenericTable(
  460. PLLS_GENERIC_TABLE Table,
  461. ULONG I
  462. );
  463. //
  464. // The function NumberGenericTableElements returns a ULONG value
  465. // which is the number of generic table elements currently inserted
  466. // in the generic table.
  467. ULONG
  468. NTAPI
  469. LLSNumberGenericTableElements(
  470. PLLS_GENERIC_TABLE Table
  471. );
  472. //
  473. // The function IsGenericTableEmpty will return to the caller TRUE if
  474. // the input table is empty (i.e., does not contain any elements) and
  475. // FALSE otherwise.
  476. //
  477. BOOLEAN
  478. NTAPI
  479. LLSIsGenericTableEmpty (
  480. PLLS_GENERIC_TABLE Table
  481. );
  482. // end_ntifs
  483. #endif // _LLSRTL_