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.

248 lines
6.5 KiB

  1. #include "nt.h"
  2. #include "ntdef.h"
  3. #include "ntrtl.h"
  4. #include "nturtl.h"
  5. #include "ntrtl.h"
  6. #include "sxs-rtl.h"
  7. #include "skiplist.h"
  8. #include "stringpool.h"
  9. NTSTATUS
  10. RtlAllocateStringInPool(
  11. ULONG ulFlags,
  12. PRTL_STRING_POOL pStringPool,
  13. PUNICODE_STRING pusOutbound,
  14. SIZE_T ulByteCount
  15. )
  16. {
  17. NTSTATUS status;
  18. ULONG idx;
  19. PRTL_STRING_POOL_FRAME pFrameWithFreeSpace = NULL;
  20. RtlZeroMemory(pusOutbound, sizeof(*pusOutbound));
  21. if (!ARGUMENT_PRESENT(pStringPool) || !ARGUMENT_PRESENT(pusOutbound) || (ulByteCount >= 0xFFFF) ) {
  22. return STATUS_INVALID_PARAMETER;
  23. }
  24. //
  25. // Zing through frames in the string pool looking for a frame with
  26. // enough bytes open
  27. //
  28. for (idx = 0; idx < pStringPool->ulFramesCount; idx++) {
  29. status = RtlIndexIntoGrowingList(
  30. &pStringPool->FrameList,
  31. idx,
  32. (PVOID*)&pFrameWithFreeSpace,
  33. FALSE);
  34. if (!NT_SUCCESS(status)) {
  35. return status;
  36. }
  37. //
  38. // There's space in this frame!
  39. //
  40. if (pFrameWithFreeSpace->cbRegionAvailable >= ulByteCount) {
  41. break;
  42. }
  43. }
  44. //
  45. // Frame not found, index one past the current limit, implicitly (potentially)
  46. // allocating into the growing list
  47. //
  48. if (pFrameWithFreeSpace == NULL) {
  49. status = RtlIndexIntoGrowingList(
  50. &pStringPool->FrameList,
  51. pStringPool->ulFramesCount,
  52. (PVOID*)&pFrameWithFreeSpace,
  53. TRUE);
  54. if (!NT_SUCCESS(status)) {
  55. return status;
  56. }
  57. //
  58. // Requested byte count is larger than the bytes in a new region? Bump up the
  59. // size of new regions to twice this size
  60. //
  61. if (ulByteCount > pStringPool->cbBytesInNewRegion) {
  62. pStringPool->cbBytesInNewRegion = ulByteCount * 2;
  63. }
  64. status = pStringPool->Allocator.pfnAlloc(
  65. pStringPool->cbBytesInNewRegion,
  66. (PVOID*)&pFrameWithFreeSpace->pvRegion,
  67. pStringPool->Allocator.pvContext);
  68. if (!NT_SUCCESS(status)) {
  69. return STATUS_NO_MEMORY;
  70. }
  71. pFrameWithFreeSpace->pvNextAvailable = pFrameWithFreeSpace->pvRegion;
  72. pFrameWithFreeSpace->cbRegionAvailable = pStringPool->cbBytesInNewRegion;
  73. }
  74. //
  75. // Sanity checking
  76. //
  77. ASSERT(pFrameWithFreeSpace != NULL);
  78. ASSERT(pFrameWithFreeSpace->cbRegionAvailable >= ulByteCount);
  79. //
  80. // Bookkeeping in the frame
  81. //
  82. pFrameWithFreeSpace->cbRegionAvailable -= ulByteCount;
  83. pFrameWithFreeSpace->pvNextAvailable = (PVOID)(((ULONG_PTR)pFrameWithFreeSpace->pvNextAvailable) + ulByteCount);
  84. //
  85. // Set up the outbound thing
  86. //
  87. pusOutbound->Buffer = pFrameWithFreeSpace->pvNextAvailable;
  88. pusOutbound->MaximumLength = (USHORT)ulByteCount;
  89. pusOutbound->Length = 0;
  90. return STATUS_SUCCESS;
  91. }
  92. NTSTATUS
  93. RtlDestroyStringPool(
  94. PRTL_STRING_POOL pStringPool
  95. )
  96. {
  97. NTSTATUS status;
  98. PRTL_STRING_POOL_FRAME pFrame = NULL;
  99. ULONG ul;
  100. //
  101. // Zing through frames and deallocate those that weren't allocated
  102. // inline with the pool
  103. //
  104. for (ul = 0; ul < pStringPool->ulFramesCount; ul++) {
  105. status = RtlIndexIntoGrowingList(
  106. &pStringPool->FrameList,
  107. ul,
  108. (PVOID*)&pFrame,
  109. FALSE);
  110. if (!NT_SUCCESS(status)) {
  111. return status;
  112. }
  113. if ((pFrame->ulFlags & RTL_STRING_POOL_FRAME_FLAG_REGION_INLINE) == 0) {
  114. status = pStringPool->Allocator.pfnFree(pFrame->pvRegion, pStringPool->Allocator.pvContext);
  115. pFrame->pvRegion = NULL;
  116. pFrame->pvNextAvailable = NULL;
  117. pFrame->cbRegionAvailable = 0;
  118. }
  119. }
  120. //
  121. // We're done, destroy the list itself
  122. //
  123. status = RtlDestroyGrowingList(&pStringPool->FrameList);
  124. if (!NT_SUCCESS(status)) {
  125. return status;
  126. }
  127. //
  128. // No frames, list destroyed
  129. //
  130. pStringPool->ulFramesCount = 0;
  131. //
  132. // Great.
  133. //
  134. return STATUS_SUCCESS;
  135. }
  136. NTSTATUS
  137. RtlCreateStringPool(
  138. ULONG ulFlags,
  139. PRTL_STRING_POOL pStringPool,
  140. SIZE_T cbBytesInFrames,
  141. PRTL_ALLOCATOR Allocator,
  142. PVOID pvOriginalRegion,
  143. SIZE_T cbOriginalRegion
  144. )
  145. {
  146. NTSTATUS status;
  147. //
  148. // Ick. Heap allocation all the way
  149. //
  150. if ((cbOriginalRegion == 0) || (pvOriginalRegion == NULL)) {
  151. status = RtlInitializeGrowingList(
  152. &pStringPool->FrameList,
  153. sizeof(RTL_STRING_POOL_FRAME),
  154. 20,
  155. NULL,
  156. 0,
  157. Allocator);
  158. pStringPool->ulFramesCount = 0;
  159. pStringPool->Allocator = *Allocator;
  160. pStringPool->cbBytesInNewRegion = cbBytesInFrames;
  161. return STATUS_SUCCESS;
  162. }
  163. //
  164. // Good, space for at least one frame, donate the remainder to the list
  165. //
  166. else if (cbOriginalRegion >= sizeof(RTL_STRING_POOL_FRAME)) {
  167. RTL_STRING_POOL_FRAME* pFirstFrame = NULL;
  168. status = RtlInitializeGrowingList(
  169. &pStringPool->FrameList,
  170. sizeof(RTL_STRING_POOL_FRAME),
  171. 20,
  172. pvOriginalRegion,
  173. sizeof(RTL_STRING_POOL_FRAME),
  174. Allocator);
  175. pStringPool->ulFramesCount = pStringPool->FrameList.cInternalElements;
  176. pStringPool->Allocator = *Allocator;
  177. pStringPool->cbBytesInNewRegion = cbBytesInFrames;
  178. if (pStringPool->ulFramesCount) {
  179. status = RtlIndexIntoGrowingList(
  180. &pStringPool->FrameList,
  181. 0,
  182. (PVOID*)&pFirstFrame,
  183. FALSE);
  184. //
  185. // Wierd...
  186. //
  187. if ((status == STATUS_NO_MEMORY) || (status == STATUS_NOT_FOUND)) {
  188. pStringPool->ulFramesCount = 0;
  189. }
  190. else {
  191. pFirstFrame->pvRegion = pFirstFrame->pvNextAvailable =
  192. (PVOID)(((ULONG_PTR)pvOriginalRegion) + sizeof(RTL_STRING_POOL_FRAME));
  193. pFirstFrame->cbRegionAvailable = cbOriginalRegion - sizeof(RTL_STRING_POOL_FRAME);
  194. pFirstFrame->ulFlags = RTL_STRING_POOL_FRAME_FLAG_REGION_INLINE;
  195. }
  196. }
  197. return STATUS_SUCCESS;
  198. }
  199. return STATUS_INVALID_PARAMETER;
  200. }