http://www.developer.com/ws/pc/article.php/3503761/Exploring-Extended-TAPI-Functions.htm
There are a lot of TAPI functions that were not touched in previous articles. I obviously don't pretend to cover them all here. Such huge task requires separate book to be described. However, I will try to overview different function groups to give you high level picture of available options. We will start this part of tutorial from regular things. This section describes how to obtain various general information for specified TAPI device. This function groups belong to Extended TAPI. ExTAPI, proving its name, extends wireless API with different options: ExTAPI uses Telephony API (TAPI) functions and available TAPI line devices. There is only one restriction with ExTAPI. All its operations are available only if: What it means for you is that most of ExTAPI functions won't work if your application hasn't requested (and obtained) enough privileges (pay attention to the LINECALLPRIVILEGE_OWNER parameter of ::lineOpen in the very first sample). As you have seen in previous articles, first of all you have to initialize TAPI. Here, I'll put one more example of how to do it. The only difference from previous examples is that this code snipped uses the Event mechanism instead of a callback function to receive further notifications: There are a couple dozen get/set-functions that give you a lot of useful information and allow managing line devices. It doesn't make sense to describe them all here; I'll only put a brief 'get' calls reference. You will find detailed explanations in SDK help: Your application can use some of the above functions to verify radio presence, barring caps and states, system type, and so forth. The following sample code illustrates how to retrieve information about a given line device: The companion project contains more examples of this group of functions; here, I'll drop the simplest one: ExTAPI exposes several functions that you can use to manage network operator-related stuff: If your application requires you to deal with these kinds of operations, these functions will help you to handle it. The tiny sample below queries all available network operators: If you run this sample, you will see that it takes some time to obtain the required information. Except for this, the code is quite common for TAPI: Usually, you will store the original network operator, set up your own, and finally restore the previous settings. ExTAPI serves you just fine here. In this acticle, you have observed Extended TAPI operations. They can or cannot be required in your applications, but anyway it's better to know your enemy before it beats you. You will continue investigating TAPI in next articles, because it is utterly not ended yet. Possible areas of intrest are managing calls, setting up conferences, and so forth. If all goes well, you will learn about these topics in the coming articles. Enjoy! Download the accompanying code's zip file here. Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.
Exploring Extended TAPI Functions
May 10, 2005
Retrieving General Information
Initialization
BOOL CExTapiDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
LINEINITIALIZEEXPARAMS LineExtParams;
LineExtParams.dwTotalSize = sizeof(LineExtParams);
LineExtParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
if (::lineInitializeEx(&m_hLineApp, 0, 0, _T("Developer.com Test"),
&m_dwNumDevs, &m_dwAPIVersion,
&LineExtParams))
{
EndDialog(IDOK);
return FALSE;
}
m_dwTSPILineDeviceID = GetTSPLineDeviceID(CELLTSP_LINENAME_STRING);
if ( m_dwTSPILineDeviceID == (DWORD)-1 )
{
::lineShutdown(m_hLineApp);
EndDialog(IDOK);
return FALSE;
}
// open the line
if( ::lineOpen(m_hLineApp, m_dwTSPILineDeviceID,
&m_hLine, m_dwAPIVersion, 0, 0,
LINECALLPRIVILEGE_OWNER,
LINEMEDIAMODE_DATAMODEM, 0) )
{
::lineShutdown(m_hLineApp);
EndDialog(IDOK);
return FALSE;
}
// set up ExTAPI
if ( ::lineNegotiateExtVersion(m_hLineApp, m_dwTSPILineDeviceID,
m_dwAPIVersion, EXT_API_LOW_VERSION,
EXT_API_HIGH_VERSION,
&m_dwExtVersion) )
{
::lineClose(m_hLine);
::lineShutdown(m_hLineApp);
EndDialog(IDOK);
return FALSE;
}
}
DWORD CExTapiDlg::GetTSPLineDeviceID(const TCHAR*
const psTSPLineName)
{
DWORD dwReturn = -1;
for(DWORD dwCurrentDevID = 0 ; dwCurrentDevID < m_dwNumDevs ;
dwCurrentDevID++)
{
LINEEXTENSIONID LineExtensionID;
if( ::lineNegotiateAPIVersion(m_hLineApp, dwCurrentDevID,
TAPI_API_LOW_VERSION,
TAPI_CURRENT_VERSION,
&m_dwAPIVersion,
&LineExtensionID) == 0 )
{
LINEDEVCAPS LineDevCaps;
LineDevCaps.dwTotalSize = sizeof(LineDevCaps);
if( ::lineGetDevCaps(m_hLineApp, dwCurrentDevID,
m_dwAPIVersion, 0, &LineDevCaps) == 0 )
{
BYTE* pLineDevCapsBytes = new BYTE[LineDevCaps.dwNeededSize];
if(0 != pLineDevCapsBytes)
{
LINEDEVCAPS* pLineDevCaps =
(LINEDEVCAPS*)pLineDevCapsBytes;
pLineDevCaps->dwTotalSize = LineDevCaps.dwNeededSize;
if( ::lineGetDevCaps(m_hLineApp, dwCurrentDevID,
m_dwAPIVersion, 0,
pLineDevCaps) == 0 )
{
if( _tcscmp((TCHAR*)
((BYTE*)pLineDevCaps+pLineDevCaps->
dwLineNameOffset), psTSPLineName) == 0 )
{
dwReturn = dwCurrentDevID;
}
}
delete[] pLineDevCapsBytes;
}
}
}
}
return dwReturn;
}
'Get/Set' functions
void CExTapiDlg::OnGetGeneralInfo()
{
LPBYTE pLineGeneralInfoBytes = NULL;
const DWORD dwMediaMode = LINEMEDIAMODE_DATAMODEM;
LINEGENERALINFO lviGeneralInfo;
LPLINEGENERALINFO plviGeneralInfo;
LPTSTR tsManufacturer, tsModel, tsRevision, tsSerialNumber,
tsSubscriberNumber;
CString sInfo;
lviGeneralInfo.dwTotalSize = sizeof(lviGeneralInfo);
LONG lRes = ::lineGetGeneralInfo(m_hLine, &lviGeneralInfo);
if (lRes != 0 && lRes != LINEERR_STRUCTURETOOSMALL)
{
TCHAR szMsg[255];
GetTAPIErrorMsg(szMsg,sizeof(szMsg), lRes);
AfxMessageBox(szMsg);
return;
}
pLineGeneralInfoBytes = new BYTE[lviGeneralInfo.dwNeededSize];
plviGeneralInfo = (LPLINEGENERALINFO)pLineGeneralInfoBytes;
if(pLineGeneralInfoBytes != NULL)
{
plviGeneralInfo->dwTotalSize = lviGeneralInfo.dwNeededSize;
if ( (lRes = ::lineGetGeneralInfo(m_hLine, plviGeneralInfo)) != 0 )
{
TCHAR szMsg[255];
GetTAPIErrorMsg(szMsg,sizeof(szMsg), lRes);
AfxMessageBox(szMsg);
}
else
{
TCHAR szUnavailable[] = L"Unavailable";
if(plviGeneralInfo->dwManufacturerSize)
{
tsManufacturer = (WCHAR*)(((BYTE*)plviGeneralInfo)
+plviGeneralInfo->dwManufacturerOffset);
}
else
{
tsManufacturer = szUnavailable;
}
if(plviGeneralInfo->dwModelSize)
{
tsModel = (WCHAR*)(((BYTE*)plviGeneralInfo)
+plviGeneralInfo->dwModelOffset);
}
else
{
tsModel = szUnavailable;
}
if(plviGeneralInfo->dwRevisionSize)
{
tsRevision = (WCHAR*)(((BYTE*)plviGeneralInfo)
+plviGeneralInfo->dwRevisionOffset);
}
else
{
tsRevision = szUnavailable;
}
if(plviGeneralInfo->dwSerialNumberSize)
{
tsSerialNumber = (WCHAR*)(((BYTE*)plviGeneralInfo)
+plviGeneralInfo->dwSerialNumberOffset);
}
else
{
tsSerialNumber = szUnavailable;
}
if(plviGeneralInfo->dwSubscriberNumberSize)
{
tsSubscriberNumber = (WCHAR*)(((BYTE*)plviGeneralInfo)
+plviGeneralInfo->dwSubscriberNumberOffset);
}
else
{
tsSubscriberNumber = szUnavailable;
}
sInfo.Format(L"Manufacturer: %s\nModel: %s\nRevision:
%s\nSerial No: %s\nSubscriber No: %s\n",
tsManufacturer,
tsModel,
tsRevision,
tsSerialNumber,
tsSubscriberNumber);
AfxMessageBox(sInfo);
}
}
delete [] pLineGeneralInfoBytes;
}
void CExTapiDlg::OnGetEquipmentState()
{
TCHAR *szEqStates[] =
{
L"LINEEQUIPSTATE_MINIMUM",
L"LINEEQUIPSTATE_RXONLY",
L"LINEEQUIPSTATE_TXONLY",
L"LINEEQUIPSTATE_NOTXRX",
L"LINEEQUIPSTATE_FULL"
};
TCHAR *szRadioSupport[] =
{
L"LINERADIOSUPPORT_OFF",
L"LINERADIOSUPPORT_ON",
L"LINERADIOSUPPORT_UNKNOWN"
};
DWORD dwState = 0;
DWORD dwRadioSupport = 0;
LONG lRet = lineGetEquipmentState(m_hLine,&dwState,&dwRadioSupport);
if ( lRet == 0 )
{
CString sInfo;
sInfo.Format(L"State = %s, Radio = %s",
szEqStates[dwState - 1],
szRadioSupport[dwRadioSupport-1]);
AfxMessageBox(sInfo);
}
else
{
TCHAR szMsg[255];
GetTAPIErrorMsg(szMsg,sizeof(szMsg), lRet);
AfxMessageBox(szMsg);
}
}
Network operator related functions
void CExTapiDlg::OnGetAvailOps()
{
LINEOPERATORSTATUS lops;
lops.dwTotalSize = sizeof(LINEOPERATORSTATUS);
BeginWaitCursor();
LONG lRes = ::lineGetOperatorStatus(m_hLine, &lops);
if (lRes != 0 && lRes != LINEERR_STRUCTURETOOSMALL)
{
EndWaitCursor();
TCHAR szMsg[255];
GetTAPIErrorMsg(szMsg,sizeof(szMsg), lRes);
AfxMessageBox(szMsg);
return;
}
CString sInfo(L"Available Operators:\r\n");
LPBYTE pLineOperatorStatusBytes = new BYTE[lops.dwNeededSize];
LPLINEOPERATORSTATUS pStatus =
(LPLINEOPERATORSTATUS)pLineOperatorStatusBytes;
if(pLineOperatorStatusBytes != NULL)
{
pStatus->dwTotalSize = lops.dwNeededSize;
if ( (lRes = ::lineGetOperatorStatus(m_hLine, pStatus)) != 0 )
{
TCHAR szMsg[255];
GetTAPIErrorMsg(szMsg,sizeof(szMsg), lRes);
AfxMessageBox(szMsg);
}
else
{
LPLINEOPERATOR pOperator = (LPLINEOPERATOR)((LPBYTE)pStatus+
(pStatus->dwAvailableOffset));
for(DWORD dwOperatorNumber = 0;dwOperatorNumber < pStatus->
dwAvailableCount;
dwOperatorNumber++)
{
sInfo += pOperator->lpszLongName;
sInfo += L"\r\n";
pOperator++;
}
}
}
delete[] pLineOperatorStatusBytes;
EndWaitCursor();
AfxMessageBox(sInfo);
}
Conclusion
Download
About the Author