Source code of Windows XP (NT5)
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.

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