📄 util.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
util.cpp
Abstract:
Notes:
--*/
#include "precomp.h"
#ifdef assert
#undef assert
#endif
#include <Safeint.hxx>
#ifdef RIL_RADIO_RESILIENCE
#include <wincrypt.h>
#endif // RIL_RADIO_RESILIENCE
#ifndef _PREFAST_
#pragma warning( disable: 4068 )
#endif
//
// Table used to convert from GSM default alphabet to Unicode
//
static const WCHAR g_rgwchGSMToUnicode[128] =
{
L'@', 0x00a3, L'$', 0x00a5, 0x00e8, 0x00e9, 0x00f9, 0x00ec, // 0x00 - 0x07
0x00f2, 0x00c7, L'\n', 0x00d8, 0x00f8, L'\r', 0x00c5, 0x00e5, // 0x08 - 0x0f
0x0394, L'_', 0x03a6, 0x0393, 0x039b, 0x03a9, 0x03a0, 0x03a8, // 0x10 - 0x17
0x03a3, 0x0398, 0x039e, L' ', 0x00c6, 0x00e6, 0x00df, 0x00c9, // 0x18 - 0x1f
L' ', L'!', L'"', L'#', 0x00a4, L'%', L'&', L'\'', // 0x20 - 0x27
L'(', L')', L'*', L'+', L',', L'-', L'.', L'/', // 0x28 - 0x2f
L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', // 0x30 - 0x37
L'8', L'9', L':', L';', L'<', L'=', L'>', L'?', // 0x38 - 0x3f
0x00a1, L'A', L'B', L'C', L'D', L'E', L'F', L'G', // 0x40 - 0x47
L'H', L'I', L'J', L'K', L'L', L'M', L'N', L'O', // 0x48 - 0x4f
L'P', L'Q', L'R', L'S', L'T', L'U', L'V', L'W', // 0x50 - 0x57
L'X', L'Y', L'Z', 0x00c4, 0x00d6, 0x00d1, 0x00dc, 0x00a7, // 0x58 - 0x5f
0x00bf, L'a', L'b', L'c', L'd', L'e', L'f', L'g', // 0x60 - 0x67
L'h', L'i', L'j', L'k', L'l', L'm', L'n', L'o', // 0x68 - 0x6f
L'p', L'q', L'r', L's', L't', L'u', L'v', L'w', // 0x70 - 0x77
L'x', L'y', L'z', 0x00e4, 0x00f6, 0x00f1, 0x00fc, 0x00e0, // 0x78 - 0x7f
};
//
// Table used to convert from Unicode to GSM default alphabet
//
static const CHARMAP g_rgcmUnicodeToGSMExceptions[] =
{
{ 0x02, L'$'}, { 0x00, L'@'}, { 0x11, L'_'}, { 0x40, 0x00a1},
{ 0x01, 0x00a3}, { 0x24, 0x00a4}, { 0x03, 0x00a5}, { 0x5f, 0x00a7},
{ 0x60, 0x00bf}, { 0x41, 0x00c0}, { 0x41, 0x00c1}, { 0x41, 0x00c2},
{ 0x41, 0x00c3}, { 0x5b, 0x00c4}, { 0x0e, 0x00c5}, { 0x1c, 0x00c6},
{ 0x09, 0x00c7}, { 0x45, 0x00c8}, { 0x1f, 0x00c9}, { 0x45, 0x00ca},
{ 0x45, 0x00cb}, { 0x49, 0x00cc}, { 0x49, 0x00cd}, { 0x49, 0x00ce},
{ 0x49, 0x00cf}, { 0x5d, 0x00d1}, { 0x4f, 0x00d2}, { 0x4f, 0x00d3},
{ 0x4f, 0x00d4}, { 0x4f, 0x00d5}, { 0x5c, 0x00d6}, { 0x0b, 0x00d8},
{ 0x55, 0x00d9}, { 0x55, 0x00da}, { 0x55, 0x00db}, { 0x5e, 0x00dc},
{ 0x59, 0x00dd}, { 0x1e, 0x00df}, { 0x7f, 0x00e0}, { 0x61, 0x00e1},
{ 0x61, 0x00e2}, { 0x61, 0x00e3}, { 0x7b, 0x00e4}, { 0x0f, 0x00e5},
{ 0x1d, 0x00e6}, { 0x09, 0x00e7}, { 0x04, 0x00e8}, { 0x05, 0x00e9},
{ 0x65, 0x00ea}, { 0x65, 0x00eb}, { 0x07, 0x00ec}, { 0x69, 0x00ed},
{ 0x69, 0x00ee}, { 0x69, 0x00ef}, { 0x7d, 0x00f1}, { 0x08, 0x00f2},
{ 0x6f, 0x00f3}, { 0x6f, 0x00f4}, { 0x6f, 0x00f5}, { 0x7c, 0x00f6},
{ 0x0c, 0x00f8}, { 0x06, 0x00f9}, { 0x75, 0x00fa}, { 0x75, 0x00fb},
{ 0x7e, 0x00fc}, { 0x79, 0x00fd}, { 0x79, 0x00ff}, { 0x13, 0x0393},
{ 0x10, 0x0394}, { 0x19, 0x0398}, { 0x14, 0x039b}, { 0x1a, 0x039e},
{ 0x16, 0x03a0}, { 0x18, 0x03a3}, { 0x12, 0x03a6}, { 0x17, 0x03a8},
{ 0x15, 0x03a9},
};
#define NUM_EXCEPTIONS (sizeof(g_rgcmUnicodeToGSMExceptions) / sizeof(CHARMAP))
//
// Table used to map semi-byte values to hex characters
//
static const char g_rgchSemiByteToCharMap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
//
// Convert a semi-byte into its character representation
//
char SemiByteToChar(const BYTE bByte, const BOOL fHigh)
{
BYTE bSemiByte = (fHigh ? (bByte & 0xf0) >> 4 : bByte & 0x0f);
DEBUGCHK(0x10 > bSemiByte);
return g_rgchSemiByteToCharMap[bSemiByte];
}
//
// Combine 2 characters representing semi-bytes into a byte
//
BYTE SemiByteCharsToByte(const char chHigh, const char chLow)
{
BYTE bRet;
if ('0' <= chHigh && '9' >= chHigh)
{
bRet = (chHigh - '0') << 4;
}
else
{
bRet = (0x0a + chHigh - 'A') << 4;
}
if ('0' <= chLow && '9' >= chLow)
{
bRet |= (chLow - '0');
}
else
{
bRet |= (0x0a + chLow - 'A');
}
return bRet;
}
//
// Comparison routine used for binary search below
//
static int _cdecl BSCompareChars(const void* pElem1, const void* pElem2)
{
WCHAR wch1 = ((CHARMAP*)pElem1)->wch;
WCHAR wch2 = ((CHARMAP*)pElem2)->wch;
int iRet;
if (wch1 < wch2)
{
iRet = -1;
}
else if (wch1 == wch2)
{
iRet = 0;
}
else
{
iRet = 1;
}
return iRet;
}
//
// Convert a single Unicode character to GSM default alphabet
//
BOOL UnicodeCharToGSM(const WCHAR wch, char *pchRet)
{
// Does this char map directly to Unicode?
if (0x000a == wch ||
0x000d == wch ||
(0x0020 <= wch && 0x0023 >= wch) ||
(0x0025 <= wch && 0x003f >= wch) ||
(0x0041 <= wch && 0x005a >= wch) ||
(0x0061 <= wch && 0x007a >= wch))
{
*pchRet = (char)(wch & 0x007f);
return TRUE;
}
else
{
CHARMAP cmKey = { '\0', wch};
CHARMAP* pcmFound;
pcmFound = (CHARMAP*)bsearch(&cmKey, g_rgcmUnicodeToGSMExceptions, NUM_EXCEPTIONS, sizeof(CHARMAP), BSCompareChars);
if (pcmFound)
{
*pchRet = pcmFound->ch;
return TRUE;
}
}
return FALSE;
}
BOOL GSMCharToUnicode(const char ch, WCHAR *pwchRet)
{
*pwchRet = g_rgwchGSMToUnicode[ch];
return TRUE;
}
//
//
//
BOOL GSMHexToGSM(const LPCSTR sIn, const UINT cbIn, __out_bcount( cbOut ) const LPSTR sOut, const UINT cbOut, UINT& rcbUsed)
{
LPCSTR pchIn = sIn;
LPCSTR pchInEnd = sIn + cbIn;
LPSTR pchOut = sOut;
LPCSTR pchOutEnd = sOut + cbOut;
BOOL fRet = FALSE;
while (pchIn < pchInEnd - 1 && pchOut < pchOutEnd)
{
*pchOut++ = SemiByteCharsToByte(*pchIn, *(pchIn + 1));
pchIn += 2;
}
rcbUsed = pchOut - sOut;
fRet = TRUE;
return fRet;
}
//
//
//
BOOL GSMToGSMHex(const LPCSTR sIn, const UINT cbIn, __out_bcount( cbOut ) const LPSTR sOut, const UINT cbOut, UINT& rcbUsed)
{
LPCSTR pchIn = sIn;
LPCSTR pchInEnd = sIn + cbIn;
LPSTR pchOut = sOut;
LPCSTR pchOutEnd = sOut + cbOut;
BOOL fRet = FALSE;
while (pchIn < pchInEnd && pchOut < pchOutEnd - 1)
{
*pchOut = g_rgchSemiByteToCharMap[((*pchIn) & 0xf0) >> 4];
pchOut++;
*pchOut = g_rgchSemiByteToCharMap[(*pchIn) & 0x0f];
pchOut++;
pchIn++;
}
rcbUsed = pchOut - sOut;
fRet = TRUE;
return fRet;
}
//
// Convert a specified string from Unicode
//
BOOL ConvertFromUnicode(const ENCODING_TYPE enc, const LPCWSTR wsIn, const UINT cchIn, __out_bcount( cbOut ) const LPSTR sOut, const UINT cbOut,
UINT& rcbUsed)
{
FUNCTION_TRACE(ConvertFromUnicode);
LPCWSTR pwchInEnd;
LPCWSTR pwchIn;
LPCSTR pchOutEnd;
LPSTR pchOut;
LPSTR sOutTemp = NULL;
LPCSTR pchOutTemp;
UINT cbOutUsed;
char ch7Bit;
UINT nBits = 0;
BOOL fRet = FALSE;
rcbUsed = 0;
if (ENCODING_GSMDEFAULT == enc)
{
pwchInEnd = wsIn + cchIn;
pchOutEnd = sOut + cbOut;
pwchIn = wsIn;
pchOut = sOut;
while (pwchIn < pwchInEnd && pchOut < pchOutEnd)
{
if (!nBits)
{
if (!UnicodeCharToGSM(*pwchIn++,pchOut))
{
*pchOut = '?';
}
DEBUGCHK(*pchOut < 0x80);
}
else
{
if (!UnicodeCharToGSM(*pwchIn++,&ch7Bit))
{
ch7Bit = '?';
}
DEBUGCHK(ch7Bit < 0x80);
*pchOut++ += ch7Bit << (8 - nBits);
*pchOut = ch7Bit >> nBits;
}
nBits = (nBits + 1) % 8;
}
if (!nBits && pchOut > sOut)
{
// We incremented the destination pointer once too many
pchOut--;
}
// Do various tricks to distinguish fill bits from real characters (GSM 03.38, ver. 6.0.1, chap. 6.1.2.3.1)
// NOTE: <CR> in GSM default alphabet maps directly to Unicode <CR>
if ( pchOut >= pchOutEnd )
{
ASSERT( FALSE );
goto Error;
}
if (7 == cchIn % 8 && !(*pchOut & 0xfe))
{
// We have 7 fill 0-bits at the end -- need to replace them with <CR>
*pchOut &= 0x01;
*pchOut |= ('\r' << 1);
}
else if (!(cchIn % 8) && pchOut < pchOutEnd - 1 && ('\r' << 1) == *pchOut)
{
// We have no fill bits and the last character in the text is <CR> --
// we need to add another <CR>, so that terminating <CR> isn't confused with fill bits
pchOut++;
*pchOut = '\r' & 0x7f;
}
rcbUsed = pchOut - sOut + 1;
fRet = TRUE;
}
else if (ENCODING_GSMDEFAULT_UNPACKED == enc)
{
DWORD dwCharCount = 0;
while ((dwCharCount < cchIn) && (dwCharCount < cbOut))
{
if (!UnicodeCharToGSM(wsIn[dwCharCount], &(sOut[dwCharCount])))
{
sOut[dwCharCount] = '?';
}
dwCharCount++;
}
rcbUsed = cchIn;
fRet = TRUE;
}
else if ((ENCODING_GSMDEFAULT_HEX == enc) || (ENCODING_GSMDEFAULT_HEX_UNPACKED == enc))
{
ENCODING_TYPE etSubEncoding;
if (ENCODING_GSMDEFAULT_HEX_UNPACKED == enc)
{
etSubEncoding = ENCODING_GSMDEFAULT_UNPACKED;
}
else
{
etSubEncoding = ENCODING_GSMDEFAULT;
}
sOutTemp = new char[cbOut / 2 + 1];
if (!sOutTemp)
{
goto Error;
}
if (!ConvertFromUnicode(etSubEncoding, wsIn, cchIn, sOutTemp, cbOut / 2 + 1, cbOutUsed))
{
goto Error;
}
pchOutTemp = sOutTemp;
pchOut = sOut;
pchOutEnd = sOut + cbOut;
while ((pchOut <= pchOutEnd) && ((cbOutUsed--) > 0))
{
*pchOut++ = SemiByteToChar(*pchOutTemp, TRUE);
*pchOut++ = SemiByteToChar(*pchOutTemp++, FALSE);
}
fRet = TRUE;
rcbUsed = pchOut - sOut;
}
else if (ENCODING_GSMDEFAULT_UNICODE == enc)
{
pwchIn = wsIn;
pwchInEnd = wsIn + cchIn;
pchOut = sOut;
pchOutEnd = sOut + cbOut;
while (pwchIn < pwchInEnd && (pchOut+3) < pchOutEnd)
{
pchOut[0] = g_rgchSemiByteToCharMap[ (int)(( *pwchIn >> 12 ) & 0x0f ) ];
pchOut[1] = g_rgchSemiByteToCharMap[ (int)(( *pwchIn >> 8 ) & 0x0f ) ];
pchOut[2] = g_rgchSemiByteToCharMap[ (int)(( *pwchIn >> 4 ) & 0x0f ) ];
pchOut[3] = g_rgchSemiByteToCharMap[ (int)( *pwchIn & 0x0f ) ];
pwchIn++;
pchOut += 4;
}
rcbUsed = pchOut - sOut;
fRet = TRUE;
}
else if (ENCODING_GSMDEFAULT_UTF8 == enc)
{
pwchIn = wsIn;
pwchInEnd = wsIn + cchIn;
pchOut = sOut;
pchOutEnd = sOut + cbOut;
while (pwchIn < pwchInEnd)
{
WCHAR wch = *pwchIn++;
if (0 == (wch & 0xFF80))
{ // 7 bits
if (pchOut + 1 > pchOutEnd)
goto Error;
*pchOut++ = (char) wch;
}
else if (0 == (wch & 0xF800))
{ // 11 bits
if (pchOut + 2 > pchOutEnd)
goto Error;
*pchOut++ = (char) (0xC0 | ((wch >> 6) & 0x1F));
*pchOut++ = (char) (0x80 | (wch & 0x3F));
}
else
{ // 16 bits
if (pchOut + 3 > pchOutEnd)
goto Error;
*pchOut++ = (char) (0xE0 | ((wch >> 12) & 0x0F));
*pchOut++ = (char) (0x80 | ((wch >> 6) & 0x3F));
*pchOut++ = (char) (0x80 | (wch & 0x3F));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -