⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smsenc.cpp

📁 ril source code for Windows CE
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    // 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 + -