Thursday, January 29, 2009

Rasdial in C#

public void RasDial(SERVICE_CLASSES_UUID16 scuServiceClass, string sBluetoothAddress, string sPhoneNumber, string sUserName, string sPassword, int iChannel)
{
//step 1: maybe keep a list to check if this connection is already active

//step 2: createBluetoothDeviceRegistryEntry
//> Purpose: create the registry entry for a bluetooth RAS device
//> ---------------------------------------------------------------------------
#if UseCOM1
int iPort = 1;
#else
int iPort = 2;
#endif
string m_strDeviceFriendlyName = GetRegDeviceName(scuServiceClass) + "(" + sBluetoothAddress + ")";
string m_strEntryName = "BSP"+ iPort.ToString();

RegistryKey rk = Registry.LocalMachine;
using (RegistryKey rk1 = rk.CreateSubKey("\\Software\\Microsoft\\bluetooth\\device\\" + GetRegDeviceName(scuServiceClass) + "\\" + GetUnformattedBluetoothAddress(sBluetoothAddress)))
{
rk1.SetValue("handle", 0 );
rk1.SetValue("encrypt", 1);
rk1.SetValue("auth", 1);
rk1.SetValue("mtu", scuServiceClass != SERVICE_CLASSES_UUID16.PANU ? 2048 : 1024);
rk1.SetValue("hid_subclass", 0);
rk1.SetValue("channel", scuServiceClass != SERVICE_CLASSES_UUID16.PANU ? iChannel : 0); //need channel number from serial port connection

rk1.SetValue("port_name", "BSP"+ iPort.ToString());

rk1.SetValue("service_id", GetServiceClassString(scuServiceClass));
rk1.SetValue("name", m_strDeviceFriendlyName);
rk1.Close();
}

//step 3: createBluetoothDevicePortEntry
//> Purpose: the bluetooth port entry for the entry created in
//> createBluetoothDeviceRegistryEntry
//> ---------------------------------------------------------------------------
using (RegistryKey rk1 = rk.CreateSubKey("\\Software\\Microsoft\\bluetooth\\device\\ports\\" + m_strDeviceFriendlyName))
{
rk1.SetValue("context", 0);
rk1.SetValue("index", iPort);
rk1.SetValue("prefix", "BSP");
rk1.SetValue("dll", "btd.dll");

//Part2 of //step 5: enableBluetoothModem
PORTEMUPortParams pp = new PORTEMUPortParams();
byte[] bA = new byte[8];
if(GetBinaryBluetoothAddress(sBluetoothAddress, ref bA))
pp.device = System.BitConverter.ToInt64(bA, 0); //int address of bluetooth
else
pp.device = 0; //int address of bluetooth
pp.channel = iChannel;
pp.imtu = 0x00000800;
////
//// RFCOMM Apis
////
//#define RFCOMM_PORT_FLAGS_REMOTE_DCB 0x00000001
//#define RFCOMM_PORT_FLAGS_KEEP_DCD 0x00000002
//#define RFCOMM_PORT_FLAGS_AUTHENTICATE 0x00000004
//#define RFCOMM_PORT_FLAGS_ENCRYPT 0x00000008
pp.uiportflags |= 0x00000004; //RFCOMM_PORT_FLAGS_AUTHENTICATE
pp.uiportflags |= 0x00000008; //RFCOMM_PORT_FLAGS_ENCRYPT

IntPtr ipTmp = LocalAlloc(0x40, (uint)Marshal.SizeOf(pp));
Marshal.StructureToPtr(pp, ipTmp, false); //Troubleshooting Exceptions: System.NotSupportedException:have to change PORTEMUPortParams to simple one

rk1.SetValue("context", ipTmp.ToInt32()); //32 or 64..WORD
rk1.Close();
}
//step 4: createBluetoothDevicePortUnimodemEntry
//> Purpose: the bluetooth port unimodem entry for the entry created in
//> createBluetoothDevicePortEntry
//> ---------------------------------------------------------------------------
using (RegistryKey rk1 = rk.CreateSubKey("\\Software\\Microsoft\\bluetooth\\device\\ports\\" + m_strDeviceFriendlyName + "\\unimodem"))
{
rk1.SetValue("devicetype", 0);
rk1.SetValue("tsp", "unimodem.dll");
rk1.SetValue("devicetype", m_strDeviceFriendlyName); // //Part 1 of step 5: enableBluetoothModem
rk1.SetValue("friendlyname", scuServiceClass == SERVICE_CLASSES_UUID16.LANAccessUsingPPP ? 0 : 1);
rk1.Close();
}
//step 5: enableBluetoothModem
////> ---------------------------------------------------------------------------
////> Purpose: activate a pre-registered Bluetooth modem
////> ---------------------------------------------------------------------------
IntPtr ipReturn = ActivateDevice("software\\microsoft\\bluetooth\\device\\ports\\" + m_strDeviceFriendlyName, 0);
if (ipReturn.ToInt32() != -1)
{
//registr
using (RegistryKey rk1 = rk.CreateSubKey("software\\microsoft\\bluetooth\\device\\" + GetServiceClassString(scuServiceClass) + "\\" + GetUnformattedBluetoothAddress(sBluetoothAddress)))
//using (RegistryKey rk1 = rk.OpenSubKey("software\\microsoft\\bluetooth\\device\\" + GetServiceClassString(scuServiceClass) + "\\" + GetUnformattedBluetoothAddress(sBluetoothAddress), true))
{
//rk1.SetValue("handle", Convert.ToInt32(ipReturn));
rk1.SetValue("handle", ipReturn.ToInt32());
rk1.SetValue("active", 1);

// Already setup earlier
//rk1.SetValue("handle", 0);
rk1.SetValue("encrypt", 1);
rk1.SetValue("auth", 1);
rk1.SetValue("mtu", scuServiceClass != SERVICE_CLASSES_UUID16.PANU ? 2048 : 1024);
rk1.SetValue("hid_subclass", 0);
rk1.SetValue("channel", scuServiceClass != SERVICE_CLASSES_UUID16.PANU ? iChannel : 0); //need channel number from serial port connection

rk1.SetValue("port_name", "BSP" + iPort.ToString());

rk1.SetValue("service_id", GetServiceClassString(scuServiceClass));
rk1.SetValue("name", m_strDeviceFriendlyName);

rk1.Close();
}

}
else
{
MessageBox.Show("ActivateDevice failed!");

}

//step 6: if all above good: createRasPhoneBookEntry
RASDEVINFO[] rdiRets = new RASDEVINFO[1];

uint intRet = 0;
int lpcb = 0;
int lpcDevices = 0;
IntPtr devinfo = IntPtr.Zero;
int iFoundIndex = -1;

intRet = RasConnection.RasEnumDevices(IntPtr.Zero, ref lpcb, ref lpcDevices);

devinfo = Marshal.AllocHGlobal(lpcb);

rdiRets[0] = new RASDEVINFO();
rdiRets[0].dwSize = Marshal.SizeOf(typeof(RASDEVINFO));
Marshal.WriteInt32(devinfo, Marshal.SizeOf(rdiRets[0]));

intRet = RasConnection.RasEnumDevices(devinfo, ref lpcb, ref lpcDevices);
if (intRet == 0)
{
rdiRets = new RASDEVINFO[lpcDevices];
for (int i = 0; i < devinfo =" (IntPtr)(devinfo.ToInt32()" szdevicename ="="" ifoundindex =" i;" rasconnection =" new" szlocalphonenumber =" sPhoneNumber;" szdevicetype =" (sPhoneNumber" szdevicename =" m_strDeviceFriendlyName;" localrasconnection =" new" dwsize =" Marshal.SizeOf(typeof(RASENTRY));" bsp =" new" dwsize =" dwSize;" temp =" 512;" dwgetentry =" 0;" dwgetentry =" RasConnection.RasGetEntryProperties(">= 1)
{
MessageBox.Show("RasDial:Unable to retrieve information:" + dwGetEntry.ToString()); //passed after readjust struc
//return;
}else
{
//#define RASEO_DialAsLocalCall 0x00020000
localRasConnection.dwfOptions |= 0x00020000;
//#define RASEO_UseCountryAndAreaCodes 0x00000001
localRasConnection.dwfOptions &= ~(0x00000001);
//#define RASEO_SpecificIpAddr 0x00000002
localRasConnection.dwfOptions &= ~(0x00000002);
//#define RASEO_SpecificNameServers 0x00000004
localRasConnection.dwfOptions &= ~(0x00000004);
//#define RASEO_SwCompression 0x00000200
localRasConnection.dwfOptions &= ~(0x00000200);
//#define RASEO_IpHeaderCompression 0x00000008
localRasConnection.dwfOptions &= ~(0x00000008);
localRasConnection.dwCountryCode = 1;
//#define RASNP_Ip 0x00000004 // Negotiate TCP/IP
localRasConnection.dwfNetProtocols = 0x00000004;
//#define RASFP_Ppp 0x00000001 // Point-to-Point Protocol (PPP)
localRasConnection.dwFramingProtocol = 0x00000001;
localRasConnection.szDeviceType = (sPhoneNumber != "" ? "modem" : "direct");
localRasConnection.szDeviceName = m_strDeviceFriendlyName;
localRasConnection.szAreaCode = "";
localRasConnection.szLocalPhoneNumber = sPhoneNumber;

dwGetEntry = RasConnection.RasSetEntryProperties(null, m_strEntryName, ref localRasConnection, dwSize, null, 0);
if (dwGetEntry >= 1)
{
MessageBox.Show("RasDial:Unable to RasSetEntryProperties:" + dwGetEntry.ToString()); //621;passed after change first parameter from "" to null
//return;
}else
{
SetDialingParameters("0","Work","G","G","G","1","","0","0");

RASDIALPARAMS RasDialParams;
RasDialParams = new RASDIALPARAMS();

RasDialParams.dwSize = (int)Marshal.SizeOf(typeof(RASDIALPARAMS));
RasDialParams.szEntryName = m_strEntryName;
RasDialParams.szPhoneNumber = sPhoneNumber;
RasDialParams.szUserName = sUserName ;
RasDialParams.szPassword = sPassword;

dwGetEntry = RasConnection.RasSetEntryDialParams(null, ref RasDialParams, false);
IntPtr m_hRasConnection = IntPtr.Zero;
if (dwGetEntry >= 1)
{
MessageBox.Show("RasDial:Unable to RasSetEntryDialParams:" + dwGetEntry.ToString()); //610:passed after change first parameter from "" to null
//return;
}

dwGetEntry = RasConnection.RasDial(IntPtr.Zero, IntPtr.Zero, ref RasDialParams, 0, IntPtr.Zero, ref m_hRasConnection);
if (dwGetEntry >= 1)
{
MessageBox.Show("RasDial:Unable to RasDial:" + dwGetEntry.ToString()); //608:ERROR_DEVICE_DOES_NOT_EXIS //http://msdn.microsoft.com/en-us/library/bb530704(VS.85).aspx
//return;
}

}

}

}
}
}
private void SetDialingParameters(string KeyName, string Location, string LocalCalls,
string LongDistanceCalls, string InternationalCalls,
string AreaCode, string DisableCallWaitingSequence,
string CountryCode, string ToneOrPulse)
{
//C++ way
//string ConfigurationString = Location + "\0" + LocalCalls + "\0" + LongDistanceCalls + "\0" +
// InternationalCalls + "\0" + AreaCode + "\0" + DisableCallWaitingSequence + "\0" +
// CountryCode + "\0" + ToneOrPulse + "\0";

//C# The way to create REG_MULTI_SZ
string[] ConfigurationString = new string[8];
ConfigurationString[0] = Location;
ConfigurationString[1] = LocalCalls;
ConfigurationString[2] = LongDistanceCalls;
ConfigurationString[3] = InternationalCalls;
ConfigurationString[4] = AreaCode;
ConfigurationString[5] = DisableCallWaitingSequence;
ConfigurationString[6] = CountryCode;
ConfigurationString[7] = ToneOrPulse;

RegistryKey rk = Registry.CurrentUser;
using (RegistryKey rk1 = rk.CreateSubKey("ControlPanel\\Dial\\Locations"))
{
rk1.SetValue(KeyName, ConfigurationString);
rk1.Close();
}
}
private bool GetBinaryBluetoothAddress(string sBluetoothAddress, ref byte[] bBTAddress)
{
try
{
//00:03:c9:56:0c:EE
string[] sTmp = sBluetoothAddress.Split(':');
bBTAddress[0] = Convert.ToByte(sTmp[5], 16);
bBTAddress[1] = Convert.ToByte(sTmp[4], 16);
bBTAddress[2] = Convert.ToByte(sTmp[3], 16);
bBTAddress[3] = Convert.ToByte(sTmp[2], 16);
bBTAddress[4] = Convert.ToByte(sTmp[1], 16);
bBTAddress[5] = Convert.ToByte(sTmp[0], 16);
bBTAddress[6] = 0;
bBTAddress[7] = 0;
return true;
}
catch
{
return false;
}
}
private string GetUnformattedBluetoothAddress(string sBluetoothAddress)
{
//00:03:c9:56:0c:EE
string[] sTmp = sBluetoothAddress.Split(':');
string sUnformattedBTAddress = sTmp[5] + sTmp[4]+ sTmp[3] + sTmp[2] + sTmp[1] + sTmp[0] + "0000";
return sUnformattedBTAddress;
}

private RASDEVINFO[] getDevices()
{
RASDEVINFO[] rdiRets = new RASDEVINFO[1];

uint intRet = 0;
int lpcb = 0;
int lpcDevices = 0;
IntPtr devinfo = IntPtr.Zero;

intRet = RasConnection.RasEnumDevices(IntPtr.Zero, ref lpcb, ref lpcDevices);

devinfo = Marshal.AllocHGlobal(lpcb);

rdiRets[0] = new RASDEVINFO();
rdiRets[0].dwSize = Marshal.SizeOf(typeof(RASDEVINFO));
Marshal.WriteInt32(devinfo, Marshal.SizeOf(rdiRets[0]));

intRet = RasConnection.RasEnumDevices(devinfo, ref lpcb, ref lpcDevices);
if (intRet == 0)
{
rdiRets = new RASDEVINFO[lpcDevices];
for (int i = 0; i < lpcDevices; i++)
{
rdiRets[i] = new RASDEVINFO();

Marshal.PtrToStructure(devinfo, rdiRets[i]);


devinfo = (IntPtr)(devinfo.ToInt32() + Marshal.SizeOf(rdiRets[i]));
}
}
return rdiRets;
}

1 comment:

Astrophobos said...

Can you please explain the purpose of that line:

for (int i = 0; i < devinfo =" (IntPtr)(devinfo.ToInt32()" szdevicename ="="" ifoundindex =" i;" rasconnection =" new" szlocalphonenumber =" sPhoneNumber;" szdevicetype =" (sPhoneNumber" szdevicename =" m_strDeviceFriendlyName;" localrasconnection =" new" dwsize =" Marshal.SizeOf(typeof(RASENTRY));" bsp =" new" dwsize =" dwSize;" temp =" 512;" dwgetentry =" 0;" dwgetentry =" RasConnection.RasGetEntryProperties(">= 1)