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 Windows

  • Anonymous
    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:

  1.  Include Bluetooth USB driver in Platform Bilder Project
  2. Included ASUI sample application in my CE platform
  3. Updated the registry accordingly.
  4. It creates RAS entry for Bluetooth, but when it calls RasDial, it returns with error code 608, device not found.
  5. 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! ~raffaele

  • Anonymous
    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, ~raffaele

  • Anonymous
    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? afriza

  • Anonymous
    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, afriza

  • Anonymous
    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! ~raffaele

  • Anonymous
    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, Markus

  • Anonymous
    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! ~raffaele

  • Anonymous
    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! ~raffaele

  • Anonymous
    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 removed

  • Anonymous
    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! ~raffaele

  • Anonymous
    January 18, 2014
    my windows embedded ce v6.00 i find it difficult to connect i need help