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.

353 lines
10 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: rtlinit.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * History:
  7. * 14-Jan-1991 mikeke
  8. \***************************************************************************/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. /**************************************************************************\
  12. * RtlCaptureAnsiString
  13. *
  14. * Converts a NULL-terminated ANSI string into a counted unicode string.
  15. *
  16. * 03-22-95 JimA Created.
  17. \**************************************************************************/
  18. BOOL RtlCaptureAnsiString(
  19. PIN_STRING pstr,
  20. LPCSTR psz,
  21. BOOL fForceAlloc)
  22. {
  23. int cbSrc, cbDst;
  24. NTSTATUS Status;
  25. pstr->fAllocated = FALSE;
  26. if (psz) {
  27. cbSrc = strlen(psz) + 1;
  28. if (cbSrc > MAXUSHORT) {
  29. RIPMSG0(RIP_WARNING, "String too long for standard string");
  30. return FALSE;
  31. }
  32. /*
  33. * If the allocation is forced or if the string is too long to fit
  34. * in the TEB, allocate a buffer. Otherwise, store the result in the
  35. * TEB.
  36. */
  37. if (fForceAlloc || cbSrc > (STATIC_UNICODE_BUFFER_LENGTH / sizeof(WCHAR))) {
  38. pstr->strCapture.Buffer = UserLocalAlloc(0, cbSrc * sizeof(WCHAR));
  39. if (pstr->strCapture.Buffer == NULL) {
  40. return FALSE;
  41. }
  42. pstr->fAllocated = TRUE;
  43. pstr->pstr = &pstr->strCapture;
  44. pstr->strCapture.MaximumLength = (USHORT)(cbSrc * sizeof(WCHAR));
  45. } else {
  46. pstr->pstr = &NtCurrentTeb()->StaticUnicodeString;
  47. }
  48. /*
  49. * Convert the string to Unicode.
  50. */
  51. Status = RtlMultiByteToUnicodeN(pstr->pstr->Buffer,
  52. (ULONG)pstr->pstr->MaximumLength,
  53. &cbDst,
  54. (LPSTR)psz,
  55. cbSrc);
  56. if (!NT_SUCCESS(Status)) {
  57. RIPMSG0(RIP_WARNING, "Unicode conversion failed");
  58. if (pstr->fAllocated) {
  59. UserLocalFree(pstr->strCapture.Buffer);
  60. pstr->fAllocated = FALSE;
  61. }
  62. return FALSE;
  63. }
  64. pstr->pstr->Length = (USHORT)cbDst - sizeof(WCHAR);
  65. } else {
  66. pstr->pstr = &pstr->strCapture;
  67. pstr->strCapture.Length = pstr->strCapture.MaximumLength = 0;
  68. pstr->strCapture.Buffer = NULL;
  69. }
  70. return TRUE;
  71. }
  72. /**************************************************************************\
  73. * RtlCaptureLargeAnsiString
  74. *
  75. * Captures a large ANSI string in the same manner as RtlCaptureAnsiString.
  76. *
  77. * 03-22-95 JimA Created.
  78. \**************************************************************************/
  79. BOOL RtlCaptureLargeAnsiString(
  80. PLARGE_IN_STRING plstr,
  81. LPCSTR psz,
  82. BOOL fForceAlloc)
  83. {
  84. int cchSrc;
  85. UINT uLength;
  86. NTSTATUS Status;
  87. plstr->fAllocated = FALSE;
  88. plstr->strCapture.bAnsi = FALSE;
  89. plstr->pstr = &plstr->strCapture;
  90. if (psz) {
  91. cchSrc = strlen(psz) + 1;
  92. /*
  93. * If the allocation is forced or if the string is too long to fit
  94. * in the TEB, allocate a buffer. Otherwise, store the result in the
  95. * TEB.
  96. */
  97. if (fForceAlloc || cchSrc > STATIC_UNICODE_BUFFER_LENGTH) {
  98. plstr->strCapture.Buffer = UserLocalAlloc(0, cchSrc * sizeof(WCHAR));
  99. if (plstr->strCapture.Buffer == NULL) {
  100. return FALSE;
  101. }
  102. plstr->fAllocated = TRUE;
  103. plstr->strCapture.MaximumLength = cchSrc * sizeof(WCHAR);
  104. } else {
  105. plstr->strCapture.Buffer = NtCurrentTeb()->StaticUnicodeBuffer;
  106. plstr->strCapture.MaximumLength =
  107. (UINT)(STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR));
  108. }
  109. /*
  110. * Convert the string to Unicode.
  111. */
  112. Status = RtlMultiByteToUnicodeN(KPWSTR_TO_PWSTR(plstr->pstr->Buffer),
  113. plstr->pstr->MaximumLength,
  114. &uLength,
  115. (LPSTR)psz,
  116. cchSrc);
  117. if (!NT_SUCCESS(Status)) {
  118. RIPMSG0(RIP_WARNING, "Unicode conversion failed");
  119. if (plstr->fAllocated) {
  120. UserLocalFree(KPWSTR_TO_PWSTR(plstr->strCapture.Buffer));
  121. plstr->fAllocated = FALSE;
  122. }
  123. return FALSE;
  124. }
  125. plstr->pstr->Length = uLength - sizeof(WCHAR);
  126. } else {
  127. plstr->strCapture.Length = plstr->strCapture.MaximumLength = 0;
  128. plstr->strCapture.Buffer = NULL;
  129. }
  130. return TRUE;
  131. }
  132. /**************************************************************************\
  133. * AllocateFromZone
  134. *
  135. * This routine removes an entry from the zone and returns a pointer to it.
  136. *
  137. * Arguments:
  138. *
  139. * Zone - Pointer to the zone header controlling the storage from which the
  140. * entry is to be allocated.
  141. *
  142. * Return Value:
  143. *
  144. * The function value is a pointer to the storage allocated from the zone.
  145. \**************************************************************************/
  146. __inline PVOID AllocateFromZone(
  147. PZONE_HEADER Zone)
  148. {
  149. PVOID ptr = (PVOID)(Zone->FreeList.Next);
  150. if (Zone->FreeList.Next) {
  151. Zone->FreeList.Next = Zone->FreeList.Next->Next;
  152. }
  153. return ptr;
  154. }
  155. /**************************************************************************\
  156. * FreeToZone
  157. *
  158. * This routine places the specified block of storage back onto the free
  159. * list in the specified zone.
  160. *
  161. * Arguments:
  162. *
  163. * Zone - Pointer to the zone header controlling the storage to which the
  164. * entry is to be inserted.
  165. *
  166. * Block - Pointer to the block of storage to be freed back to the zone.
  167. *
  168. * Return Value:
  169. *
  170. * Pointer to previous block of storage that was at the head of the free
  171. * list. NULL implies the zone went from no available free blocks to at
  172. * least one free block.
  173. \**************************************************************************/
  174. __inline VOID FreeToZone(
  175. PZONE_HEADER Zone,
  176. PVOID Block)
  177. {
  178. ((PSINGLE_LIST_ENTRY)Block)->Next = Zone->FreeList.Next;
  179. Zone->FreeList.Next = (PSINGLE_LIST_ENTRY)Block;
  180. }
  181. /***************************************************************************\
  182. * InitLookaside
  183. *
  184. * Initializes the lookaside list. This improves control locality by keeping
  185. * control entries in a single page
  186. *
  187. * 05-04-95 JimA Created.
  188. \***************************************************************************/
  189. NTSTATUS
  190. InitLookaside(
  191. PLOOKASIDE pla,
  192. DWORD cbEntry,
  193. DWORD cEntries)
  194. {
  195. ULONG i;
  196. PCH p;
  197. ULONG BlockSize;
  198. PZONE_HEADER Zone;
  199. PVOID InitialSegment;
  200. ULONG InitialSegmentSize;
  201. InitialSegmentSize = (cEntries * cbEntry) + sizeof(ZONE_SEGMENT_HEADER);
  202. p = (PCH)UserLocalAlloc(0, InitialSegmentSize);
  203. if (!p) {
  204. return STATUS_NO_MEMORY;
  205. }
  206. RtlEnterCriticalSection(&gcsLookaside);
  207. //
  208. // If the lookaside list has already been initialized, we're done.
  209. //
  210. if (pla->LookasideBase != NULL && pla->EntrySize == cbEntry) {
  211. RtlLeaveCriticalSection(&gcsLookaside);
  212. UserLocalFree(p);
  213. return STATUS_SUCCESS;
  214. }
  215. pla->LookasideBase = (PVOID)p;
  216. pla->LookasideBounds = (PVOID)(p + InitialSegmentSize);
  217. pla->EntrySize = cbEntry;
  218. //
  219. // Using the ExZone-like code, slice up the page into QMSG's
  220. //
  221. Zone = &pla->LookasideZone;
  222. BlockSize = cbEntry;
  223. InitialSegment = pla->LookasideBase;
  224. Zone->BlockSize = BlockSize;
  225. Zone->SegmentList.Next = &((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList;
  226. ((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList.Next = NULL;
  227. ((PZONE_SEGMENT_HEADER) InitialSegment)->Reserved = NULL;
  228. Zone->FreeList.Next = NULL;
  229. p = (PCH)InitialSegment + sizeof(ZONE_SEGMENT_HEADER);
  230. for (i = sizeof(ZONE_SEGMENT_HEADER);
  231. i <= InitialSegmentSize - BlockSize;
  232. i += BlockSize) {
  233. ((PSINGLE_LIST_ENTRY)p)->Next = Zone->FreeList.Next;
  234. Zone->FreeList.Next = (PSINGLE_LIST_ENTRY)p;
  235. p += BlockSize;
  236. }
  237. Zone->TotalSegmentSize = i;
  238. RtlLeaveCriticalSection(&gcsLookaside);
  239. return STATUS_SUCCESS;
  240. }
  241. /***************************************************************************\
  242. * AllocLookasideEntry
  243. *
  244. * Allocates an entry from the lookaside list.
  245. *
  246. * 05-04-95 JimA Created.
  247. \***************************************************************************/
  248. PVOID AllocLookasideEntry(
  249. PLOOKASIDE pla)
  250. {
  251. PVOID pEntry;
  252. //
  253. // Attempt to get an entry from the zone. If this fails, then
  254. // UserLocalAlloc the entry.
  255. //
  256. RtlEnterCriticalSection(&gcsLookaside);
  257. pEntry = AllocateFromZone(&pla->LookasideZone);
  258. RtlLeaveCriticalSection(&gcsLookaside);
  259. if (!pEntry) {
  260. /*
  261. * Allocate a local structure.
  262. */
  263. #if DBG
  264. pla->AllocSlowCalls++;
  265. #endif
  266. if ((pEntry = UserLocalAlloc(0, pla->EntrySize)) == NULL) {
  267. return NULL;
  268. }
  269. }
  270. RtlZeroMemory(pEntry, pla->EntrySize);
  271. #if DBG
  272. pla->AllocCalls++;
  273. if (pla->AllocCalls - pla->DelCalls > pla->AllocHiWater) {
  274. pla->AllocHiWater = pla->AllocCalls - pla->DelCalls;
  275. }
  276. #endif
  277. return pEntry;
  278. }
  279. /***************************************************************************\
  280. * FreeLookasideEntry
  281. *
  282. * Returns a qmsg to the lookaside buffer or free the memory.
  283. *
  284. * 05-04-95 JimA Created.
  285. \***************************************************************************/
  286. VOID FreeLookasideEntry(
  287. PLOOKASIDE pla,
  288. PVOID pEntry)
  289. {
  290. #if DBG
  291. pla->DelCalls++;
  292. #endif
  293. //
  294. // If the pEntry was from zone, then free to zone.
  295. //
  296. if ((PVOID)pEntry >= pla->LookasideBase && (PVOID)pEntry < pla->LookasideBounds) {
  297. RtlEnterCriticalSection(&gcsLookaside);
  298. FreeToZone(&pla->LookasideZone, pEntry);
  299. RtlLeaveCriticalSection(&gcsLookaside);
  300. } else {
  301. #if DBG
  302. pla->DelSlowCalls++;
  303. #endif
  304. UserLocalFree(pEntry);
  305. }
  306. }