Establishing GPRS Connection on Windows CE and Windows Mobile: Sample Codes
Sometimes developers asking for support have straightforward goals they want to achieve with the minimal amount of code, even if the "application" will work only on very specific scenarios. This was the case for a request I handled, where the goal was: connect the device via GPRS to Internet, when it's not cradled to a desktop PC and WiFi is not available. As you may know connections in Windows Mobile are entirely handled by the Connection Manager, and developers are "encouraged" on using only Connection Manager APIs, as long as you want CM-aware applications to run as expected. For example, IE Mobile is a CM-aware application: if you open a GPRS connection through RAS APIs as documented in the Windows *CE* documentation (see here), then Connection Manager wouldn't sense it and IE Mobile would request a new one. A well done article about this for mobile developers was written by Jim Wilson and is available here.
So, the "recommended" way on Windows Mobile is to invoke CM APIs, while on Windows CE you can use for example RAS APIs (CM is not available) - see below. Note that this code is meant to work when no other less expensive networks are available (ActiveSync\WMDC's Desktop-Passthrough, WiFi).
#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
#include "connmgr.h"
GUID GetNetworkForURL (LPCTSTR url)
{
DWORD dwIndex = 0;
GUID rv;
if (!SUCCEEDED (ConnMgrMapURL (url, &rv, &dwIndex)))
rv = GUID_NULL;
return rv;
}
HRESULT EstablishConnection (LPCTSTR url, DWORD retries, DWORD timeout, DWORD* dwStatus, HANDLE hConnection)
{
CONNMGR_CONNECTIONINFO ConnectionInfo;
ZeroMemory (&ConnectionInfo, sizeof (ConnectionInfo));
ConnectionInfo.cbSize = sizeof (ConnectionInfo);
ConnectionInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
ConnectionInfo.dwFlags = CONNMGR_FLAG_PROXY_HTTP;
ConnectionInfo.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
ConnectionInfo.guidDestNet = GetNetworkForURL (url);
return ConnMgrEstablishConnectionSync (&ConnectionInfo, &hConnection, timeout, dwStatus);
}
//
// Called when there was an error while connecting
// generally due to network connection not being available (no modem, no nic etc).
//
HRESULT DoConnectingError(DWORD dwStatus)
{
// we received an error to do with connecting.
SHELLEXECUTEINFO sei = {0};
TCHAR szExec[MAX_PATH];
wsprintf( szExec, TEXT("-CMERROR 0x%x -report"), dwStatus );
sei.cbSize = sizeof(sei);
sei.hwnd = NULL;
sei.lpFile = TEXT(":MSREMNET");
sei.lpParameters = szExec;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx( &sei );
return E_FAIL;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwStatus = 0;
HANDLE hConnection = NULL;
LPCTSTR url = L"https://www.msn.com"; //just to set Internet network - and no need for proxies
HRESULT hr = EstablishConnection (url, 10, 25000, &dwStatus, hConnection);
if ( FAILED( hr ) )
{
DoConnectingError(dwStatus);
}
ConnMgrReleaseConnection(hConnection, TRUE);
return 0;
}
while on Windows CE-based devices:
//TODO: ADD ERROR-CHECKING
BOOL ConnectGPRSonWindowsCE()
{
HRASCONN hRASConnection = NULL;
DWORD nRet;
RASENTRYNAME TempEntryName;
TempEntryName.dwSize = sizeof(RASENTRYNAME);
unsigned long EntryBufferSize = sizeof(TempEntryName);
unsigned long EntryWritten = 0;
//ERROR_BUFFER_TOO_SMALL is expected
nRet = RasEnumEntries( NULL, NULL, &TempEntryName, &EntryBufferSize, &EntryWritten );
if (nRet != ERROR_BUFFER_TOO_SMALL)
{
WCHAR strErr[255];
wsprintf(strErr,L"RasEnumEntries failed: Error %d\n", nRet);
MessageBox(NULL, (LPCTSTR)strErr, L"GPRS Monitor", MB_OK);
return FALSE;
}
RASENTRYNAME *RasEntryNameArray = (RASENTRYNAME*)malloc(EntryBufferSize);
RasEntryNameArray[0].dwSize = sizeof(RASENTRYNAME);
nRet = RasEnumEntries( NULL, NULL, RasEntryNameArray, &EntryBufferSize, &EntryWritten );
if (0 != nRet)
{
WCHAR strErr[255];
wsprintf(strErr,L"RasEnumEntries failed: Error %d\n", nRet);
MessageBox(NULL, (LPCTSTR)strErr, L"GPRS Monitor", MB_OK);
return FALSE;
}
int GPRSEntry = -1;
RASENTRY RasEntry;
memset( &RasEntry, 0, sizeof(RasEntry) );
RasEntry.dwSize = sizeof(RasEntry);
DWORD dwEntrySize = sizeof(RasEntry);
unsigned char Buffer[4098];
memset( Buffer, 0, sizeof(Buffer) );
DWORD dwBufferSize = sizeof(Buffer);
for ( unsigned long iEntry = 0; iEntry < EntryWritten; iEntry++ )
{
// Check if the name has GPRS in it
// AND
// if Local Phone Number contains "~GPRS!"
nRet = RasGetEntryProperties(NULL, RasEntryNameArray[iEntry].szEntryName, &RasEntry,&dwEntrySize,NULL,NULL);
if (0 != nRet)
{
WCHAR strErr[255];
wsprintf(strErr,L"RasGetEntryProperties failed: Error %d\n", nRet);
MessageBox(NULL, (LPCTSTR)strErr, L"GPRS Monitor", MB_OK);
return FALSE;
}
if ((wcsstr(RasEntry.szLocalPhoneNumber,L"~GPRS!") != NULL)
&&
(wcsstr(RasEntryNameArray[iEntry].szEntryName, L"GPRS") != NULL))
{
//RAS entry is GPRS - exit 'for' loop
GPRSEntry = iEntry;
break;
}
}
nRet = RasGetEntryProperties( NULL, RasEntryNameArray[GPRSEntry].szEntryName, &RasEntry, &dwEntrySize, Buffer, &dwBufferSize );
if(0 != nRet)
{
WCHAR strErr[255];
wsprintf(strErr,L"RasGetEntryProperties failed: Error %d\n", nRet);
MessageBox(NULL, (LPCTSTR)strErr, L"GPRS Monitor", MB_OK);
return FALSE;
}
// Configure the RASDIALPARAMS structure
RASDIALPARAMS RASDialParameters;
memset( &RASDialParameters,0,sizeof( RASDIALPARAMS ) );
RASDialParameters.szPhoneNumber[0] = NULL; //TEXT('\0');
RASDialParameters.szCallbackNumber[0] = NULL; //TEXT('\0');
RASDialParameters.dwSize = sizeof( RASDIALPARAMS );
wcscpy( RASDialParameters.szEntryName, RasEntryNameArray[GPRSEntry].szEntryName);
RASDialParameters.szUserName[0] = TEXT('\0');
RASDialParameters.szPassword[0] = TEXT('\0');
RASDialParameters.szDomain[0] = TEXT('\0');
//wcscpy (RasDialParams.szUserName, szUserName); //This is optional
//wcscpy (RasDialParams.szPassword, szPassword); //This is optional
//wcscpy (RasDialParams.szDomain, szDomain); //This is optional
//try reuse GPRS connection
BOOL bPassword = FALSE;
nRet = RasGetEntryDialParams(NULL, &RASDialParameters, &bPassword);
if (0 != nRet)
{
WCHAR strErr[255];
wsprintf(strErr,L"RasGetEntryDialParams failed: Error %d\n", nRet);
MessageBox(NULL, (LPCTSTR)strErr, L"GPRS Monitor", MB_OK);
return FALSE;
}
//free resources not on the stack
free ((VOID*)RasEntryNameArray);
// Try to establish RAS connection.
if ( RasDial( NULL, NULL, &RASDialParameters,
NULL, // Notifier type is NOT a window handle
NULL, // Window receives notification message - none
&hRASConnection ) != 0 )
{
if ( hRASConnection != NULL )
RasHangUp( hRASConnection );
hRASConnection = NULL;
MessageBox (/*hDlgWnd*/NULL, L"Could not connect using RAS", /*szTitle*/ L"GPRS Monitor", MB_OK);
return FALSE;
}
hRASConnection = NULL;
return TRUE;
}
Comments
Anonymous
April 20, 2008
This post is somehow related to a previous one ( Establishing GPRS Connection on Windows CE and WindowsAnonymous
May 23, 2008
I have a related problem. I do not know if this is right forum to ask. If this is not the right forum, can you please direct me to right forum please? I am using Windows CE 4.2, and I wanted Bluetooth USB Dongle to connect to PC using ActiveSync. Here are the things I did:
- Include Bluetooth USB driver in Platform Bilder Project
- Included ASUI sample application in my CE platform
- Updated the registry accordingly.
- It creates RAS entry for Bluetooth, but when it calls RasDial, it returns with error code 608, device not found.
- On the PC side, I have ActiveSync setting, selecting the BT virtual COM port. Bluetooth stack on CE device is loaded, I can see the CE device from my laptop. But it does not see any service on CE device. Thanks for your help.
Anonymous
May 23, 2008
Hi Santosh, The topic is a bit different (here I was talking about GPRS, you're interested on Bluetooth and ActiveSync). You may ask to MSDN Forums, probably the best one for you is http://forums.microsoft.com/msdn/ShowForum.aspx?ForumID=34&SiteID=1. If you won't find a solution, you may also open a request at Microsoft Technical Support. Thanks! ~raffaeleAnonymous
November 25, 2008
Hi, I have some problems in connecting the windows CE 5.0 platform to a Siemens GPRS modem (mod. TC35). I followed the instructions on this site (http://e-consystems.com/gprs.asp). I have a serial connection between the platform and the modem. I insert a Vodafone SIM card in to the modem. I create a new dial up connection as shown on the site: baudrate 19200 (the modem supports util 115 kB), no parity, hw flow control.. then I insert the special modem command: +cgdcont=1, "IP", "internet". My phone number is 99**1#. So I doible click on my new connection and don't insert username and pwd. When the platform tries to connect, on the screen appears the following error message: "the port is not available: another program may be using it. What should I do to let the platform and the modem work correctly? thanks.Anonymous
December 01, 2008
Hi Forzafaith, personally I suggest to touch base with the Windows CE's OEM to see if your issue is OEM-specific: it may well be that the "another program" the error message is talking about is OEM's. HTH.Anonymous
February 09, 2009
Hi Raffael, How can I set the APN for the Dial-Up?Anonymous
February 10, 2009
Hi afriza, On Windows Mobile, you can use XML Provisioning and specifically the CM_GPRSEntries. On Windows CE, you should use RasSetEntryDialParams to set the RASDIALPARAMS structure you need later to retrieve through RasEnumEntries. You may start from http://msdn.microsoft.com/en-us/library/aa922037.aspx. HTH, ~raffaeleAnonymous
April 08, 2009
Hi Raffaele, I've taken a look at RasSetEntryDialParams() and RasSetEntryProperties() but I haven't found any APN related variables, or did I missed out something here? afrizaAnonymous
April 08, 2009
Maybe because the sample code at the page I mentioned (http://msdn.microsoft.com/en-us/library/aa922037.aspx) omitted such parts... // Insert code here to fill the RASENTRY structure. // ... ... // Insert code here to fill up the RASDIALPARAMS structure. // ... but this is where you can set the APN related variables. For example: RASENTRY RasEntry; RASIPADDR EmptyIP = {0,0,0,0}; memset (&RasEntry, 0, sizeof(RASENTRY)); RasEntry.dwSize = sizeof(RASENTRY); RasEntry.dwfOptions = 0; RasEntry.dwCountryID = 0; RasEntry.dwCountryCode = dwCountryCode; _tcscpy (RasEntry.szAreaCode, lpszAreaCode); _tcscpy (RasEntry.szLocalPhoneNumber, lpszPhoneNumber); RasEntry.dwAlternatesOffset = 0; RasEntry.ipaddr = EmptyIP; RasEntry.ipaddrDns = EmptyIP; RasEntry.ipaddrDnsAlt = EmptyIP; RasEntry.ipaddrWins = EmptyIP; RasEntry.ipaddrWinsAlt = EmptyIP; RasEntry.dwFrameSize = 1500; RasEntry.dwfNetProtocols = RASNP_Ip; RasEntry.dwFramingProtocol = RASFP_Ppp; _tcscpy (RasEntry.szScript, TEXT("")); _tcscpy (RasEntry.szAutoDialDll, TEXT("")); _tcscpy (RasEntry.szAutoDialFunc, TEXT("")); // _tcscpy (RasEntry.szDeviceType, RASDT_Modem); _tcscpy (RasEntry.szDeviceType, RASDT_Direct); _tcscpy (RasEntry.szDeviceName, lpszModemName); _tcscpy (RasEntry.szX25PadType, TEXT("")); _tcscpy (RasEntry.szX25Address, TEXT("")); _tcscpy (RasEntry.szX25Facilities, TEXT("")); _tcscpy (RasEntry.szX25UserData, TEXT("")); RasEntry.dwChannels = 1; RasEntry.dwReserved1 = 0; RasEntry.dwReserved2 = 0; RetVal = RasSetEntryProperties ( NULL, lpszEntryName, &RasEntry, sizeof(RasEntry), NULL, //default DEVCFG parameters 0);Anonymous
April 15, 2009
Hi Raffaele, Thank you for your replies, maybe I misunderstood something, but what I want to set is something like "internet" value for Access Point Name ( APN, as described in the example in http://en.wikipedia.org/wiki/Access_Point_Name ). I think it corresponds to the GPRSInfoAccessPointName parameter in the XML Provisioning. However, I find no corresponding variable in RASENTRY ( http://msdn.microsoft.com/en-us/library/aa920252.aspx ) nor in RASDIALPARAMS ( http://msdn.microsoft.com/en-us/library/aa920539.aspx ) previously I used to open a serial port and send AT command +cgdcont=1, "IP", "internet" to set the APN. I wonder if there is a better way using some APIs. Thank you again and regards, afrizaAnonymous
April 15, 2009
Just for clarification, I am developing for Windows CE.Anonymous
April 16, 2009
You should set Extra dial-string modem commands, for example thru the registry under HKLMExtModems<ModemDriver>Init. I'm referring to a string like AT+CGDCONT=1,"IP","myAPN.com", I'm sorry I don't have a sample code right now but you may be able to find it over the web now that you know what to look for. There will be more than one key, each separated by the literal string "<cr>". HTH! ~raffaeleAnonymous
February 19, 2010
i am java coder but i need to develop an app for my win ce6 device in .net. i tired this code, but i do something wrong. i only made a new project and inserted this code. i was able to compile and depoly to my device. here my output: Modul laden: RasConn.exe Modul laden: coredll.dll.0409.MUI Modul laden: MZFC0960.dll Modul laden: ddraw.dll Modul laden: fpcrt.dll Modul laden: ole32.dll Modul laden: rpcrt4.dll Modul laden: lpcrt.dll Modul laden: coredll.dll Das Programm "[0xB72007E] RasConn.exe" wurde mit Code -1 (0xffffffff) beendet. can u help me? here you can see why i need this: http://www.meizume.com/m8-applications/9705-net-application-establish-gprs-connection.html there is a firmware bug on my mobile device. so i am not able to make a connection with mobilkom austria. so i need an application to do this. regards, MarkusAnonymous
February 21, 2010
Hi Markus, I'm sorry but didn't understand precisely the issue. I imagine you know that the sample above is native language, not for .NET Compact Framework (so you should use Win32 templates). Also, make sure you're targeting the right platform: Wiindows Mobile is different from Windows CE in terms of GPRS connectivity (the Connection Manager is available only on Mobile). Consider also opening a Service Request at Microsoft Technical Support: this may be an option, before the issue becomes too urgent. Viceversa, i.e. if not urgent, then we may also try continuing offline - just contact me thru http://blogs.msdn.com/raffael/contact.aspx. HTH! ~raffaeleAnonymous
February 22, 2010
native means that i can use a Win32 template and can run on win ce6 too? I know that i have to use RAS and not CM. I used a ppc template.Anonymous
February 23, 2010
Feel free to continue offline as I mentioned in my previous answer. Doesn't the manufacturer of the Windows CE 6.0-based device provide a "Private SDK" so that you can target it? Otherwise Visual Studio's "templates" will use the wrong INCLUDE folder, i.e. the wrong header files - hence the same code may not be eligible to work on that platform. HTH! ~raffaeleAnonymous
June 14, 2010
Hi Raffaele, Do you happen to know if the RasDial function has a limit to the length of the username/password ? I have an application trying to access a private APN with a login of 25 chars (a few special ones, but all below the D128 in the ASCII table), and a password of 10 chars. It fails all the time. Accessing a public APN (without username/password) works just fine. BTW, I have the impression whatever goes wrong with RasDial, you get error 0x279 (port not available). Thanks in advance !Anonymous
June 14, 2010
Oeps, forgot to mention my device runs CE 5.0 ! Thanks !Anonymous
June 15, 2010
The comment has been removedAnonymous
September 21, 2011
Hi Raffaele, I'm developing a Ril for Windows CE. I'm able to pass the data test through a Gprs Ndis (WWAN based) connection. In Windows Mobile with almost the same Ril I can configure the gpr ndis connection with the CM, but in CE I don't have it. Can you give me some help about configuring a WWAN connection in the UI or programmaticly? Thank you!Anonymous
September 22, 2011
Hi David, please consider using your support contract and open a Service Request - I'm afraid blog-comments wouldn't be as effective in your case. If you've never tried Microsoft Technical Support, hopefully you can find interesting info in a non-technical post of mine: blogs.msdn.com/.../get-help-now-a-vademecum-about-requesting-technical-support-from-microsoft.aspx. Should you encounter problems on opening the request, contact me offline thru blogs.msdn.com/.../contact.aspx. HTH! ~raffaeleAnonymous
January 18, 2014
my windows embedded ce v6.00 i find it difficult to connect i need help