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.

134 lines
3.3 KiB

  1. // STRTOHEX.CPP
  2. //
  3. // Utility functions to convert string representations of hexadecimal numbers
  4. // into the numbers themselves.
  5. //
  6. // Note: These functions are in their own file, rather than in STRUTIL.CPP,
  7. // because they use a const array. The current implementation of the linker
  8. // pulls this array into binaries if they use any function in the source file,
  9. // not just the functions which reference this array.
  10. #include "precomp.h"
  11. #include <strutil.h>
  12. // This array maps ASCII chars in the range '0' - 'f' to their hex equivalent.
  13. // INVALID_CHAR_ID is used to mark slots that don't correspond to a valid
  14. // hex char.
  15. const BYTE INVALID_CHAR_ID = (BYTE) -1;
  16. const BYTE rgbHexCharMap[] =
  17. {
  18. // ASCII 0x30 - 0x3f
  19. 0, 1, 2, 3,
  20. 4, 5, 6, 7,
  21. 8, 9, INVALID_CHAR_ID, INVALID_CHAR_ID,
  22. INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID,
  23. // ASCII 0x40 - 0x4f
  24. INVALID_CHAR_ID, 0xA, 0xB, 0xC,
  25. 0xD, 0xE, 0xF, INVALID_CHAR_ID,
  26. INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID,
  27. INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID,
  28. // ASCII 0x50 - 0x5f
  29. INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID,
  30. INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID,
  31. INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID,
  32. INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID, INVALID_CHAR_ID,
  33. // ASCII 0x60 - 0x67
  34. INVALID_CHAR_ID, 0xa, 0xb, 0xc,
  35. 0xd, 0xe, 0xf, INVALID_CHAR_ID
  36. };
  37. const int cbHexCharMap = ARRAY_ELEMENTS(rgbHexCharMap);
  38. //
  39. // HexStringToQWordA()
  40. //
  41. // Converts a hex ANSI string (without 0x or 0X prefix) to a ULARGE_INTEGER
  42. //
  43. // NOTE: The a-f characters can be lowercase or uppercase
  44. //
  45. // Returns TRUE if successful (the string contained all valid characters)
  46. // Returns FALSE otherwise
  47. //
  48. BOOL NMINTERNAL HexStringToQWordA(LPCSTR pcszString, ULARGE_INTEGER* pqw)
  49. {
  50. BOOL bRet;
  51. ASSERT(pcszString);
  52. ASSERT(pqw);
  53. pqw->QuadPart = 0ui64;
  54. int cchStr = lstrlenA(pcszString);
  55. if (cchStr <= CCH_HEX_QWORD)
  56. {
  57. bRet = TRUE;
  58. PDWORD pdwCur = (cchStr < CCH_HEX_DWORD) ? &(pqw->LowPart) : &(pqw->HighPart);
  59. for (int i = 0; i < cchStr; i++)
  60. {
  61. // NOTE: DBCS characters are not allowed
  62. ASSERT(! IsDBCSLeadByte(pcszString[i]));
  63. if (CCH_HEX_DWORD == (cchStr - i))
  64. {
  65. pdwCur = &(pqw->LowPart);
  66. }
  67. DWORD dwDigit = (DWORD) INVALID_CHAR_ID;
  68. int iDigit = pcszString[i] - '0';
  69. if (iDigit >= 0 && iDigit < cbHexCharMap)
  70. {
  71. dwDigit = (DWORD) rgbHexCharMap[iDigit];
  72. }
  73. if (INVALID_CHAR_ID != dwDigit)
  74. {
  75. *pdwCur = ((*pdwCur) << BITS_PER_HEX_CHAR) + dwDigit;
  76. }
  77. else
  78. {
  79. bRet = FALSE;
  80. break;
  81. }
  82. }
  83. }
  84. else
  85. {
  86. bRet = FALSE;
  87. }
  88. return bRet;
  89. }
  90. /* D W F R O M H E X */
  91. /*-------------------------------------------------------------------------
  92. %%Function: DwFromHex
  93. Return the DWORD from the hex string.
  94. -------------------------------------------------------------------------*/
  95. DWORD DwFromHex(LPCTSTR pchHex)
  96. {
  97. TCHAR ch;
  98. DWORD dw = 0;
  99. while (_T('\0') != (ch = *pchHex++))
  100. {
  101. DWORD dwDigit = (DWORD) INVALID_CHAR_ID;
  102. int iDigit = ch - _T('0');
  103. if (iDigit >= 0 && iDigit < cbHexCharMap)
  104. {
  105. dwDigit = (DWORD) rgbHexCharMap[iDigit];
  106. }
  107. if (INVALID_CHAR_ID != dwDigit)
  108. {
  109. dw = (dw << 4) + dwDigit;
  110. }
  111. else
  112. break;
  113. }
  114. return dw;
  115. }