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.

171 lines
4.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. buffer.c
  5. Abstract:
  6. The module implements a buffer in the style popularized by
  7. Michael J. Grier (MGrier), where some amount (like MAX_PATH)
  8. of storage is preallocated (like on the stack) and if the storage
  9. needs grow beyond the preallocated size, the heap is used.
  10. Author:
  11. Jay Krell (a-JayK) June 2000
  12. Environment:
  13. User Mode or Kernel Mode (but don't preallocate much on the stack in kernel mode)
  14. Revision History:
  15. --*/
  16. #pragma warning(disable:4214) // bit field types other than int
  17. #pragma warning(disable:4201) // nameless struct/union
  18. #pragma warning(disable:4115) // named type definition in parentheses
  19. #pragma warning(disable:4127) // condition expression is constant
  20. #include "ntos.h"
  21. #include "nt.h"
  22. #include "ntrtl.h"
  23. #include "nturtl.h"
  24. #include <limits.h>
  25. NTSTATUS
  26. NTAPI
  27. RtlpEnsureBufferSize (
  28. IN ULONG Flags,
  29. IN OUT PRTL_BUFFER Buffer,
  30. IN SIZE_T Size
  31. )
  32. /*++
  33. Routine Description:
  34. This function ensures Buffer can hold Size bytes, or returns
  35. an error. It either bumps Buffer->Size closer to Buffer->StaticSize,
  36. or heap allocates.
  37. Arguments:
  38. Buffer - a Buffer object, see also RtlInitBuffer.
  39. Size - the number of bytes the caller wishes to store in Buffer->Buffer.
  40. Return Value:
  41. STATUS_SUCCESS
  42. STATUS_NO_MEMORY
  43. --*/
  44. {
  45. PUCHAR Temp;
  46. if ((Flags & ~(RTL_ENSURE_BUFFER_SIZE_NO_COPY)) != 0) {
  47. return STATUS_INVALID_PARAMETER;
  48. }
  49. if (Buffer == NULL) {
  50. return STATUS_INVALID_PARAMETER;
  51. }
  52. if (Size <= Buffer->Size) {
  53. return STATUS_SUCCESS;
  54. }
  55. // Size <= Buffer->StaticSize does not imply static allocation, it
  56. // could be heap allocation that the client poked smaller.
  57. if (Buffer->Buffer == Buffer->StaticBuffer && Size <= Buffer->StaticSize) {
  58. Buffer->Size = Size;
  59. return STATUS_SUCCESS;
  60. }
  61. //
  62. // The realloc case was messed up in Whistler, and got removed.
  63. // Put it back in Blackcomb.
  64. //
  65. Temp = (PUCHAR)RtlAllocateStringRoutine(Size);
  66. if (Temp == NULL) {
  67. return STATUS_NO_MEMORY;
  68. }
  69. if ((Flags & RTL_ENSURE_BUFFER_SIZE_NO_COPY) == 0) {
  70. RtlCopyMemory(Temp, Buffer->Buffer, Buffer->Size);
  71. }
  72. if (RTLP_BUFFER_IS_HEAP_ALLOCATED(Buffer)) {
  73. RtlFreeStringRoutine(Buffer->Buffer);
  74. Buffer->Buffer = NULL;
  75. }
  76. ASSERT(Temp != NULL);
  77. Buffer->Buffer = Temp;
  78. Buffer->Size = Size;
  79. return STATUS_SUCCESS;
  80. }
  81. NTSTATUS
  82. NTAPI
  83. RtlMultiAppendUnicodeStringBuffer (
  84. OUT PRTL_UNICODE_STRING_BUFFER Destination,
  85. IN ULONG NumberOfSources,
  86. IN const UNICODE_STRING* SourceArray
  87. )
  88. /*++
  89. Routine Description:
  90. Arguments:
  91. Destination -
  92. NumberOfSources -
  93. SourceArray -
  94. Return Value:
  95. STATUS_SUCCESS
  96. STATUS_NO_MEMORY
  97. STATUS_NAME_TOO_LONG
  98. --*/
  99. {
  100. SIZE_T Length;
  101. ULONG i;
  102. NTSTATUS Status;
  103. const SIZE_T CharSize = sizeof(*Destination->String.Buffer);
  104. const ULONG OriginalDestinationLength = Destination->String.Length;
  105. Length = OriginalDestinationLength;
  106. for (i = 0 ; i != NumberOfSources ; ++i) {
  107. Length += SourceArray[i].Length;
  108. if (Length > MAX_UNICODE_STRING_MAXLENGTH) {
  109. return STATUS_NAME_TOO_LONG;
  110. }
  111. }
  112. Length += CharSize;
  113. if (Length > MAX_UNICODE_STRING_MAXLENGTH) {
  114. return STATUS_NAME_TOO_LONG;
  115. }
  116. Status = RtlEnsureBufferSize(0, &Destination->ByteBuffer, Length);
  117. if (!NT_SUCCESS(Status)) {
  118. return Status;
  119. }
  120. Destination->String.MaximumLength = (USHORT)Length;
  121. Destination->String.Length = (USHORT)(Length - CharSize);
  122. Destination->String.Buffer = (PWSTR)Destination->ByteBuffer.Buffer;
  123. Length = OriginalDestinationLength;
  124. for (i = 0 ; i != NumberOfSources ; ++i) {
  125. RtlMoveMemory(
  126. Destination->String.Buffer + Length / CharSize,
  127. SourceArray[i].Buffer,
  128. SourceArray[i].Length);
  129. Length += SourceArray[i].Length;
  130. }
  131. Destination->String.Buffer[Length / CharSize] = 0;
  132. return STATUS_SUCCESS;
  133. }