Cisco TSP - Tool migration from 32bit to 64bit in C#

3

Currently I have the problem that I should migrate a tool which communicates via Cisco TAPI. Currently it is running under a 32bit compilation.

If I switch the compilation set to 64bit and update the nuget package "ATAPI" (by Mark Smith <2>) to the 64bit version.

If I build this and test it, the TAPI logs writes there is a dwSize mismatch. I tried to set an explicity StructLayout for the CiscoDevSpecific-structs (like suggested here <1>) . But the same error appears in the log file.

error message

15:44:51.105 |   TSPI_lineGetAddressStatus() TSPI_lineGetAddressStatus returns = 0x00000000
15:44:51.106 |   TSPI_lineDevSpecific() 
        dwRequestID: 0x000105AF  hdLine: 0x175B4B30  dwAddressID: 0x00000000  hdCall: 0x00000000  lpParams: 0x202D6E98  dwSize: 32
15:44:51.106 |   CSelsiusTSPLine::DevSpecific() [0x00000D32] *ERROR* dwSize mis-match 0x00000020
15:44:51.106 |   TSPI_lineDevSpecific() TSPI_lineDevSpecific returns = 0x80000048

eg The struct for a StartCallMonitotoring looks like

    [StructLayout(LayoutKind.Explicit, Size = 32)]
    public struct CiscoLineDevSpecificStartCallMonitoring
    {
        [FieldOffset(0)]
        public int m_MsgType;
        [FieldOffset(8)]
        public int m_PermanentLineID;
        [FieldOffset(16)]
        public int m_MonitorMode; //0= NONE, 1=SILENT, 2=WHISPER, 3=ACTIVE
        [FieldOffset(24)]
        public int m_ToneDirection; //0=LOCALONLY, 1=REMOTEONLY, 2=BOTH, 3=NOTLOCALORREMOTE
    }

The initiliziation like

var cisco = new CiscoLineDevSpecificStartCallMonitoring
{
    m_MsgType = (int)CiscoLineDevSpecificType.SLDST_START_CALL_MONITORING,
    m_PermanentLineID = permanentIdOfTargetLine,
    m_MonitorMode = (int)monitorMode,
    m_ToneDirection = (int)PlayToneDirection.PlayToneDirectionNoLocalOrRemote
};

And the calculation of the Bytes looks like:

private static byte[] GetBytes(object msg)
{
    var size = Marshal.SizeOf(msg);
    var arr = new byte[size];
    var ptr = Marshal.AllocHGlobal(size);

    Marshal.StructureToPtr(msg, ptr, true);
    Marshal.Copy(ptr, arr, 0, size);
    Marshal.FreeHGlobal(ptr);

    return arr;
}

Thank you for your responds.

<1> https://community.cisco.com/t5/collaboration-documents/tsp-x64-devspecific-dword-size-mismatch-problem/ta-p/3613828 <2> https://github.com/markjulmar/atapi.net

c#
cisco
tapi
asked on Stack Overflow Aug 6, 2020 by Pit Braunsdorf • edited Aug 6, 2020 by Pit Braunsdorf

1 Answer

1

I am experiencing same issue. I didn't fully resolve it but I think I can provide some info to help. I know this is not a complete solutions but no one has responded in 7 months.

The first point is the structure we have to marshal. I couldn't decompile cisco classes (don't have access to them) but if you have a look at cisco dev guide:

class CCiscoLineDevSpecific
{
    public:CCicsoLineDevSpecific(DWORDmsgType);
    virtual~CCiscoLineDevSpecific();
    DWORD GetMsgType(void) const {return m_MsgType;}
    void* lpParams() { 
        return &m_MsgType;
    }
    virtual DWORDdwSize()= 0;
    private: DWORDm_MsgType;
};

//and the class we are using is:

    class CCiscoLineDevSpecificStartCallMonitoring: public CCiscoLineDevSpecific
{
public:
    CCiscoLineDevSpecificStartCallMonitoring () : 
      CCiscoLineDevSpecific(SLDST_START_CALL_MONITORING) {}
    virtual ~    CCiscoLineDevSpecificStartCallMonitoring () {}
    DWORD m_PermanentLineID ; 
    DWORD m_MonitorMode;
    DWORD m_ToneDirection; 
   // subtract out the virtual function table pointer
    virtual DWORD dwSize(void) const {return sizeof(*this)-4;} 
} ;

So inheritance is involved then some bytes for padding/aligment are expected.

The second point is that DWORD is not 8 bytes size but 4 bytes even in x64 OS.

With that in mind my proposal por the struct shoud be something like this :

[StructLayout(LayoutKind.Explicit, Size = 24)]
public struct CCiscoLineDevSpecificStartCallMonitoring_64
    {
        [FieldOffset(0)]
        public uint msgType;
        [FieldOffset(4)]
        public uint padding;
        [FieldOffset(8)]
        public uint m_PermanentLineID;
        [FieldOffset(12)]
        public uint m_MonitorMode;
        [FieldOffset(16)]
        public uint m_ToneDirection;
        [FieldOffset(20)]
        public uint m_padding;

        public byte[] ToBytes()
        {
            Byte[] bytes = new Byte[Marshal.SizeOf(typeof(CCiscoLineDevSpecificStartCallMonitoring_64))];
            GCHandle pinStructure = GCHandle.Alloc(this, GCHandleType.Pinned);
            try
            {
                Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
                return bytes;
            }
            finally
            {
                pinStructure.Free();
            }
        }
    }

With this structure I can get:

20:50:31.480 |   LineCallStartMonitoringRequest::Trace 
        dwCallingAddressOffset =0x00000058
        dwCallingAddressSize =4
        CallingAddress =870
        dwDestAddressOffset =0x0000005C
        dwDestAddressSize =4
        DestAddress =984
        dwDeviceNameOffset =0x00000060
        dwDeviceNameSize =10
        DeviceName =CSFCAT984
        dwCallID =0x023B4DA2
        dwTone=3
        dwMonitorMode =1 

I am not a C++ developer, but i've prepared a small C++ program to inspect the elements offset of the derived class and found these paddings. I don't know where they came from.

As I mentioned it is still not working in my infra. After this I recieve:

20:50:31.497 |-->CSelsiusTSPLine::MapCtiToTspErrorCode(), CTI error code - 0x8CCC009D 
20:50:31.497 |   CSelsiusTSPLine::MapCtiToTspErrorCode(), CTI error code - 0x8CCC009D lResult = 0x80000049
20:50:31.497 |<--CSelsiusTSPLine::MapCtiToTspErrorCode(), CTI error code - 0x8CCC009D 

But may be this is because of configuration issues. Any case I wanted to provide this point of view so we can reach a complete solution soon.

answered on Stack Overflow Mar 25, 2021 by j.outon • edited Mar 26, 2021 by j.outon

User contributions licensed under CC BY-SA 3.0