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.

329 lines
9.4 KiB

  1. /*++
  2. Copyright (c) Microsoft 1998, All Rights Reserved
  3. Module Name:
  4. strings.c
  5. Abstract:
  6. This module contains code for converting data buffers and integer values
  7. to and from string representation for display.
  8. Environment:
  9. User mode
  10. Revision History:
  11. May-98 : Created
  12. --*/
  13. #include <windows.h>
  14. #include <stdlib.h>
  15. #include <limits.h>
  16. #include <math.h>
  17. #include "strings.h"
  18. #define ROUND_UP_ON_DIVIDE(d, n) (0 == ((d) % (n)) ? ((d)/(n)) : ((d)/(n))+1)
  19. VOID
  20. Strings_CreateDataBufferString(
  21. IN PCHAR DataBuffer,
  22. IN ULONG DataBufferLength,
  23. IN ULONG NumBytesToDisplay,
  24. IN ULONG DisplayBlockSize,
  25. OUT PCHAR *BufferString
  26. )
  27. /*++
  28. Routine Description:
  29. This routine takes a DataBuffer of size DataBufferLength and creates a string
  30. in BufferString that contains a string representation of the bytes stored in
  31. data buffer.
  32. The parameter NumBytesToDisplay tells the routine the maximum number of bytes
  33. from the buffer to display. For instance, a caller may only want to convert
  34. the first four bytes of an eight byte buffer to a string
  35. The parameter DisplayBlockSize indicates how many bytes should be grouped
  36. together in the display. Valid values are 1, 2, 4 and would indicate whether
  37. the displayed bytes should be displayed as bytes, words, or dwords.
  38. The routine allocates a buffer big enough to store the data. Callers of this
  39. routine are responsible for freeing this string buffer.
  40. --*/
  41. {
  42. ULONG BufferStringLength;
  43. ULONG MaxDisplayedBytes;
  44. PUCHAR NextByte;
  45. PUCHAR String;
  46. PUCHAR CurrentBufferOffset;
  47. INT nFullIterations;
  48. INT LeftOverBytes;
  49. INT IterationIndex;
  50. INT ByteOffset;
  51. /*
  52. // Determine the maximum number of bytes that will be displayed in
  53. // the string
  54. */
  55. MaxDisplayedBytes = (NumBytesToDisplay > DataBufferLength) ? DataBufferLength
  56. : NumBytesToDisplay;
  57. /*
  58. // Determine the size of the string we'll need: This is based on the
  59. // maximum number of displayed bytes (MaxDisplayedBytes) and the
  60. // DisplayBlockSize
  61. */
  62. BufferStringLength = 2*MaxDisplayedBytes + ROUND_UP_ON_DIVIDE(MaxDisplayedBytes,
  63. DisplayBlockSize
  64. );
  65. /*
  66. // Now we need to allocate string space
  67. */
  68. String = (PCHAR) malloc(BufferStringLength * sizeof(CHAR));
  69. if (NULL != String) {
  70. /*
  71. // Determine how many iterations through the conversion routine must be made.
  72. */
  73. nFullIterations = MaxDisplayedBytes / DisplayBlockSize;
  74. /*
  75. // Initialize our variables which point to data in the buffer to convert
  76. // and the byte in the string in which to put the converted data value.
  77. // Next byte is set to String-1 because it is incremented on entry into the
  78. // loop.
  79. */
  80. CurrentBufferOffset = DataBuffer;
  81. NextByte = String-1;
  82. /*
  83. // Each iteration of the loop creates a block of DisplayBlockSize. Any
  84. // partial iterations are performed afterwards if the number of bytes
  85. // to display is not a multiple of the display block size
  86. */
  87. for (IterationIndex = 0; IterationIndex < nFullIterations; IterationIndex++)
  88. {
  89. NextByte++;
  90. /*
  91. // Output a block of data size. Notice the bytes are accessed in
  92. // reverse order to display the the MSB of a block as the first
  93. // value in the string
  94. */
  95. for (ByteOffset = DisplayBlockSize-1; ByteOffset >= 0; ByteOffset--)
  96. {
  97. wsprintf(NextByte, "%02X", *(CurrentBufferOffset+ByteOffset));
  98. NextByte += 2;
  99. }
  100. /*
  101. // Insert the space to separate blocks
  102. */
  103. *(NextByte) = ' ';
  104. CurrentBufferOffset += DisplayBlockSize;
  105. }
  106. /*
  107. // Resolve any other bytes that are left over
  108. */
  109. LeftOverBytes = (MaxDisplayedBytes % DisplayBlockSize);
  110. if (0 == LeftOverBytes)
  111. {
  112. *(NextByte) = '\0';
  113. }
  114. for (ByteOffset = LeftOverBytes-1, NextByte++; ByteOffset >= 0; ByteOffset--)
  115. {
  116. wsprintf(NextByte, "%02X", *(CurrentBufferOffset+ByteOffset));
  117. NextByte += 2;
  118. }
  119. }
  120. *BufferString = String;
  121. return;
  122. }
  123. BOOL
  124. Strings_StringToUnsignedList(
  125. IN OUT PCHAR InString,
  126. IN ULONG UnsignedSize,
  127. IN ULONG Base,
  128. OUT PCHAR *UnsignedList,
  129. OUT PULONG nUnsigneds
  130. )
  131. /*++
  132. Routine Description:
  133. This routine takes an input string, InString, and creates a list of unsigned
  134. values of all the values that are in the list. The caller can specify a
  135. base, Base, for all the numbers in the list or specify 0 to let the function
  136. determine the base depending on the format of the number in the string.
  137. The parameter UnsignedSize specifies the size of unsigneds to store in the list.
  138. The routine allocates a CHAR buffer to store the list of unsigned values.
  139. On exit, nUnsigneds will report the number of unsigned values stored in
  140. UnsignedList.
  141. The function will return TRUE if it could convert all of the numbers in the
  142. string into the unsigned list. It will return FALSE if there was a problem
  143. with the string or if there was a problem allocating memory to store the
  144. unsigned list.
  145. --*/
  146. {
  147. CHAR tokDelims[] = "\t,; ";
  148. PCHAR strToken;
  149. PCHAR endp;
  150. BOOL fStatus;
  151. ULONG ulValue;
  152. PCHAR pList;
  153. PCHAR pNewList;
  154. ULONG nAllocUnsigneds;
  155. ULONG nActualUnsigneds;
  156. ULONG ulMaxValue;
  157. /*
  158. // Begin by initializing our unsigned list
  159. // 1) Start with initial allocation for 2 unsigneds, this will
  160. // be expanded if necessary
  161. // 2) If initial allocation fails, return FALSE;
  162. */
  163. nAllocUnsigneds = 2;
  164. nActualUnsigneds = 0;
  165. pList = (PCHAR) malloc(nAllocUnsigneds * sizeof(ULONG));
  166. if (NULL == pList)
  167. {
  168. return (FALSE);
  169. }
  170. /*
  171. // Calculate the maximum value that can be represented with the value for
  172. // iBufferSize;
  173. */
  174. ulMaxValue = (sizeof(ULONG) == UnsignedSize) ? ULONG_MAX
  175. : (1 << (UnsignedSize*8)) - 1;
  176. /*
  177. // Begin our processing of the token string.
  178. // 1) Set fStatus to TRUE to get through loop the first time
  179. // 2) Try to get the first token -- if we can't get the first token
  180. // then we pass through loop
  181. */
  182. fStatus = TRUE;
  183. strToken = strtok(InString, tokDelims);
  184. /*
  185. // Loop until there are no more tokens or we detect an error (fStatus == FALSE)
  186. */
  187. while (NULL != strToken && fStatus)
  188. {
  189. /*
  190. // Set fStatus initially to false. Only if nothing goes wrong in
  191. // the loop will this get set to TRUE
  192. */
  193. fStatus = FALSE;
  194. /*
  195. // Attempt to convert the token
  196. */
  197. ulValue = strtoul(strToken, &endp, Base);
  198. /*
  199. // To be a valid value, *endp must point to the NULL character
  200. */
  201. if ('\0' == *endp)
  202. {
  203. /*
  204. // Check to see that the ulValue found is less than or equal to
  205. // the maximum allowed by UnsignedSize.
  206. */
  207. if (ulValue <= ulMaxValue)
  208. {
  209. /*
  210. // If we're set to overrun our buffer, attempt to allocate
  211. // more space. If we can't then release the old space
  212. // and fail the loop.
  213. */
  214. if (nAllocUnsigneds == nActualUnsigneds)
  215. {
  216. nAllocUnsigneds *= 2;
  217. pNewList = (PCHAR) realloc(pList, UnsignedSize*nAllocUnsigneds);
  218. if (NULL == pNewList)
  219. {
  220. break;
  221. }
  222. pList = pNewList;
  223. }
  224. /*
  225. // Add the token to the end of the list of unsigneds
  226. */
  227. memcpy(pList + (UnsignedSize * nActualUnsigneds),
  228. &ulValue,
  229. UnsignedSize);
  230. nActualUnsigneds++;
  231. /*
  232. // Prepare to reenter the loop. Set fStatus = TRUE
  233. // Try to get another token
  234. */
  235. fStatus = TRUE;
  236. strToken = strtok(NULL, tokDelims);
  237. }
  238. }
  239. }
  240. /*
  241. // If the loop failed for some reason or we found no unsigneds
  242. // release the list
  243. */
  244. if (!fStatus || 0 == nActualUnsigneds)
  245. {
  246. free(pList);
  247. pList = NULL;
  248. nActualUnsigneds = 0;
  249. }
  250. *UnsignedList = pList;
  251. *nUnsigneds = nActualUnsigneds;
  252. return (fStatus);
  253. }