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.

657 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. cnvint.c
  5. Abstract:
  6. Text to integer and integer to text converion routines.
  7. Author:
  8. Steve Wood (stevewo) 23-Aug-1990
  9. Revision History:
  10. --*/
  11. #include <ntrtlp.h>
  12. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  13. #pragma alloc_text(PAGE,RtlIntegerToChar)
  14. #pragma alloc_text(PAGE,RtlCharToInteger)
  15. #pragma alloc_text(PAGE,RtlUnicodeStringToInteger)
  16. #pragma alloc_text(PAGE,RtlIntegerToUnicode)
  17. #pragma alloc_text(PAGE,RtlIntegerToUnicodeString)
  18. #pragma alloc_text(PAGE,RtlLargeIntegerToChar)
  19. #pragma alloc_text(PAGE,RtlLargeIntegerToUnicode)
  20. #pragma alloc_text(PAGE,RtlInt64ToUnicodeString)
  21. #endif
  22. #if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  23. #pragma const_seg("PAGECONST")
  24. #endif
  25. const CHAR RtlpIntegerChars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  26. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  27. const WCHAR RtlpIntegerWChars[] = { L'0', L'1', L'2', L'3', L'4', L'5',
  28. L'6', L'7', L'8', L'9', L'A', L'B',
  29. L'C', L'D', L'E', L'F' };
  30. NTSTATUS
  31. RtlIntegerToChar (
  32. IN ULONG Value,
  33. IN ULONG Base OPTIONAL,
  34. IN LONG OutputLength,
  35. OUT PSZ String
  36. )
  37. /*++
  38. Routine Description:
  39. Arguments:
  40. Return Value:
  41. --*/
  42. {
  43. CHAR Result[33], *s;
  44. ULONG Shift, Mask, Digit, Length;
  45. RTL_PAGED_CODE();
  46. Shift = 0;
  47. switch( Base ) {
  48. case 16: Shift = 4; break;
  49. case 8: Shift = 3; break;
  50. case 2: Shift = 1; break;
  51. case 0: Base = 10;
  52. case 10: Shift = 0; break;
  53. default: return( STATUS_INVALID_PARAMETER );
  54. }
  55. if (Shift != 0) {
  56. Mask = (1 << Shift) - 1;
  57. }
  58. s = &Result[33];
  59. do {
  60. if (Shift != 0) {
  61. Digit = Value & Mask;
  62. Value >>= Shift;
  63. } else {
  64. Digit = Value % Base;
  65. Value = Value / Base;
  66. }
  67. *--s = RtlpIntegerChars[Digit];
  68. } while (Value != 0);
  69. Length = (ULONG) (&Result[33] - s);
  70. if (OutputLength < 0) {
  71. OutputLength = -OutputLength;
  72. while ((LONG)Length < OutputLength) {
  73. *String++ = '0';
  74. OutputLength--;
  75. }
  76. }
  77. if ((LONG)Length > OutputLength) {
  78. return (STATUS_BUFFER_OVERFLOW);
  79. } else {
  80. try {
  81. RtlCopyMemory (String, s, Length);
  82. if ((LONG)Length < OutputLength) {
  83. String[Length] = '\0';
  84. }
  85. } except (EXCEPTION_EXECUTE_HANDLER) {
  86. return (GetExceptionCode ());
  87. }
  88. return (STATUS_SUCCESS);
  89. }
  90. }
  91. NTSTATUS
  92. RtlCharToInteger (
  93. IN PCSZ String,
  94. IN ULONG Base OPTIONAL,
  95. OUT PULONG Value
  96. )
  97. {
  98. CHAR c, Sign;
  99. ULONG Result, Digit, Shift;
  100. RTL_PAGED_CODE();
  101. while ((Sign = *String++) <= ' ') {
  102. if (!*String) {
  103. String--;
  104. break;
  105. }
  106. }
  107. c = Sign;
  108. if (c == '-' || c == '+') {
  109. c = *String++;
  110. }
  111. if (!ARGUMENT_PRESENT( Base )) {
  112. Base = 10;
  113. Shift = 0;
  114. if (c == '0') {
  115. c = *String++;
  116. if (c == 'x') {
  117. Base = 16;
  118. Shift = 4;
  119. } else if (c == 'o') {
  120. Base = 8;
  121. Shift = 3;
  122. } else if (c == 'b') {
  123. Base = 2;
  124. Shift = 1;
  125. } else {
  126. String--;
  127. }
  128. c = *String++;
  129. }
  130. } else {
  131. switch( Base ) {
  132. case 16: Shift = 4; break;
  133. case 8: Shift = 3; break;
  134. case 2: Shift = 1; break;
  135. case 10: Shift = 0; break;
  136. default: return( STATUS_INVALID_PARAMETER );
  137. }
  138. }
  139. Result = 0;
  140. while (c) {
  141. if (c >= '0' && c <= '9') {
  142. Digit = c - '0';
  143. } else if (c >= 'A' && c <= 'F') {
  144. Digit = c - 'A' + 10;
  145. } else if (c >= 'a' && c <= 'f') {
  146. Digit = c - 'a' + 10;
  147. } else {
  148. break;
  149. }
  150. if (Digit >= Base) {
  151. break;
  152. }
  153. if (Shift == 0) {
  154. Result = (Base * Result) + Digit;
  155. } else {
  156. Result = (Result << Shift) | Digit;
  157. }
  158. c = *String++;
  159. }
  160. if (Sign == '-') {
  161. Result = (ULONG)(-(LONG)Result);
  162. }
  163. try {
  164. *Value = Result;
  165. } except( EXCEPTION_EXECUTE_HANDLER ) {
  166. return( GetExceptionCode() );
  167. }
  168. return( STATUS_SUCCESS );
  169. }
  170. NTSTATUS
  171. RtlUnicodeStringToInteger (
  172. IN PCUNICODE_STRING String,
  173. IN ULONG Base OPTIONAL,
  174. OUT PULONG Value
  175. )
  176. {
  177. PCWSTR s;
  178. WCHAR c, Sign;
  179. ULONG nChars, Result, Digit, Shift;
  180. RTL_PAGED_CODE();
  181. s = String->Buffer;
  182. nChars = String->Length / sizeof( WCHAR );
  183. while (nChars-- && (Sign = *s++) <= ' ') {
  184. if (!nChars) {
  185. Sign = UNICODE_NULL;
  186. break;
  187. }
  188. }
  189. c = Sign;
  190. if (c == L'-' || c == L'+') {
  191. if (nChars) {
  192. nChars--;
  193. c = *s++;
  194. }
  195. else {
  196. c = UNICODE_NULL;
  197. }
  198. }
  199. if (!ARGUMENT_PRESENT( Base )) {
  200. Base = 10;
  201. Shift = 0;
  202. if (c == L'0') {
  203. if (nChars) {
  204. nChars--;
  205. c = *s++;
  206. if (c == L'x') {
  207. Base = 16;
  208. Shift = 4;
  209. }
  210. else
  211. if (c == L'o') {
  212. Base = 8;
  213. Shift = 3;
  214. }
  215. else
  216. if (c == L'b') {
  217. Base = 2;
  218. Shift = 1;
  219. }
  220. else {
  221. nChars++;
  222. s--;
  223. }
  224. }
  225. if (nChars) {
  226. nChars--;
  227. c = *s++;
  228. }
  229. else {
  230. c = UNICODE_NULL;
  231. }
  232. }
  233. }
  234. else {
  235. switch( Base ) {
  236. case 16: Shift = 4; break;
  237. case 8: Shift = 3; break;
  238. case 2: Shift = 1; break;
  239. case 10: Shift = 0; break;
  240. default: return( STATUS_INVALID_PARAMETER );
  241. }
  242. }
  243. Result = 0;
  244. while (c != UNICODE_NULL) {
  245. if (c >= L'0' && c <= L'9') {
  246. Digit = c - L'0';
  247. }
  248. else
  249. if (c >= L'A' && c <= L'F') {
  250. Digit = c - L'A' + 10;
  251. }
  252. else
  253. if (c >= L'a' && c <= L'f') {
  254. Digit = c - L'a' + 10;
  255. }
  256. else {
  257. break;
  258. }
  259. if (Digit >= Base) {
  260. break;
  261. }
  262. if (Shift == 0) {
  263. Result = (Base * Result) + Digit;
  264. }
  265. else {
  266. Result = (Result << Shift) | Digit;
  267. }
  268. if (!nChars) {
  269. break;
  270. }
  271. nChars--;
  272. c = *s++;
  273. }
  274. if (Sign == L'-') {
  275. Result = (ULONG)(-(LONG)Result);
  276. }
  277. try {
  278. *Value = Result;
  279. }
  280. except( EXCEPTION_EXECUTE_HANDLER ) {
  281. return( GetExceptionCode() );
  282. }
  283. return( STATUS_SUCCESS );
  284. }
  285. NTSTATUS
  286. RtlIntegerToUnicode (
  287. IN ULONG Value,
  288. IN ULONG Base OPTIONAL,
  289. IN LONG OutputLength,
  290. OUT PWSTR String
  291. )
  292. /*++
  293. Routine Description:
  294. Arguments:
  295. Return Value:
  296. --*/
  297. {
  298. WCHAR Result[33], *s;
  299. ULONG Shift, Mask, Digit, Length;
  300. RTL_PAGED_CODE();
  301. Shift = 0;
  302. switch( Base ) {
  303. case 16: Shift = 4; break;
  304. case 8: Shift = 3; break;
  305. case 2: Shift = 1; break;
  306. case 0: Base = 10;
  307. case 10: Shift = 0; break;
  308. default: return (STATUS_INVALID_PARAMETER);
  309. }
  310. if (Shift != 0) {
  311. Mask = (1 << Shift) - 1;
  312. }
  313. s = &Result[33];
  314. do {
  315. if (Shift != 0) {
  316. Digit = Value & Mask;
  317. Value >>= Shift;
  318. } else {
  319. Digit = Value % Base;
  320. Value = Value / Base;
  321. }
  322. *--s = RtlpIntegerWChars[ Digit ];
  323. } while (Value != 0);
  324. Length = (ULONG) (&Result[33] - s);
  325. if (OutputLength < 0) {
  326. OutputLength = -OutputLength;
  327. while ((LONG)Length < OutputLength) {
  328. *String++ = L'0';
  329. OutputLength--;
  330. }
  331. }
  332. if ((LONG)Length > OutputLength) {
  333. return (STATUS_BUFFER_OVERFLOW);
  334. } else {
  335. try {
  336. RtlCopyMemory (String, s, Length * sizeof (WCHAR));
  337. if ((LONG)Length < OutputLength) {
  338. String[Length] = L'\0';
  339. }
  340. } except (EXCEPTION_EXECUTE_HANDLER) {
  341. return (GetExceptionCode ());
  342. }
  343. return (STATUS_SUCCESS);
  344. }
  345. }
  346. NTSTATUS
  347. RtlIntegerToUnicodeString (
  348. IN ULONG Value,
  349. IN ULONG Base OPTIONAL,
  350. IN OUT PUNICODE_STRING String
  351. )
  352. {
  353. NTSTATUS Status;
  354. UCHAR ResultBuffer[16];
  355. ANSI_STRING AnsiString;
  356. RTL_PAGED_CODE();
  357. Status = RtlIntegerToChar (Value, Base, sizeof (ResultBuffer), ResultBuffer);
  358. if (NT_SUCCESS (Status)) {
  359. AnsiString.Buffer = ResultBuffer;
  360. AnsiString.MaximumLength = sizeof (ResultBuffer);
  361. AnsiString.Length = (USHORT)strlen (ResultBuffer);
  362. Status = RtlAnsiStringToUnicodeString (String, &AnsiString, FALSE);
  363. }
  364. return( Status );
  365. }
  366. #define MAX_DIGITS 65
  367. NTSTATUS
  368. RtlLargeIntegerToChar (
  369. IN PLARGE_INTEGER Value,
  370. IN ULONG Base OPTIONAL,
  371. IN LONG OutputLength,
  372. OUT PSZ String
  373. )
  374. /*++
  375. Routine Description:
  376. Arguments:
  377. Return Value:
  378. --*/
  379. {
  380. CHAR Result[MAX_DIGITS], *s;
  381. ULONG Shift, Mask, Digit, Length;
  382. RTL_PAGED_CODE();
  383. Shift = 0;
  384. switch (Base) {
  385. case 16: Shift = 4; break;
  386. case 8: Shift = 3; break;
  387. case 2: Shift = 1; break;
  388. case 0:
  389. case 10: Shift = 0; break;
  390. default: return (STATUS_INVALID_PARAMETER);
  391. }
  392. if (Shift != 0) {
  393. Mask = (1 << Shift) - 1;
  394. }
  395. s = &Result[MAX_DIGITS];
  396. if (Shift != 0) {
  397. ULONGLONG tValue;
  398. tValue = (ULONGLONG) Value->QuadPart;
  399. do {
  400. Digit = (ULONG) (tValue & Mask);
  401. tValue = tValue >> Shift;
  402. *--s = RtlpIntegerChars[Digit];
  403. } while (tValue != 0);
  404. } else {
  405. LARGE_INTEGER TempValue = *Value;
  406. do {
  407. TempValue = RtlExtendedLargeIntegerDivide (TempValue, Base, &Digit);
  408. *--s = RtlpIntegerChars [Digit];
  409. } while (TempValue.QuadPart != 0);
  410. }
  411. Length = (ULONG)(&Result[MAX_DIGITS] - s);
  412. if (OutputLength < 0) {
  413. OutputLength = -OutputLength;
  414. while ((LONG)Length < OutputLength) {
  415. *String++ = '0';
  416. OutputLength--;
  417. }
  418. }
  419. if ((LONG)Length > OutputLength) {
  420. return (STATUS_BUFFER_OVERFLOW);
  421. } else {
  422. try {
  423. RtlCopyMemory (String, s, Length);
  424. if ((LONG)Length < OutputLength) {
  425. String[Length] = '\0';
  426. }
  427. } except (EXCEPTION_EXECUTE_HANDLER) {
  428. return (GetExceptionCode ());
  429. }
  430. return (STATUS_SUCCESS);
  431. }
  432. }
  433. NTSTATUS
  434. RtlLargeIntegerToUnicode (
  435. IN PLARGE_INTEGER Value,
  436. IN ULONG Base OPTIONAL,
  437. IN LONG OutputLength,
  438. OUT PWSTR String
  439. )
  440. /*++
  441. Routine Description:
  442. Arguments:
  443. Return Value:
  444. --*/
  445. {
  446. WCHAR Result [MAX_DIGITS], *s;
  447. ULONG Shift, Mask, Digit, Length;
  448. RTL_PAGED_CODE();
  449. Shift = 0;
  450. switch (Base) {
  451. case 16: Shift = 4; break;
  452. case 8: Shift = 3; break;
  453. case 2: Shift = 1; break;
  454. case 0:
  455. case 10: Shift = 0; break;
  456. default: return (STATUS_INVALID_PARAMETER);
  457. }
  458. if (Shift != 0) {
  459. Mask = (1 << Shift) - 1;
  460. }
  461. s = &Result [MAX_DIGITS];
  462. if (Shift != 0) {
  463. ULONGLONG tValue;
  464. tValue = (ULONGLONG) Value->QuadPart;
  465. do {
  466. Digit = (ULONG) (tValue & Mask);
  467. tValue = tValue >> Shift;
  468. *--s = RtlpIntegerWChars[Digit];
  469. } while (tValue != 0);
  470. } else {
  471. LARGE_INTEGER TempValue = *Value;
  472. do {
  473. TempValue = RtlExtendedLargeIntegerDivide (TempValue, Base, &Digit);
  474. *--s = RtlpIntegerWChars[Digit];
  475. } while (TempValue.QuadPart != 0);
  476. }
  477. Length = (ULONG)(&Result[MAX_DIGITS] - s);
  478. ASSERT (Length <= MAX_DIGITS);
  479. if (OutputLength < 0) {
  480. OutputLength = -OutputLength;
  481. while ((LONG)Length < OutputLength) {
  482. *String++ = L'0';
  483. OutputLength--;
  484. }
  485. }
  486. if ((LONG)Length > OutputLength) {
  487. return (STATUS_BUFFER_OVERFLOW);
  488. } else {
  489. try {
  490. RtlCopyMemory (String, s, Length * sizeof(WCHAR));
  491. if ((LONG)Length < OutputLength) {
  492. String [Length] = L'\0';
  493. }
  494. } except (EXCEPTION_EXECUTE_HANDLER) {
  495. return (GetExceptionCode ());
  496. }
  497. return (STATUS_SUCCESS);
  498. }
  499. }
  500. NTSTATUS
  501. RtlInt64ToUnicodeString (
  502. IN ULONGLONG Value,
  503. IN ULONG Base OPTIONAL,
  504. IN OUT PUNICODE_STRING String
  505. )
  506. {
  507. NTSTATUS Status;
  508. UCHAR ResultBuffer[32];
  509. ANSI_STRING AnsiString;
  510. LARGE_INTEGER Temp;
  511. RTL_PAGED_CODE();
  512. Temp.QuadPart = Value;
  513. Status = RtlLargeIntegerToChar(&Temp,
  514. Base,
  515. sizeof(ResultBuffer),
  516. ResultBuffer);
  517. if (NT_SUCCESS(Status)) {
  518. AnsiString.Buffer = ResultBuffer;
  519. AnsiString.MaximumLength = sizeof(ResultBuffer);
  520. AnsiString.Length = (USHORT)strlen(ResultBuffer);
  521. Status = RtlAnsiStringToUnicodeString(String, &AnsiString, FALSE);
  522. }
  523. return Status;
  524. }
  525. #if defined(ALLOC_DATA_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  526. #pragma const_seg()
  527. #endif