Programmatically getting the phone number of a device
One question that is often asked is "How do I get the phone number of my device?" Usually the person asking doesn't really need the phone number, they just need some number that uniquely identifies the device. While there does exist an IOCTL to get a unique ID (not the phone number), only apps that are privileged are allowed to call it. (On a closed Smartphone, that means only apps that have been signed with a certificate that is in the device's privileged certificate store.) As an alternative, the code below shows how to get the phone number (without needing to be privileged).
#include "stdafx.h"
#include "windows.h"
#include "tapi.h"
#include "tsp.h"
#define EXIT_ON_NULL(_p) \
if (_p == NULL) \
{ \
hr = E_OUTOFMEMORY; \
goto FuncExit; \
}
#define EXIT_ON_FALSE(_f) \
if (!(_f)) \
{ \
hr = E_FAIL; \
goto FuncExit; \
}
#define MAX(i, j) ((i) > (j) ? (i) : (j))
#define TAPI_API_LOW_VERSION 0x00020000
#define TAPI_API_HIGH_VERSION 0x00020000
#define CAPS_BUFFER_SIZE 512
HRESULT SHReadLineAddressCaps(LPTSTR szNumber, UINT cchNumber, PDWORD pdwCallFwdModes, UINT nLineNumber)
{
HRESULT hr = E_FAIL;
LRESULT lResult = 0;
HLINEAPP hLineApp;
DWORD dwNumDevs;
DWORD dwAPIVersion = TAPI_API_HIGH_VERSION;
LINEINITIALIZEEXPARAMS liep;
DWORD dwTAPILineDeviceID;
const DWORD dwAddressID = nLineNumber - 1;
liep.dwTotalSize = sizeof(liep);
liep.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
if (SUCCEEDED(lineInitializeEx(&hLineApp, 0, 0, TEXT("ExTapi_Lib"), &dwNumDevs, &dwAPIVersion, &liep)))
{
BYTE* pCapBuf = NULL;
DWORD dwCapBufSize = CAPS_BUFFER_SIZE;
LINEEXTENSIONID LineExtensionID;
LINEDEVCAPS* pLineDevCaps = NULL;
LINEADDRESSCAPS* placAddressCaps = NULL;
pCapBuf = new BYTE[dwCapBufSize];
EXIT_ON_NULL(pCapBuf);
pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
pLineDevCaps->dwTotalSize = dwCapBufSize;
// Get TSP Line Device ID
dwTAPILineDeviceID = 0xffffffff;
for (DWORD dwCurrentDevID = 0 ; dwCurrentDevID < dwNumDevs ; dwCurrentDevID++)
{
if (0 == lineNegotiateAPIVersion(hLineApp, dwCurrentDevID, TAPI_API_LOW_VERSION, TAPI_API_HIGH_VERSION,
&dwAPIVersion, &LineExtensionID))
{
lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);
if (dwCapBufSize < pLineDevCaps->dwNeededSize)
{
delete[] pCapBuf;
dwCapBufSize = pLineDevCaps->dwNeededSize;
pCapBuf = new BYTE[dwCapBufSize];
EXIT_ON_NULL(pCapBuf);
pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
pLineDevCaps->dwTotalSize = dwCapBufSize;
lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);
}
if ((0 == lResult) &&
(0 == _tcscmp((TCHAR*)((BYTE*)pLineDevCaps+pLineDevCaps->dwLineNameOffset), CELLTSP_LINENAME_STRING)))
{
dwTAPILineDeviceID = dwCurrentDevID;
break;
}
}
}
placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
placAddressCaps->dwTotalSize = dwCapBufSize;
lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);
if (dwCapBufSize < placAddressCaps->dwNeededSize)
{
delete[] pCapBuf;
dwCapBufSize = placAddressCaps->dwNeededSize;
pCapBuf = new BYTE[dwCapBufSize];
EXIT_ON_NULL(pCapBuf);
placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
placAddressCaps->dwTotalSize = dwCapBufSize;
lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);
}
if (0 == lResult)
{
if (szNumber)
{
szNumber[0] = _T('\0');
EXIT_ON_FALSE(0 != placAddressCaps->dwAddressSize);
// A non-zero dwAddressSize means a phone number was found
ASSERT(0 != placAddressCaps->dwAddressOffset);
PWCHAR tsAddress = (WCHAR*)(((BYTE*)placAddressCaps)+placAddressCaps->dwAddressOffset);
StringCchCopy(szNumber, cchNumber, tsAddress);
}
// Record the allowed forwarding modes
if (pdwCallFwdModes)
{
*pdwCallFwdModes = placAddressCaps->dwForwardModes;
}
hr = S_OK;
}
delete[] pCapBuf;
} // End if ()
FuncExit:
lineShutdown(hLineApp);
return hr;
}
// szNumber - Out Buffer for the phone number
//cchNumber - size of sznumber in characters
// nLineNumber - which phone line (1 or 2) to get the number for
HRESULT SHGetPhoneNumber(LPTSTR szNumber, UINT cchNumber, UINT nLineNumber)
{
return SHReadLineAddressCaps(szNumber, cchNumber, NULL, nLineNumber);
}
Comments
Anonymous
November 28, 2004
How about some bluetooth things using the WinSock stack new BT APIs? Is Bluetooth being wrapped in 2.0 Base Class Libraries in .NET for this? If not, do you know a good .NET wrapper for Winsock bluetooth APIs?Anonymous
November 30, 2004
Does this only work with the SIM cards that have the owners phone number stored?Anonymous
November 30, 2004
Great. Now can you tell how to get current info from the embedded GPS device?Anonymous
December 01, 2004
It seems like it takes a lot of code in this article to get the phone number. What is the difference with just making a single call to SmsGetPhoneNumber()?
If you don't post a reply, is there any chance you could email it to me? jeff@activemap.com - thanks!Anonymous
December 09, 2004
hi, im not sure why it doesn't work so i debug it myself and everything is success but ends to EXIT_ON_FALSE(0 != placAddressCaps->dwAddressSize);
what causes this?
thanks (progy at walla.com)Anonymous
December 19, 2004
Hello.
I am new to this stuff, and I just spent all Monday trying to get the code above to compile and link successfully. I am mostly using VB, both 6.0 and .NET, but I also have basic C/C++ knowledge.
I have on my PC eVC++ 4.0 sp2, and the SDKs for Windows Mobile 2003 based Smartphones and PPC's.
After many many moving around the .h files, I managed to compile this code, but I get 6 link errors like the one below:
error LNK2019: unresolved external symbol _lineShutdown referenced in function "long __cdecl SHReadLineAddressCaps(unsigned short *,unsigned int,unsigned long *,unsigned int)" (?SHReadLineAddressCaps@@YAJPAGIPAKI@Z)
Any help would be GREATLY appreciated.
KyriakosAnonymous
December 19, 2004
Adding to the message above,
please do contact me personally via email if you can help me with this program.
k.lakkas@protonet.gr
KyriakosAnonymous
December 26, 2004
I don't know why this code runs not stable. Some is good, but some is wrong.
I got "" always on a Motorola MPX220, and I tried it not 2 lines, but 5 lines. nLineNumber = 1->5.
Please help me!Anonymous
August 11, 2005
I can't get the phone number. I also always got "" on a Motorola MPX220, and I also tried SmsGetPhoneNumber(), it also gave me "" for phone number. Could you tell me why and how to get the phone number correctly.
BTW, I can get the deviceID using lineOpen(), lineGetGeneralInfo(), but have problem in getting the phone number. It could be great if you can help me for that.
Please contact me at: aaron_zhang888@yahoo.ca
Thanks.
AaronAnonymous
December 05, 2005
The comment has been removedAnonymous
June 11, 2006
Hi Jason
IT will be very helpful for me if you can post the full source as a zip file so that I can convert it into a DLL and call it from my managed code can you please do it for me
thanks
SriAnonymous
February 07, 2007
This is my site: http://32url.com/?88KM ,This is my site: http://32url.com/?88KMAnonymous
February 28, 2007
hi jason, we r developing an telephony application on windows mobile 5.0 using .net cf 2.0.we r able to control the speaker phone volume but not able to control the headset volume. IT will be very helpful for us if u can help us in this.Anonymous
April 03, 2007
HI GUYZ! This code works fine on windows mobile smartphone 5.0 emulator.But not working on device.Same case is also happening with SmsGetPhoneNumber(). can anybody suggest any way out.Anonymous
May 03, 2007
Hello. I have problem with enter to this site via GPRS. Please, help me. Thanks! Best regards.Anonymous
May 07, 2007
Hi, I try to use the code but the result is always empty could please explain me the reason of this resultAnonymous
October 08, 2007
I tried it. But the result is also always empty. Can someone please help?Anonymous
October 08, 2007
My email is shellyshao@hotmail.com. I tried above sample and the sample from msdn, always get empty phone number. Help is greatly appreciated.Anonymous
January 03, 2008
Hello,all I met the question exactly as Kyriakos met.If someone can help me about this,I will be Great appreaciated. Thank all very muchAnonymous
February 25, 2008
I tried this program in a HP iPAQ Bussines Navigator and always the result is empty. Anyone knows another way to obtain the own phone number? I tried the program with the same SIM Card in a HP 6915 and works fine.Anonymous
April 07, 2008
thanks ,starting from your code I can get the imei code using lineGetGeneralInfo().. ;)Anonymous
March 21, 2009
Hello, the own phone number (MSISDN) is assigned to mobile station by operator during outgoing call, therefore you can get the number out of SIM only if operator stored it there. Jan