📄 smsenc.cpp
字号:
// Set address type, top bit is always set
bTypeOfAddress = 0x80 | (g_rgbAddrTypes[raAddress.dwType] << 4);
// Set numplan type, if necessary
if (RIL_ADDRTYPE_UNKNOWN == raAddress.dwType ||
RIL_ADDRTYPE_INTERNATIONAL == raAddress.dwType ||
RIL_ADDRTYPE_NATIONAL == raAddress.dwType) {
if (!(raAddress.dwParams & RIL_PARAM_A_NUMPLAN) ||
NUM_NUMPLANS <= raAddress.dwNumPlan) {
hr = E_INVALIDARG;
goto Error;
}
bTypeOfAddress |= g_rgbNumPlans[raAddress.dwNumPlan];
}
// Copy the address, removing all unwanted characters (Ex: '(', '-', '.')
// Note that '+' is automatically removed from INTERNATIONAL addresses
wszRILAddressWalk = wszRILAddress;
C_ASSERT(ARRAY_LENGTH(raAddress.wszAddress) < ARRAY_LENGTH(wszRILAddress));
for(j = 0 ; j < ARRAY_LENGTH(raAddress.wszAddress) ; j++) {
if(strchr("1234567890*#ABCD", raAddress.wszAddress[j])) {
*wszRILAddressWalk++ = raAddress.wszAddress[j];
} else if(L'\0' == raAddress.wszAddress[j]) {
break; // Done
}
}
*wszRILAddressWalk = L'\0';
// Note: Untested for ALPHANUM addresses
cchAddressLen = wcslen(wszRILAddress);
if (fBeforePDU) {
*pbWalk++ = ((cchAddressLen + 1)/ 2) + 1;
} else {
*pbWalk++ = cchAddressLen;
}
*pbWalk++ = bTypeOfAddress;
cbOut -= 2;
if (RIL_ADDRTYPE_ALPHANUM == raAddress.dwType) {
hr = RILAddressToString(raAddress, szAddress, MAXLENGTH_ADDRESS + 1, bTypeOfAddress);
if (FAILED(hr)) {
goto Error;
}
DEBUGCHK(strlen(szAddress) <= MAXLENGTH_ADDRESS);
if ( cbOut < strlen(szAddress) ) {
hr = E_INVALIDARG;
ASSERT( FALSE );
goto Error;
}
memcpy(pbWalk, szAddress, strlen(szAddress));
} else {
wszBuffer[1] = L'\0'; // Not changed below
if ( cbOut < (size_t)((cchAddressLen + 1) / 2) ) {
hr = E_INVALIDARG;
ASSERT( FALSE );
goto Error;
}
for (j = 0; j < cchAddressLen; j += 2) {
wszBuffer[0] = wszRILAddress[j];
nTemp = _wtoi(wszBuffer);
*pbWalk = nTemp;
if (j + 1 < cchAddressLen) {
wszBuffer[0] = wszRILAddress[j + 1];
nTemp = _wtoi(wszBuffer);
*pbWalk++ |= nTemp << 4;
} else {
*pbWalk++ |= 0xf0;
}
}
}
rcbUsed = pbWalk - pbOut;
Error:
return hr;
}
//
// Encode the ProtocolID for an outgoing message
// see GSM 03.40 section 9.2.3.9
//
static HRESULT EncodeMsgProtocolID(const DWORD dwProtocolID, __out_bcount( cbOut ) BYTE* const pbOut, const size_t cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgProtocolID);
DEBUGCHK(NULL != pbOut && cbOut);
HRESULT hr = S_OK;
rcbUsed = 0;
if ( !pbOut || !cbOut || dwProtocolID >= NUM_PROTOCOLIDS) {
hr = E_INVALIDARG;
goto Error;
}
if (dwProtocolID == RIL_MSGPROTOCOL_SMETOSME) {
*pbOut = 0x00;
} else {
DEBUGCHK(0x100 > g_rgdwProtocolIDs[dwProtocolID]);
*pbOut = (BYTE)g_rgdwProtocolIDs[dwProtocolID];
}
rcbUsed = 1;
Error:
return hr;
}
//
// calculate the total length of the user data in an outgoing message
// if fGSMDefault is trure, then the length is measured in septets, otherwise in octets
//
static HRESULT EncodeEncDataLength(const DWORD cchMsgLength, const DWORD cbHdrLength, const DWORD dwAlphabet, __out_bcount( cbOut ) BYTE* const pbOut,
const size_t cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeEncDataLength);
HRESULT hr = S_OK;
UINT cchUserData;
rcbUsed = 0;
if ( !pbOut || !cbOut ) {
hr = E_INVALIDARG;
ASSERT( FALSE );
goto error_label;
}
if (!cchMsgLength && !cbHdrLength) {
// Neither header nor body are specified
cchUserData = 0;
} else {
if (RIL_DCSALPHABET_UCS2 == dwAlphabet) {
// Account for the fact that every UCS2 char takes up 2 bytes
cchUserData = cchMsgLength * 2;
} else {
cchUserData = cchMsgLength;
}
if (cbHdrLength) {
// Add the size of the header, and a byte for the header-length indicator, plus any fill-bits
// (for GSM default alpabet)
if (RIL_DCSALPHABET_DEFAULT == dwAlphabet) {
cchUserData += (DIVIDE_ROUNDING_UP((1 + cbHdrLength) * 8, 7));
} else {
cchUserData += (1 + cbHdrLength);
}
}
}
*pbOut = cchUserData;
rcbUsed = 1;
error_label:
return hr;
}
//
// Fill out a BYTE array for the header of an outgoing message
//
static HRESULT EncodeMsgHdr(const BYTE* const pbIn, const int cbHdrLength, const DWORD dwAlphabet, __out_bcount( cbOut ) BYTE* const pbOut, size_t cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgHdr);
HRESULT hr = S_OK;
BYTE* pbWalk = pbOut;
rcbUsed = 0;
if ( !pbIn || !pbOut || cbHdrLength < 0 || !cbOut ) {
hr = E_INVALIDARG;
ASSERT( FALSE );
goto error_label;
}
if (cbHdrLength) {
*pbWalk++ = cbHdrLength;
--cbOut;
if ( cbOut < (size_t)min(cbHdrLength, MAXLENGTH_ADDRESS) ) {
hr = E_INVALIDARG;
ASSERT( FALSE );
goto error_label;
}
memcpy(pbWalk, pbIn, min(cbHdrLength, MAXLENGTH_ADDRESS));
pbWalk += cbHdrLength;
}
rcbUsed = pbWalk - pbOut;
error_label:
return hr;
}
//
//
//
static HRESULT EncodeMsgDlvStatus(const DWORD dwStatus, __out_bcount( cbOut ) BYTE* const pbOut, const UINT cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgDlvStatus);
DEBUGCHK(NULL != pbOut && cbOut);
HRESULT hr = S_OK;
rcbUsed = 0;
if ( NUM_DLVSTATUS <= dwStatus || !pbOut || !cbOut ) {
hr = E_INVALIDARG;
goto Error;
}
*pbOut = (BYTE) g_rgdwDlvStatus[dwStatus];
rcbUsed = 1;
Error:
return hr;
}
void ShiftPackedBufferNBitsLeft( __out_bcount( cBufferBytes ) BYTE *pbyBuffer, DWORD cBufferBytes, DWORD cShiftRightBits )
{
if (0 != cBufferBytes)
{
BYTE *pbyCurrentByte = pbyBuffer + cBufferBytes - 1;
while (pbyCurrentByte > pbyBuffer )
{
*pbyCurrentByte-- = ((*pbyCurrentByte << cShiftRightBits) |
(*(pbyCurrentByte - 1) >> (8 - cShiftRightBits)));
}
*pbyCurrentByte = (*pbyCurrentByte << cShiftRightBits);
}
}
//
//
//
static HRESULT EncodeMsgHeaderAndBody(const DWORD dwParams, const DWORD dwFlags, const DWORD cchMsgLength, const DWORD cbHdrLength,
const BYTE* const pbHdr, const BYTE* const pbMsg, const RILMSGDCS* const prmdDataCoding,
__out_bcount( cbOut ) BYTE* const pbOut, size_t cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgHeaderAndBody);
HRESULT hr = S_OK;
BYTE* pbWalk = pbOut;
DWORD dwAlphabet;
UINT cbMsgBytes;
UINT cbAdvancedBy;
DWORD dwBitsToShift = 0;
rcbUsed = 0;
if ( !pbOut || !cbOut ) {
hr = E_INVALIDARG;
ASSERT( FALSE );
goto error_label;
}
if (!(dwFlags & RIL_MSGFLAG_HEADER) && !cchMsgLength) {
// There is no header or data for this message, so set the data length to zero,
// and skip the rest of the function
*pbWalk++ = 0;
--cbOut;
} else {
if (prmdDataCoding && (prmdDataCoding->dwParams & RIL_PARAM_MDCS_ALPHABET)) {
dwAlphabet = prmdDataCoding->dwAlphabet;
} else {
// Default to 8-bit alphabet
dwAlphabet = RIL_DCSALPHABET_8BIT;
}
// Calculate the length of the user data in the message
hr = EncodeEncDataLength(cchMsgLength, (dwFlags & RIL_MSGFLAG_HEADER) ? cbHdrLength : 0, dwAlphabet, pbWalk, cbOut, cbAdvancedBy);
if ( FAILED( hr ) || cbOut < cbAdvancedBy ) {
goto error_label;
}
pbWalk += cbAdvancedBy;
cbOut -= cbAdvancedBy;
// Set the header, if it exists
if ((dwParams & RIL_PARAM_M_HDRLENGTH) && (dwParams & RIL_PARAM_M_HDR)) {
// Encode message header
hr = EncodeMsgHdr(pbHdr, cbHdrLength, dwAlphabet, pbWalk, cbOut, cbAdvancedBy);
if ( FAILED( hr ) || cbOut < cbAdvancedBy ) {
goto error_label;
}
pbWalk += cbAdvancedBy;
cbOut -= cbAdvancedBy;
if (RIL_DCSALPHABET_DEFAULT == dwAlphabet) {
dwBitsToShift = 7-((cbAdvancedBy * 8) % 7);
if (dwBitsToShift == 7) dwBitsToShift = 0;
}
}
// Set the message data
if (cchMsgLength) {
// Figure out the number of bytes the body would occupy
if (RIL_DCSALPHABET_DEFAULT == dwAlphabet) {
cbMsgBytes = (cchMsgLength * 7 + 7) / 8;
} else if (RIL_DCSALPHABET_UCS2 == dwAlphabet) {
cbMsgBytes = cchMsgLength * 2;
} else {
cbMsgBytes = cchMsgLength;
}
cbAdvancedBy = min(cbMsgBytes, MAXLENGTH_MSG);
if ( cbOut < cbAdvancedBy ) {
ASSERT( FALSE );
goto error_label;
}
memcpy(pbWalk, pbMsg, cbAdvancedBy);
cbOut -= cbAdvancedBy;
// make sure any GSM characters start on the septet boundry, not on the byte boundry.
if (dwBitsToShift) {
if (((cchMsgLength * 7 + 7 + dwBitsToShift) / 8) > cbMsgBytes)
{
ASSERT(cbAdvancedBy < MAXLENGTH_MSG);
if(cbAdvancedBy < MAXLENGTH_MSG)
{
// our shift will overflow into the next byte
if ( !cbOut )
{
ASSERT( FALSE );
goto error_label;
}
pbWalk[cbAdvancedBy++] = 0;
--cbOut;
}
}
ShiftPackedBufferNBitsLeft(pbWalk, cbAdvancedBy, dwBitsToShift);
}
pbWalk += cbAdvancedBy;
}
else
{
// If there is no message body then we may need to walk one more byte to make it to snag
// the next septet boundry.
if (dwBitsToShift)
{
pbWalk++;
}
}
}
rcbUsed = pbWalk - pbOut;
error_label:
return hr;
}
//
// Fill out a BYTE array for a Submit message
//
static HRESULT EncodeSubmitMsg(const RILMESSAGE& rmMsg, __out_bcount( cbOut ) BYTE* const pbOut, const UINT cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeSubmitMsg);
BYTE* pbWalk = pbOut;
const BYTE* pbEnd = pbOut + cbOut;
UINT cbAdvancedBy;
HRESULT hr = S_OK;
rcbUsed = 0;
if ( !pbOut || !cbOut ) {
hr = E_INVALIDARG;
ASSERT( FALSE );
goto Error;
}
(void)memset(pbOut, 0, cbOut);
// These parameters are mandatory, and if not present, we error out
if (!(rmMsg.dwParams & RIL_PARAM_M_TYPE) || !(rmMsg.dwParams & RIL_PARAM_M_DESTADDRESS) ||
!(rmMsg.dwParams & RIL_PARAM_M_PROTOCOLID) || !(rmMsg.dwParams & RIL_PARAM_M_MSGLENGTH) ||
!(rmMsg.dwParams & RIL_PARAM_M_FLAGS) || !(rmMsg.dwParams & RIL_PARAM_M_VPFORMAT) ||
!(rmMsg.dwParams & RIL_PARAM_M_DATACODING)) {
hr = E_INVALIDARG;
goto Error;
}
// Set Type, per GSM 03.40 section 9.2.3.1
*pbWalk |= 0x01;
// RIL_MSGFLAGS_REJECTDUPS, GSM 03.40 section 9.2.3.25
if (rmMsg.dwFlags & RIL_MSGFLAG_REJECTDUPS) {
*pbWalk |= 0x04;
}
// Validity Period Format, GSM 03.40 section 9.2.3.3
switch (rmMsg.msgOutSubmit.dwVPFormat)
{
case RIL_MSGVP_NONE:
*pbWalk |= 0x00;
break;
case RIL_MSGVP_ENHANCED:
//*pbWalk |= 0x08;
ASSERT(FALSE); // not supported, treat SYSTEMTIME as relative
__fallthrough;
case RIL_MSGVP_RELATIVE:
*pbWalk |= 0x10;
break;
case RIL_MSGVP_ABSOLUTE:
*pbWalk |= 0x18;
break;
default:
hr = E_INVALIDARG;
goto Error;
}
// RIL_MSGFLAG_STATUSREPORTREQUESTED, GSM 03.40 section 9.2.3.5
if (rmMsg.dwFlags & RIL_MSGFLAG_STATUSREPORTREQUESTED) {
*pbWalk |= 0x20;
}
// RIL_MSGFLAG_HEADER, GSM 03.40 section 9.2.3.23
if (rmMsg.dwFlags & RIL_MSGFLAG_HEADER) {
*pbWalk |= 0x40;
}
// RIL_MSGFLAG_REPLYPATH, GSM 03.40 section 9.2.3.17
if (rmMsg.dwFlags & RIL_MSGFLAG_REPLYPATH) {
*pbWalk |= 0x80;
}
pbWalk++;
DEBUGCHK(pbWalk <= pbEnd);
// RIL_PARAM_M_MSGREFERENCE, GSM 03.40 section 9.2.3.6
// NOTE: it appears that we can put anything into this field -- the radio generates correct msg reference for us
pbWalk++;
DEBUGCHK(pbWalk <= pbEnd);
// Encode the destination address. pbWalk should be set properly by the function
hr = EncodeMsgAddress(rmMsg.msgOutSubmit.raDestAddress, FALSE, pbWalk, pbEnd > pbWalk ? pbEnd - pbWalk : 0, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
// Set ProtocolID, see GSM 03.40 section 9.2.3.9
hr = EncodeMsgProtocolID(rmMsg.msgOutSubmit.dwProtocolID, pbWalk, pbEnd > pbWalk ? pbEnd - pbWalk : 0, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
// Reconstruct DCS, see GSM 03.40 section 9.2.3.10
hr = EncodeMsgDCS(rmMsg.msgOutSubmit.rmdDataCoding, pbWalk, pbEnd > pbWalk ? pbEnd - pbWalk : 0, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
if (rmMsg.dwParams & RIL_PARAM_M_VP) {
DEBUGCHK(0 != (rmMsg.dwParams & RIL_PARAM_M_VPFORMAT));
// See GSM 03.40 section 9.2.3.12
hr = EncodeMsgValidityPeriod(rmMsg.msgOutSubmit.stVP, rmMsg.msgOutSubmit.dwVPFormat, pbWalk,
pbEnd > pbWalk ? pbEnd - pbWalk : 0, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
}
// Encode header and body
hr = EncodeMsgHeaderAndBody(rmMsg.dwParams, rmMsg.dwFlags, rmMsg.msgOutSubmit.cchMsgLength,
rmMsg.msgOutSubmit.cbHdrLength, rmMsg.msgOutSubmit.rgbHdr, rmMsg.msgOutSubmit.rgbMsg,
&rmMsg.msgOutSubmit.rmdDataCoding, pbWalk, pbEnd > pbWalk ? pbEnd - pbWalk : 0, cbAdvancedBy);
if ( FAILED( hr ) ) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
rcbUsed = pbWalk - pbOut;
Error:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -