[Windows CE] Using Ras C#

If we will ask somebody experienced questions like:”What should we use to establish dial up connection on Windows”, i`m totally sure that 90% of asked will answer use RAS library!

If some somebody will ask me what do to establish GPRS connection on Windows Mobile i answer use Connection Manager API, but there is nothing regarding Connection Manager API on Windows CE, but we can use RAS API!

If you developing on C++ or C thats not a problem, but what to do if your project on C#? I googled and found that opennet cf got ras components, but it aint free(!), so we need to create our own :)

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace CERas
{
/// <summary>
/// CERAS
/// </summary>
public class CERAS : IDisposable
{
#region Constants
private const int ENTRY_SIZE = 1464;
#endregion

#region P/Invoke
[DllImport("coredll.dll")]
public static extern uint RasDial(
IntPtr dialExtensions,
IntPtr phoneBookPath,
IntPtr rasDialParam,
uint notifierType,
IntPtr notifier,
ref IntPtr pRasConn);

[DllImport("coredll.dll")]
public static extern uint RasHangUp(IntPtr pRasConn);
#endregion

#region Private Declarations
private IntPtr rasConn_ = IntPtr.Zero; //Connection Handle
private uint result_ = 0;
private IntPtr rasEntry_ = IntPtr.Zero; //Entry Container
private string connName_ = ""; //connection name
private string userName_ = ""; //user name (could be empty string)
private string password_ = ""; // password (could be empty string)
#endregion

#region Properties
//property, sets or gets connection name
public string ConnectionName
{
get
{
return connName_;
}
set
{
if (value != connName_)
{
connName_ = value;
}
}
}

//property, sets or gets connection login
public string Login
{
get
{
return userName_;
}

set
{
if (value != userName_)
{
userName_ = value;
}
}
}

//property, sets or gets connection password
public string Password
{
get
{
return password_;
}
set
{
if (value != password_)
{
password_ = value;
}
}
}

//property, checks if connection established
public bool Established
{
get
{
return ((rasConn_ != IntPtr.Zero) && (result_ == 0));
}
}
#endregion

#region Public Methods
//Constructor
public CERAS()
{
rasConn_ = IntPtr.Zero;
result_ = 0;
rasEntry_ = Marshal.AllocHGlobal(ENTRY_SIZE); //Allocating 1464 bytes (size of Entry structure)
if (rasEntry_ == IntPtr.Zero)
{
throw new Exception("Error cannot get Allocate memory");
}
}

// Destructor
public void Dispose()
{
Marshal.FreeHGlobal(rasEntry_); //Free allocated memory
}

//Establishing connection, it will block thread that called this method
public bool Connect()
{
if (rasConn_ != IntPtr.Zero)
{
Disconnect();
}

FillEntry();
try
{
result_ = RasDial(IntPtr.Zero, IntPtr.Zero, rasEntry_, 0, IntPtr.Zero, ref rasConn_);
}
catch
{
//exception
}

if (result_ != 0)
{
Disconnect(); //we need call disconnect even if connection was not established
return false;
}
return true;
}

//Closing internet connection
public void Disconnect()
{
if (rasConn_ != IntPtr.Zero)
{
RasHangUp(rasConn_);
rasConn_ = IntPtr.Zero;
result_ = 0;
System.Threading.Thread.Sleep(3000); //read msdn, it says that we need wail like 3 seconds to release connection(!)
}
else
{
result_ = 0;
}
}
#endregion

#region Private Methods
//Clearing Entry Structure
private void ClearPtr()
{
//I`m totally sure that there should be easier way
for (int i = 0; i < ENTRY_SIZE; i++)
{
Marshal.WriteByte((IntPtr)(rasEntry_.ToInt32() + i), 0);
}
}

//Filling Entry structure
private void FillEntry()
{
ClearPtr();
IntPtr pCurrent = rasEntry_;
Marshal.WriteInt32(pCurrent, ENTRY_SIZE);

pCurrent = (IntPtr)(pCurrent.ToInt32() + 4);
foreach (byte b in Encoding.Unicode.GetBytes(connName_))
{
Marshal.WriteByte(pCurrent, b);
pCurrent = (IntPtr)(pCurrent.ToInt32() + 1);
}

pCurrent = (IntPtr)(rasEntry_.ToInt32() + 0x192);
foreach (byte b in Encoding.Unicode.GetBytes(userName_))
{
Marshal.WriteByte(pCurrent, b);
pCurrent = (IntPtr)(pCurrent.ToInt32() + 1);
}

pCurrent = (IntPtr)(rasEntry_.ToInt32() + 0x394);
foreach (byte b in Encoding.Unicode.GetBytes(password_))
{
Marshal.WriteByte(pCurrent, b);
pCurrent = (IntPtr)(pCurrent.ToInt32() + 1);
}
}
#endregion
}
}

Yau can download sources from here

BTW it should work on win mobile too :)

19 Responses to “[Windows CE] Using Ras C#”

Pages: [2] 1 » Show All

  1. 19
    wyvern Says:

    Hi, Alex.

    Your post is great. But can you show an example of using function “RasGetEntryDialParams” from “coredll”, which is usefull in cases when we don’t know login and password, and don’t want to ask for them?

  2. 18
    Mark Brown Says:

    Works great…thanks! I have been looking for something like this for a long time too!

  3. 17
    John Phee Says:

    Thanks Great code snippet! -Work perfectly on WinCE6.0.
    One problem though…I can’t seem to suppress the RAS (ie. OS) from asking again for the password.
    Does anyone know how to stop this ?

  4. 16
    BPM Says:

    i do not have any visual studio.
    is anybody here able to build this project so that i can enter my apn/user/pass in a config file and make a connection with this tool?
    i am using an win ce 6 device.

    why do i need this?
    see my problem here:
    http://www.meizume.com/m8-applications/9705-net-application-establish-gprs-connection.html

  5. 15
    Bambang Says:

    Hi Alex,
    Thank you very much for your source code.It’s really help me to finish my job.Hopefully, you will get more and more knowledge and can share to other people.

    Thanks,
    Bambang

  6. 14
    Mojtaba Says:

    Hi Prajwal,

    How do solve your problem?
    Please inform me. I have same problem.

  7. 13
    Serdar Says:

    I really thank you for this excelent code. It solved my problem. Thanks again.

  8. 12
    Prajwal Says:

    Hi Alex,

    Finally, at the end of my working day i was able to make a dial up connection using this blog….

    Really, i am happy.

    Alex, thank you man for your support till the last minute. I think the solution fixed after reconnection my modem physically. But not sure of it. Will cross check it and will mail you.

    Once again thank you.

  9. 11
    Prajwal Says:

    Hi,

    I tried the modification you specified but still it does not work for me.

    following is my complete code

    using System;
    using System.Text;
    using System.Runtime.InteropServices;

    namespace CERas
    {
    ///
    /// CERAS
    ///
    public class CERAS : IDisposable
    {
    #region Constants
    private const int ENTRY_SIZE = 1464;
    #endregion

    #region P/Invoke
    [DllImport(”coredll.dll”)]
    public static extern uint RasDial(
    IntPtr dialExtensions,
    IntPtr phoneBookPath,
    IntPtr rasDialParam,
    uint notifierType,
    IntPtr notifier,
    ref IntPtr pRasConn);

    [DllImport(”coredll.dll”)]
    public static extern uint RasHangUp(IntPtr pRasConn);
    #endregion

    #region Private Declarations
    private IntPtr rasConn_ = IntPtr.Zero; //Connection Handle
    private uint result_ = 0;
    private IntPtr rasEntry_ = IntPtr.Zero; //Entry Container
    private string connName_ = “”; //connection name
    private string userName_ = “”; //user name (could be empty string)
    private string password_ = “”; // password (could be empty string)
    #endregion

    #region Properties
    //property, sets or gets connection name
    public string ConnectionName
    {
    get
    {
    return connName_;
    }
    set
    {
    if (value != connName_)
    {
    connName_ = value;
    }
    }
    }

    //property, sets or gets connection login
    public string Login
    {
    get
    {
    return userName_;
    }

    set
    {
    if (value != userName_)
    {
    userName_ = value;
    }
    }
    }

    //property, sets or gets connection password
    public string Password
    {
    get
    {
    return password_;
    }
    set
    {
    if (value != password_)
    {
    password_ = value;
    }
    }
    }

    //property, checks if connection established
    public bool Established
    {
    get
    {
    return ((rasConn_ != IntPtr.Zero) && (result_ == 0));
    }
    }
    #endregion

    #region Public Methods
    //Constructor
    public CERAS()
    {
    rasConn_ = IntPtr.Zero;
    result_ = 0;
    rasEntry_ = Marshal.AllocHGlobal(ENTRY_SIZE); //Allocating 1464 bytes (size of Entry structure)
    if (rasEntry_ == IntPtr.Zero)
    {
    throw new Exception(”Error cannot get Allocate memory”);
    }
    }

    // Destructor
    public void Dispose()
    {
    Marshal.FreeHGlobal(rasEntry_); //Free allocated memory
    }

    //Establishing connection, it will block thread that called this method
    public bool Connect(IntPtr hWnd_)
    {
    if (rasConn_ != IntPtr.Zero)
    {
    Disconnect();
    }

    FillEntry();
    try
    {

    result_ = RasDial(IntPtr.Zero, IntPtr.Zero, rasEntry_, 0xFFFFFFFF, hWnd_, ref rasConn_);
    //result_ = RasDial(IntPtr.Zero, IntPtr.Zero, rasEntry_, 0, IntPtr.Zero, ref rasConn_);
    }
    catch
    {
    //exception
    }

    if (result_ != 0)
    {
    Disconnect(); //we need call disconnect even if connection was not established
    return false;
    }
    return true;
    }

    //Closing internet connection
    public void Disconnect()
    {
    if (rasConn_ != IntPtr.Zero)
    {
    RasHangUp(rasConn_);
    rasConn_ = IntPtr.Zero;
    result_ = 0;
    System.Threading.Thread.Sleep(3000); //read msdn, it says that we need wail like 3 seconds to release connection(!)
    }
    else
    {
    result_ = 0;
    }
    }
    #endregion

    #region Private Methods
    //Clearing Entry Structure
    private void ClearPtr()
    {
    //I`m totally sure that there should be easier way
    for (int i = 0; i < ENTRY_SIZE; i++)
    {
    Marshal.WriteByte((IntPtr)(rasEntry_.ToInt32() + i), 0);
    }
    }

    //Filling Entry structure
    private void FillEntry()
    {
    ClearPtr();
    IntPtr pCurrent = rasEntry_;
    Marshal.WriteInt32(pCurrent, ENTRY_SIZE);

    pCurrent = (IntPtr)(pCurrent.ToInt32() + 4);
    foreach (byte b in Encoding.Unicode.GetBytes(connName_))
    {
    Marshal.WriteByte(pCurrent, b);
    pCurrent = (IntPtr)(pCurrent.ToInt32() + 1);
    }

    pCurrent = (IntPtr)(rasEntry_.ToInt32() + 0×192);
    foreach (byte b in Encoding.Unicode.GetBytes(userName_))
    {
    Marshal.WriteByte(pCurrent, b);
    pCurrent = (IntPtr)(pCurrent.ToInt32() + 1);
    }

    pCurrent = (IntPtr)(rasEntry_.ToInt32() + 0×394);
    foreach (byte b in Encoding.Unicode.GetBytes(password_))
    {
    Marshal.WriteByte(pCurrent, b);
    pCurrent = (IntPtr)(pCurrent.ToInt32() + 1);
    }
    }
    #endregion

    }
    }

    private void btnDialUp_Click(object sender, EventArgs e)
    {
    try
    {
    objCE.ConnectionName = “Connection”;
    objCE.Login = “”;
    objCE.Password = “”;
    bool val = objCE.Connect(this.Handle);
    MessageBox.Show(”Connection result: ” + val.ToString() + ” Is Established: ” + objCE.Established.ToString());
    }
    catch (Exception ex)
    {

    MessageBox.Show(ex.Message.ToString());
    }
    }
    And the function which calls Ras connect

Pages: [2] 1 » Show All

Leave a Reply