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;
}

Tuesday, January 27, 2009

Storage: MAP in C++ and List in C# (2)

MAP in C++ and List in C#
=====================

(2) MAP in C++

In C++, we can use MAP to do similar thing as List in C#.
-------------------BTMap.h----
----------------------
#include "BluetoothDevice.h"
#include map
using namespace std;

typedef struct
{
TCHAR tcDeviceName[100];
TCHAR tcAddress[100];
}BLUETOOTHDEVICE;

typedef map BLUETOOTHDEVICEMAP;
typedef BLUETOOTHDEVICEMAP::iterator BLUETOOTHDEVICEITERATOR;
typedef pair BLUETOOTHDEVICEMAPPAIR;

class BluetoothDeviceMap : public BLUETOOTHDEVICEMAP
{
private:
CRITICAL_SECTION m_CriticalSection;;
bool m_bIsDirty;

private:

BluetoothDevice *findBluetoothDevice(CString bluetoothAddress,int &iIndex);
void removeBluetoothDevice(int iIndex);
void removeBluetoothDevice(BluetoothDevice *pBluetoothDevice,int &iIndex);

public:
BluetoothDeviceMap(void);
virtual ~BluetoothDeviceMap(void);
int GetDeviceIndex(BluetoothDevice *pBluetoothDevice);
bool IsDevicePaired(DWORD dwIndex);
void SetDirtyBit() {m_bIsDirty = true;};
void RemoveBluetoothDevice(int iIndex);
void RemoveBluetoothDevice(BluetoothDevice *pBluetoothDevice);
void RemoveBluetoothDevice(LPTSTR bluetoothAddress);
void flush();
void Flush();

BluetoothDevice *findBluetoothDevice(LPTSTR bluetoothAddress,int &iIndex);
BluetoothDevice *AddBluetoothDevice(BLUETOOTHDEVICE *pQueryResult);
BluetoothDevice *GetBluetoothDevice(int iIndex);
BluetoothDevice *GetBluetoothDevice(LPTSTR bluetoothAddress);
//CSDPRecord *GetSDPRecord(BT_ADDR bluetoothAddress,SERVICE_CLASSES_UUID16 serviceClassID);

-------------------BTMap.cpp-----------------------------
#include "stdafx.h"
#include "BluetoothDeviceMap.h"

BluetoothDeviceMap::BluetoothDeviceMap(void)
{
InitializeCriticalSection(&m_CriticalSection);
}

BluetoothDeviceMap::~BluetoothDeviceMap(void)
{
DeleteCriticalSection(&m_CriticalSection);
}
void BluetoothDeviceMap::removeBluetoothDevice(int iIndex)
{
if((iIndex >=0)&&(iIndex < (int)size()))
{
BLUETOOTHDEVICEITERATOR iter = find(iIndex);
delete iter->second;
erase(iter);
}
}

void BluetoothDeviceMap::RemoveBluetoothDevice(int iIndex)
{
EnterCriticalSection(&m_CriticalSection);
removeBluetoothDevice(iIndex);
LeaveCriticalSection(&m_CriticalSection);
}

void BluetoothDeviceMap::RemoveBluetoothDevice(BluetoothDevice *pBluetoothDevice)
{
EnterCriticalSection(&m_CriticalSection);
for(BLUETOOTHDEVICEITERATOR iter = begin(); iter != end();iter++)
{
if(iter->second == pBluetoothDevice)
{
removeBluetoothDevice(iter->first);
break;
}
}
LeaveCriticalSection(&m_CriticalSection);

}
void BluetoothDeviceMap::RemoveBluetoothDevice(LPTSTR bluetoothAddress)
{
EnterCriticalSection(&m_CriticalSection);
for(BLUETOOTHDEVICEITERATOR iter = begin(); iter != end();iter++)
{
if(iter->second->GetBTAddress() == bluetoothAddress)
{
removeBluetoothDevice(iter->first);
break;
}
}
LeaveCriticalSection(&m_CriticalSection);
}

void BluetoothDeviceMap::flush()
{
for (BLUETOOTHDEVICEITERATOR itr = begin();itr != end();itr++)
{
delete itr->second;
}
clear();
m_bIsDirty = false;
}
void BluetoothDeviceMap::Flush()
{
EnterCriticalSection(&m_CriticalSection);
//flushToRegistry();
flush();
LeaveCriticalSection(&m_CriticalSection);
}

int BluetoothDeviceMap::GetDeviceIndex(BluetoothDevice *pBluetoothDevice)
{
int tmp = -1;
EnterCriticalSection(&m_CriticalSection);
for(BLUETOOTHDEVICEITERATOR iter = begin(); iter!=end();iter++)
{
if(iter->second = pBluetoothDevice)
{
tmp = iter->first;
break;
}
}
LeaveCriticalSection(&m_CriticalSection);
return tmp;
}

BluetoothDevice *BluetoothDeviceMap::AddBluetoothDevice(BLUETOOTHDEVICE *pQueryResult)
{
BluetoothDevice *tmpBTDevice = NULL;
EnterCriticalSection(&m_CriticalSection);
int iIndex = -1;
CString aa;
//aa.Format(L"%s", pQueryResult->tcAddress);
if(findBluetoothDevice(pQueryResult->tcAddress, iIndex)==NULL)
{
tmpBTDevice = new BluetoothDevice(pQueryResult->tcDeviceName, pQueryResult->tcAddress);
insert(BLUETOOTHDEVICEMAPPAIR(size(), tmpBTDevice));
iIndex = size()-1;
}else
iIndex = -1;

return tmpBTDevice;
}
BluetoothDevice * BluetoothDeviceMap::findBluetoothDevice(LPTSTR bluetoothAddress,int &iIndex)
{
BLUETOOTHDEVICEITERATOR iter;
bool bFound = false;
for(iter=begin(); iter!=end();iter++)
{
if(iter->second->GetBTAddress() == bluetoothAddress)
{
iIndex = iter->first;
bFound = true;
break;
}
}
return bFound == true ? iter->second : NULL;

}

BluetoothDevice * BluetoothDeviceMap::GetBluetoothDevice(int iIndex)
{
BluetoothDevice *p;
BLUETOOTHDEVICEITERATOR itr;
EnterCriticalSection(&m_CriticalSection);
if (0 <= iIndex && iIndex < (int)size())
{
itr = find(iIndex);
p = itr->second;
}
LeaveCriticalSection(&m_CriticalSection);
return itr->second;
}
BluetoothDevice * BluetoothDeviceMap::GetBluetoothDevice(LPTSTR bluetoothAddress)
{
EnterCriticalSection(&m_CriticalSection);
int iIndex = -1;
BluetoothDevice *p = findBluetoothDevice(bluetoothAddress,iIndex);
LeaveCriticalSection(&m_CriticalSection);
return p;
}
bool BluetoothDeviceMap::IsDevicePaired(DWORD dwIndex)
{
bool bReturn = false;
if(dwIndex >= 0 && dwIndex < (DWORD)size() )
{
BLUETOOTHDEVICEITERATOR iter = find(dwIndex);
if(iter->second != NULL)
{
bReturn = iter->second->IsDevicePaired();
}
}
return bReturn;
}
------------------------------BluetoothDevice.h-------------------
#pragma once

class BluetoothDevice
{
private:
TCHAR m_DeviceName[100];
TCHAR m_tcAddress[100];
bool m_Paired;

public:
BluetoothDevice(void);
BluetoothDevice(TCHAR DeviceName[100], TCHAR tcAddress[100]);

virtual ~BluetoothDevice(void);
LPTSTR GetBTAddress(){return m_tcAddress;};
LPTSTR GetDeviceName(){return m_DeviceName;};
bool IsDevicePaired(){ return m_Paired;};
};
----------------------BluetoothDevice.cpp------------------------
#include "stdafx.h"
#include "BluetoothDevice.h"

BluetoothDevice::BluetoothDevice(void)
{
}
BluetoothDevice::BluetoothDevice(LPTSTR DeviceName, LPTSTR tcAddress)
{
_tcscpy(m_DeviceName,DeviceName);
_tcscpy(m_tcAddress,tcAddress);
}

BluetoothDevice::~BluetoothDevice(void)
{
}
------------------------To Use--------------------------------
Add:

BLUETOOTHDEVICE *tmpBTDevice = new BLUETOOTHDEVICE();
CString sssAddress = "myName";
_tcsncpy(tmpBTDevice->tcDeviceName,sssAddress,sssAddress.GetLength());
CString sssAddress = "myAddress";
_tcsncpy(tmpBTDevice->tcAddress ,sssAddress,sssAddress.GetLength());

m_pCMSBluetooth->AddBluetoothDevice(tmpBTDevice);
_tcscpy(tmpBTDevice->tcAddress,L"");
_tcscpy(tmpBTDevice->tcDeviceName,L"");


Retrieve:

int CxxxBluetooth::GetBluetoothAddress(int iIndex, TCHAR* bsAddress)
{
int iError = -100;
if(iIndex < GetDeviceCount())
{
BluetoothDevice *p = GetBluetoothDevice(iIndex); //GetBluetoothDevice: please see above function defination
//bsAddress = p->GetBTAddress(); //cannot do this, value is not copied!
_tcscpy(bsAddress,p->GetBTAddress());
iError = *bsAddress == 0? -1:0;
}
return iError;
}
int CxxxBluetooth::GetBluetoothDeviceName(int iIndex, TCHAR* bsName)
{
int iError = -100;
if(iIndex < GetDeviceCount())
{
BluetoothDevice *p = GetBluetoothDevice(iIndex);
//bsName = p->GetDeviceName();
_tcscpy(bsName,p->GetDeviceName());
iError = *bsName == 0? -1:0;
}
return iError;
}

Storage: MAP in C++ and List in C# (1)

MAP in C++ and List in C#
=====================

(1) List in C#

For C#, if we want to store complicated data, we can use array list like following:
public class General
{
public BluetoothDevice[] DeviceList = new BluetoothDevice[(int)
MaxSearchNumber.MaxDeviceNumer];
...
}

while BluetoothDevice is a Class:

public class BluetoothDevice
{
private string m_Name;
private string m_Address;
private bool m_Paired;
private int m_index;

private string m_type;

public string Type
{
get { return m_type; }
set { m_type = value; }
}
///
/// Constructor
///

public BluetoothDevice()
{
m_Name = "";
m_Address = "";
m_Paired = false;
m_index = -1;
m_type = "";
}

public int Index
{
get { return m_index; }
set { m_index = value; }
}
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}

public string Address
{
get { return m_Address; }
set { m_Address = value; }
}
}

To use:
for (int i = 0; i < m_General.DeviceList.Length; i++)
m_General.DeviceList[i] = new BluetoothDevice();

m_General.DeviceList[m_General.DeviceCounter].Name = somevalue;

Monday, January 26, 2009

typedef struct and struct

There are _3_ ways of using struct. (not two as
mentioned in the previous e-mails). Here are all 3 different ways in a
program, with comments. Hope this clears up confusion.

typedef struct {

int data;
int text;
} S1;
// This will define a typedef for S1, in both C and in C++

struct S2 {
int data;
int text;
};
// This will define a typedef for S2 ONLY in C++, will create error in C.


struct {
int data;
int text;
} S3;
// This will declare S3 to be a variable of type struct.
// This is VERY different from the above two.
// This does not define a type. The above two defined type S1 and S2.

// This tells compiler to allocate memory for variable S3

void main()
{
S1 mine1; // this will work, S1 is a typedef.
S2 mine2; // this will work, S2 is also a typedef.
S3 mine3; // this will NOT work, S3 is not a typedef.


S1.data = 5; // Will give error because S1 is only a typedef.
S2.data = 5; // Will also give error because S1 is only a typedef.
S3.data = 5; // This will work, because S3 is a variable.
}
// That's how they different stuff are handy.


also !!!!!!!!!!! This next bit is important for people who using linked
lists etc.

struct S6 {
S6* ptr;
};
// This works, in C++ only.

typedef struct {
S7* ptr;
} S7;
// Although you would think this does the same thing in C OR C++....

// This DOES NOT work in C nor C++ !!!

Message send/receive between DLL and EXE

1. Message.h

#pragma once
#include "enums.h"
class CMessages
{
public:
static DWORD sm_dwNotificationMessage;
static HWND sm_hWndNotification;
static void PostMessage(NOTIFICATION_
MESSAGES message,LPARAM info=0);
};

//enum.h
enum NOTIFICATION_MESSAGES
{
DISCOVERY_COMPLETE=0x100,
PAIRING_COMPLETE,
PAIRING_ERROR,
DISCOVERY_ERROR,
SERVICE_DISCOVERY_COMPLETE,
SERVICE_DISCOVERY_ERROR,
};

2. Message.cpp

#include "StdAfx.h"
#include "Messages.h"

DWORD CMessages::sm_dwNotificationMessage = RegisterWindowMessage(_T("Notification2A23463D-0006-4ec7-89CC-0A27AA71C4A8"));
HWND CMessages::sm_hWndNotification = NULL;

void CMessages::PostMessage(NOTIFICATION_MESSAGES message,LPARAM info)
{
::PostMessage(CMessages::sm_hWndNotification,CMessages::sm_dwNotificationMessage,message,info);
}

3. Usage:

CMessages::PostMessage(DISCOVERY_ERROR,iError);

Exported functions:

MYLIB_API unsigned WINAPI GetNotificationMessage();
MYLIB_API void WINAPI SetNotificationWindow(HWND hWndNotify) ;

CMessages m_CMessages;
HWND GetNotificationWnd() {return m_CMessages.sm_hWndNotification;}
DWORD GetNotificationMessage() {return m_CMessages.sm_dwNotificationMessage;}
void SetNotificationWindow(HWND hWndNotify) {m_CMessages.sm_hWndNotification = hWndNotify;}

4. In exe, using C#

#region MessageFunctions
//> ---------------------------------------------------------------------------
//> Class: NotificationWindow
//> Purpose: target window for bluetooth device events
//> ---------------------------------------------------------------------------
public class NotificationWindow : MessageWindow
{
// Create an instance of the form.
private Form1 m_FormConnWizard;

// Save a reference to the form so it can
// be notified when messages are received.
public NotificationWindow(Form1 formConnWizard)
{
this.m_FormConnWizard = formConnWizard;
}

// handle window messages from the bluetooth dll
protected override void WndProc(ref Message msg)
{
if (msg.Msg == m_FormConnWizard.GetMyNotificationMessage())
{
// call back to the form to handle this message
m_FormConnWizard.NotificationMessage(msg);
}
else{}
// Call the base WndProc method
// to process any messages not handled.
base.WndProc(ref msg);
}
}
private int GetMyNotificationMessage()
{
return (int)GetNotificationMessage();
}
private void NotificationMessage(Message msg)
{
switch ((uint)msg.WParam)
{
case (uint)NOTIFICATION_MESSAGES.DISCOVERY_COMPLETE:
{
KillSearchingTimer();
MessageBox.Show("DISCOVERY COMPLETE!");
break;
}
case (uint)NOTIFICATION_MESSAGES.DISCOVERY_ERROR:
{
//dx: revise the message
MessageBox.Show("...");
break;
}
case (uint)NOTIFICATION_MESSAGES.SERVICE_DISCOVERY_COMPLETE:
{

break;
}
case (uint)NOTIFICATION_MESSAGES.SERVICE_DISCOVERY_ERROR:
{
//MessageBox.Show(Properties.Resources.strDiscoveryError, "Service Discovery Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
break;
}

}

}
#endregion

public partial class Form1 : Form
{
NotificationWindow m_NotificationWindow;
public Form1()
{
m_NotificationWindow = new NotificationWindow(this);
SetNotificationWindow(m_NotificationWindow.Hwnd);

InitializeComponent();
}
..
}

[DllImport("xxx.dll", EntryPoint = "SetNotificationWindow", SetLastError = true)]
private extern static void SetNotificationWindow(IntPtr hWndNotify);

[DllImport("xxx.dll", EntryPoint = "GetNotificationMessage", SetLastError = true)]
private extern static uint GetNotificationMessage();

Thread Class for C++

1. CBaseThread.h

#pragma once
const DWORD TERMINATION_TIMEOUT = 10000;


class CBaseThread
{
protected:
DWORD m_dwThreadId;
HANDLE m_hTerminateEvent;
HANDLE m_hThread;

protected:
virtual DWORD ThreadProcedure(){return 0;};

public:
bool SetTerminationEvent(HANDLE hTerminationEvent);
bool ShouldTerminateThread();
virtual void TerminateThread();
static DWORD WINAPI ThreadProcedure(PVOID pVoid);
CBaseThread();
virtual ~CBaseThread();
};


2. CBaseThread.cpp

#include "stdafx.h"
#include "CBaseThread.h"

//////////////////////////////
////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBaseThread::CBaseThread()
{
m_dwThreadId = NULL;
m_hTerminateEvent = NULL;
m_hThread = NULL;
m_hTerminateEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
ResetEvent(m_hTerminateEvent);
}
CBaseThread::~CBaseThread()
{
CloseHandle(m_hTerminateEvent);
}

//> ---------------------------------------------------------------------------
//> Function: CBaseThread::ThreadProcedure
//> Params: [in] void *pVoid data passed to the thread procedure
//> Returns: DWORD
//> Purpose: implements the static CBaseThread derived class thread procedure
//> by calling the derived class ThreadProcedure method
//> ---------------------------------------------------------------------------
DWORD CBaseThread::ThreadProcedure(void *pVoid)
{
CBaseThread *pThread = static_cast(pVoid);

return pThread->ThreadProcedure();
}
//> ---------------------------------------------------------------------------
//> Function: CBaseThread::TerminateThread
//> Params: none
//> Returns: void
//> Purpose: call this method to terminate the thread procedure
//> ---------------------------------------------------------------------------
void CBaseThread::TerminateThread()
{
// Signal the thread to terminate itself
SetEvent(m_hTerminateEvent);

// wait for the thread procedure to exit before returning
WaitForSingleObject(m_hThread,TERMINATION_TIMEOUT);

if (NULL != m_hThread)
{
CloseHandle(m_hThread);
}
}
//> ---------------------------------------------------------------------------
//> Function: CBaseThread::ShouldTerminateThread
//> Params: void
//> Returns: bool
//> Purpose: check to see if thread termination was requested
//> ---------------------------------------------------------------------------
bool CBaseThread::ShouldTerminateThread()
{
bool bReturn = false;
if (WAIT_OBJECT_0 == WaitForSingleObject(m_hTerminateEvent,0))
{
bReturn = true;
}
return bReturn;
}

3. Usage:

3.1. CDeviceDiscoveryThread.h

#pragma once
#include "cbasethread.h"
#include
#include
#include
#include
class CGigaBluetooth;
class CDeviceDiscoveryThread : public CBaseThread
{
private:
CGigaBluetooth *m_pCMSBluetooth;
protected:
virtual DWORD ThreadProcedure();

public:
static CDeviceDiscoveryThread *ThreadFactory(CGigaBluetooth *pCMSBluetooth);
CDeviceDiscoveryThread(CGigaBluetooth *pCMSBluetooth);
virtual ~CDeviceDiscoveryThread(void);
};

3.2. CDeviceDiscoveryThread.cpp

#include "StdAfx.h"
#include "GigaBluetooth.h"
#include "DeviceDiscoveryThread.h"

CDeviceDiscoveryThread::CDeviceDiscoveryThread(CGigaBluetooth *pCMSBluetooth)
{
ASSERT(NULL != pCMSBluetooth);
m_pCMSBluetooth = pCMSBluetooth;
}

CDeviceDiscoveryThread::~CDeviceDiscoveryThread(void)
{
}
//> ---------------------------------------------------------------------------
//> Function: ThreadFactory
//> Params: MSBluetooth *pMSBluetooth
//> Returns: CDeviceDiscoveryThread *
//> Purpose: creates CDeviceDiscoveryThread threads
//> ---------------------------------------------------------------------------
CDeviceDiscoveryThread * CDeviceDiscoveryThread::ThreadFactory(CGigaBluetooth *pCMSBluetooth)
{
CDeviceDiscoveryThread *pCDeviceDiscoveryThread = new CDeviceDiscoveryThread(pCMSBluetooth);

if (NULL != pCDeviceDiscoveryThread)
{
pCDeviceDiscoveryThread->m_hThread = ::CreateThread(NULL,0,CBaseThread::ThreadProcedure,pCDeviceDiscoveryThread,0,&pCDeviceDiscoveryThread->m_dwThreadId);
}
return pCDeviceDiscoveryThread;
}

//> ---------------------------------------------------------------------------
//> Function: ThreadProcedure
//> Params: none
//> Returns: DWORD
//> Purpose: implements the thread procedure
//> ---------------------------------------------------------------------------
DWORD CDeviceDiscoveryThread::ThreadProcedure()
{
Sleep(5000); //test
CMessages::PostMessage(DISCOVERY_COMPLETE);
return 0;
}

3.3.

CDeviceDiscoveryThread *m_pCDeviceDiscoveryThread;
m_pCDeviceDiscoveryThread = CDeviceDiscoveryThread::ThreadFactory(this);
return NULL != m_pCDeviceDiscoveryThread ? true : false;

Friday, January 23, 2009

Create a MFC support (CString) win32 dll using EVC++

Step 1: EVC++
New project->WinCE Dynamic-link library->Simple Window CE DLL ->


Step 2: Add header aaa.h file:

#ifdef TWOTECHBT_EXPORTS //cannot use numbers here like "2TBT_EXPORTS" will get fatal error C1016: #if[n]def expected an identifier"
#define TWOTECHBTLIB_API __declspec(dllexport)
#else
#define TWOTECHBTLIB_API __declspec(dllimport)
#endif
// Use "C" naming convention for methods.

#ifdef __cplusplus
extern "C" {
#endif


TWOTECHBTLIB_API BOOL WINAPI Initialize();
TWOTECHBTLIB_API BOOL WINAPI Deinitialize();
TWOTECHBTLIB_API BOOL WINAPI GetLocalBluetoothAddressName(
TCHAR *bsAddress, TCHAR *bsName);


#ifdef __cplusplus
}
#endif

Step 3: Settings->C/C++->Preprocessor->Add "TWOTECHBTLIB"

Step 4: aaa.cpp file: may need use following to replace default dllmain

BOOL APIENTRY Dllentry( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

Step 5: in order to use CString, add following to stdafx.h


#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers

#include // MFC core and standard components
#include // MFC extensions

#if defined(_WIN32_WCE) && (_WIN32_WCE >= 211) && (_AFXDLL)
#include // MFC support for Internet Explorer 4 Common Controls
#endif

#ifndef _AFX_NO_AFXCMN_SUPPORT
#include // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT

error LNK2005: DllMain already defined in corelibc.lib(dllmain.obj)

After conversion, I got following errors:

Error 1 error LNK2005: DllMain already defined in corelibc.lib(dllmain.obj) uafxcwd.lib
Error 2 fatal error LNK1169: one or more multiply defined symbols found JETTce 5.0

Solution:

Configuration Properties->Linker->Input->Additional Dependency: uncheck "inherited from parent or project defaults" checkbox.

Wednesday, January 21, 2009

How to play a sound

http://www.bobpowell.net/playsnd.htm

Windows Forms classes are bereft of a simple way to play sounds. This glaring oversight is however easily rectified with a little bit of platform-invoke interop.

There are a couple of ways to do this. The first method requires the multimedia API sndPlaySnd and a few constants defined but once this is done you can add sounds to your Windows Forms applications easily. This API is a subset of the PlaySound API which can also be accessed through interop.

First you need to import the sndPlaySound or PlaySound API from the multimedia DLL. Interop enables us to import these signatures in a number of ways. For example, in some configurations the sndPlaySound method can be passed the address of a .WAV sound stored in memory but C# and VB are a bit finicky about casting strings to pointers so we can overload the p/invoke import statement to provide a version of the method signature that accepts an IntPtr instead of a string.

[DllImport("Winmm.dll")]

static extern int sndPlaySound(string lpszSound, int fuSound);

[DllImport("Winmm.dll")]

static extern int sndPlaySound(IntPtr ptr, int fuSound);

_

Shared Function sndPlaySound(lpszSound As String, fuSound As Integer) As Integer

_

Shared Function sndPlaySound(ptr As IntPtr, fuSound As Integer) As Integer

The constants required for the multimedia functions can be converted from the old C++ header files.

enum soundConstants

{

SND_SYNC = 0x0000, /* play synchronously (default) */

SND_ASYNC = 0x0001, /* play asynchronously */

SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */

SND_MEMORY = 0x0004, /* pszSound points to a memory file */

SND_LOOP = 0x0008, /* loop the sound until next sndPlaySound */

SND_NOSTOP = 0x0010, /* don't stop any currently playing sound */

SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */

SND_ALIAS = 0x00010000, /* name is a registry alias */

SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */

SND_FILENAME = 0x00020000, /* name is file name */

SND_RESOURCE = 0x00040004, /* name is resource name or atom */

SND_PURGE = 0x0040, /* purge non-static events for task */

SND_APPLICATION = 0x0080, /* look for application specific association */

}

Enum soundConstants

SND_SYNC = &H0 ' play synchronously (default)

SND_ASYNC = &H1 ' play asynchronously

SND_NODEFAULT = &H2 ' silence (!default) if sound not found

SND_MEMORY = &H4 ' pszSound points to a memory file

SND_LOOP = &H8 ' loop the sound until next sndPlaySound

SND_NOSTOP = &H10 ' don't stop any currently playing sound

SND_NOWAIT = &H2000 ' don't wait if the driver is busy

SND_ALIAS = &H10000 ' name is a registry alias

SND_ALIAS_ID = &H110000 ' alias is a predefined ID

SND_FILENAME = &H20000 ' name is file name

SND_RESOURCE = &H40004 ' name is resource name or atom

SND_PURGE = &H40 ' purge non-static events for task

SND_APPLICATION = &H80 ' look for application specific association

End Enum 'soundConstants

Then, to play a sound simply call the method and provide the sound file.

sndPlaySound(@"C:\Sounds\Explosion1.wav", (int)soundConstants.SND_ASYNC);

sndPlaySound("C:\Sounds\Explosion1.wav", CInt(soundConstants.SND_ASYNC))

You can embed a .wav file into your application by adding it to the application and then setting the build action to "embedded resource" in the solution item properties. This enables you to ship an application with the sounds built into the resources and so there are no extra files to distribute.

Getting at the file is a little more complex than simply nominating the filename an must be done using a Garbage Collector handle (GCHandle) and a pinned array. The following listing assumes a file has been embedded in the resources and is accessible as a stream.

Stream s=this.GetType().Assembly.GetManifestResourceStream("PlaySound.win_1.wav");

byte[] buffer=new byte[s.Length];

s.Read(buffer,0,(int)s.Length);

GCHandle h=GCHandle.Alloc(buffer);

IntPtr ptr=Marshal.UnsafeAddrOfPinnedArrayElement(buffer,0);

sndPlaySound(ptr,(int)soundConstants.SND_MEMORY | (int)soundConstants.SND_ASYNC);

h.Free();

Dim s As Stream = Me.GetType().Assembly.GetManifestResourceStream("PlaySoundVB.win_1.wav")

Dim buffer(s.Length) As Byte

s.Read(buffer, 0, CInt(s.Length))

Dim h As GCHandle = GCHandle.Alloc(buffer)

Dim ptr As IntPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0)

sndPlaySound(ptr, CInt(soundConstants.SND_MEMORY) Or CInt(soundConstants.SND_ASYNC))

-----------------------------------------------------------------------------------------

  1. // Include file
  2. #include "mmsystem.h"
  3. // Link to this library
  4. #pragma comment( lib, "winmm.lib" )
  5. int main( int argc, char **argv )
  6. {
  7. // Will block till the whole file is played, use SND_ASYNC to play asynchronously
  8. sndPlaySound( "c://windows//media//ding.wav", SND_SYNC );
  9. // Play for ever, should use SND_ASYNC
  10. sndPlaySound( "c://windows//media//ding.wav", SND_ASYNC|SND_LOOP );
  11. // Sleep for 5 seconds
  12. Sleep( 5000 );
  13. // Enough is enough stop making that stupid noise
  14. sndPlaySound( NULL, SND_SYNC );
  15. return 0;
  16. }// End main

Thursday, January 15, 2009

How to create REG_MULTI_SZ and REG_BINARY in C++ and C#

1. REG_MULTI_SZ

C#:

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();
}

C++: (not tested yet!)

HKEY hKey = NULL;
DWORD dataType = REG_MULTI_SZ;
LONG retVal = 0;
LONG ConfigurationStringSize = 512;
WCHAR *ConfigurationString = new WCHAR[ConfigurationStringSize];
memset(ConfigurationString,'\0',512);

// Build the configuration string.
wcscat(ConfigurationString, Location);
wcscat(ConfigurationString, TEXT("$"));

wcscat(ConfigurationString, LocalCalls);
wcscat(ConfigurationString, TEXT("$"));

wcscat(ConfigurationString, LongDistanceCalls);
wcscat(ConfigurationString, TEXT("$"));

wcscat(ConfigurationString, InternationalCalls);
wcscat(ConfigurationString, TEXT("$"));

wcscat(ConfigurationString, AreaCode);
wcscat(ConfigurationString, TEXT("$"));

wcscat(ConfigurationString, DisableCallWaitingSequence);
wcscat(ConfigurationString, TEXT("$"));

wcscat(ConfigurationString, CountryCode);
wcscat(ConfigurationString, TEXT("$"));

wcscat(ConfigurationString, ToneOrPulse);
wcscat(ConfigurationString, TEXT("$"));

// Format the string correctly.
int ConfigStringLen = wcslen(ConfigurationString);
for(int x = 0; x < ConfigStringLen; ++x)
{
if(ConfigurationString[x] == '$')
ConfigurationString[x] = '\0';
}

// Open the registry key.
retVal = RegOpenKeyEx(HKEY_CURRENT_USER , TEXT("ControlPanel\\Dial\\Locations"), 0, KEY_READ, &hKey);
if(retVal != ERROR_SUCCESS)
{
delete [] ConfigurationString;
return false;
}

// Set the value of the key.
retVal = RegSetValueEx(hKey, KeyName, NULL, dataType, (PBYTE)ConfigurationString, ConfigurationStringSize);
RegCloseKey(hKey);

delete [] ConfigurationString;

return retVal != ERROR_SUCCESS ? false : true;
-------------------------------------------------------------------------------
2. REG_BINARY

C#:
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;
}
}

RegistryKey rk = Registry.LocalMachine;
using (RegistryKey rk1 = rk.CreateSubKey("\\Software\\dx"))
{
byte[] bA = new byte[8];
if (GetBinaryBluetoothAddress("00:03:c9:56:0c:EE", ref bA))
{
rk1.SetValue("dxaddress", bA);
MessageBox.Show("Good!");
}
else
MessageBox.Show("Failed!");

rk1.Close();
}
rk.Close();

C++:

unsigned char epwd[9];

//set epwd here

RegSetValueEx(hKey,"keyname",0,REG_BINARY,(LPBYTE)&epwd,8);

Tuesday, January 13, 2009

How to set Bluetooth ActiveSync Connection

Method 1: use ras to setup the dialing parameters
SetActiveSyncDialingParameters();


private void SetActiveSyncDialingParameters
()
{
int dwSize;
char[] bSP = new char[512];
RASENTRY RasEntry;
RasEntry = new RASENTRY();

RASDIALPARAMS RasDialParams;
RasDialParams = new RASDIALPARAMS();

dwSize = Marshal.SizeOf(typeof(RASENTRY));
RasEntry.dwSize = dwSize;
uint temp = 512;


//MessageBox.Show("Attempting RASGetEntries");
uint dwGetEntry = 0;
dwGetEntry = RasConnection.RasGetEntryProperties("", "",
ref RasEntry, ref dwSize, bSP, ref temp);
if (dwGetEntry >= 1)
{
MessageBox.Show("Unable to retrieve information:" + dwGetEntry.ToString()); //passed after readjust struc
//return;

}
///* RASENTRY 'dwfOptions' bit flags.
//*/
//#define RASEO_UseCountryAndAreaCodes 0x00000001
//#define RASEO_SpecificIpAddr 0x00000002
//#define RASEO_SpecificNameServers 0x00000004
//#define RASEO_IpHeaderCompression 0x00000008
//#define RASEO_RemoteDefaultGateway 0x00000010
//#define RASEO_DisableLcpExtensions 0x00000020
//#define RASEO_TerminalBeforeDial 0x00000040
//#define RASEO_TerminalAfterDial 0x00000080
//#define RASEO_ModemLights 0x00000100
//#define RASEO_SwCompression 0x00000200
//#define RASEO_RequireEncryptedPw 0x00000400
//#define RASEO_RequireMsEncryptedPw 0x00000800
//#define RASEO_RequireDataEncryption 0x00001000
//#define RASEO_NetworkLogon 0x00002000
//#define RASEO_UseLogonCredentials 0x00004000
//#define RASEO_PromoteAlternates 0x00008000
//#define RASEO_SecureLocalFiles 0x00010000
//#define RASEO_DialAsLocalCall 0x00020000

//#define RASEO_ProhibitPAP 0x00040000
//#define RASEO_ProhibitCHAP 0x00080000
//#define RASEO_ProhibitMsCHAP 0x00100000
//#define RASEO_ProhibitMsCHAP2 0x00200000
//#define RASEO_ProhibitEAP 0x00400000
//#define RASEO_PreviewUserPw 0x01000000
//#define RASEO_NoUserPwRetryDialog 0x02000000
//#define RASEO_CustomScript 0x80000000

//RasEntry.dwfOptions &= ~(RASEO_SpecificNameServers|RASEO_SpecificIpAddr|
// RASEO_IpHeaderCompression|RASEO_SwCompression|RASEO_UseCountryAndAreaCodes);

RasEntry.dwfOptions &= ~(0x00000004 | 0x00000002 | 0x00000008 | 0x00000200 | 0x00000001);

RasEntry.szDeviceName = "BluetoothSYN";
RasEntry.szDeviceType = "direct";

dwGetEntry = RasConnection.RasSetEntryProperties(null, "Bluetooth", ref RasEntry, dwSize, null, 0);
if (dwGetEntry >= 1)
{
MessageBox.Show("Unable to RasSetEntryProperties:" + dwGetEntry.ToString()); //621;passed after change first parameter from "" to null
//return;
}

RasDialParams.dwSize = (int )Marshal.SizeOf (typeof(RASDIALPARAMS));
RasDialParams.szEntryName = "Bluetooth";
RasDialParams.szUserName = "guest";
RasDialParams.szPassword = "guest";


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

Method 2: directly go to registry to set up ras phone book
RASPHONEENTRY rs = new RASPHONEENTRY();
#if (UseCOM1)
rs.CreateRasEntry("BluetoothCOM1", 1, ref m_iOldValue1, ref m_sOldValue2);
#else
rs.CreateRasEntry("BluetoothCOM2", 2, ref m_iOldValue1, ref m_sOldValue2);
#endif
//timer start
m_ActiveSyncTimer = new System.Windows.Forms.Timer();
m_ActiveSyncTimer.Tick += new EventHandler(ActiveSyncTimerEventProcessor);
m_ActiveSyncTimer.Interval = 10000;
m_ActiveSyncTimer.Enabled = true;

rs.RunActiveSyncConnection();


void ActiveSyncTimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
//maybe kill repllog.exe???
//MyProcess mp = new MyProcess();
//if (mp.FindProcess("repllog.exe"))
// mp.KillProcess("repllog.exe");


RegistryKey rk = Registry.CurrentUser;
using (RegistryKey rk1 = rk.OpenSubKey("\\ControlPanel\\Comm", true))
{
rk1.SetValue("AutoCnct", m_iOldValue1);
rk1.SetValue("Cnct", m_sOldValue2);
rk1.Close();
}
rk.Close();

}
----------------------From Attched RasPhoneEntry.cs------------------

public Byte[] byteDevCfgCOM1 = {
0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x10,0x03,0x00,0x00,0x00,0xC2,0x01,0x00,
....
}


//step 1: On device, Start->Settings->Control Panel. Choose "Network and Dial-up Connections". Click "Make New Connections".
//Input "com2", "Direct","Cable on COM2:". Click "Configure", set "115200" etc. "Finish"
///
///
//step 2: Use following code to read manual created ras phone entry: PC-115K for COM1 and com2 for COM2.
///
/// GenerateRasEntryFile
///

public void GenerateRasEntryFile()
{
RegistryKey rk = Registry.CurrentUser;
StreamWriter sw = new StreamWriter("\\ras.txt");
using (RegistryKey rk1 = rk.CreateSubKey("\\Comm\\RasBook\\PC-115K"))
{
sw.WriteLine("");
sw.WriteLine("//\\Comm\\RasBook\\PC-115K");
sw.WriteLine("//1. DevCfg");

sw.WriteLine("Byte[] m_byteDevCfg = {");
Byte[] DevCfg = (Byte[])rk1.GetValue("DevCfg");
int i = 1;
foreach (Byte b in DevCfg)
{
if (i != 8)
{
sw.Write("0x" + b.ToString("X2"));
sw.Write(",");
i++;
}
else
{
sw.WriteLine("0x" + b.ToString("X2") + ",");
i = 1;
}
}
sw.WriteLine("};");
sw.WriteLine("");
sw.WriteLine("");
i = 1;

sw.WriteLine("//2. Entry");
sw.WriteLine("Byte[] m_byteEntry = {");
Byte[] Entry = (Byte[])rk1.GetValue("Entry");
foreach (Byte b in Entry)
{
if (i != 8)
{
sw.Write("0x" + b.ToString("X2"));
sw.Write(",");
i++;
}
else
{
sw.WriteLine("0x" + b.ToString("X2") + ",");
i = 1;
}
}
sw.WriteLine("};");
rk1.Close();
}
using (RegistryKey rk1 = rk.CreateSubKey("\\Comm\\RasBook\\com2"))
{
sw.WriteLine("");
sw.WriteLine("//\\Comm\\RasBook\\com2");
sw.WriteLine("//1. DevCfg");
sw.WriteLine("Byte[] m_byteDevCfg = {");
Byte[] DevCfg = (Byte[])rk1.GetValue("DevCfg");
int i = 1;
sw.WriteLine("1. DevCfg");
foreach (Byte b in DevCfg)
{
if (i != 8)
{
sw.Write("0x" + b.ToString("X2"));
sw.Write(",");
i++;
}
else
{
sw.WriteLine("0x" + b.ToString("X2") + ",");
i = 1;
}
}
sw.WriteLine("};");
sw.WriteLine("");
sw.WriteLine("");
sw.WriteLine("//2. Entry");
i = 1;
sw.WriteLine("Byte[] m_byteEntry = {");
Byte[] Entry = (Byte[])rk1.GetValue("Entry");
foreach (Byte b in Entry)
{
if (i != 8)
{
sw.Write("0x" + b.ToString("X2"));
sw.Write(",");
i++;
}
else
{
sw.WriteLine("0x" + b.ToString("X2") + ",");
i = 1;
}
}
sw.WriteLine("};");
sw.Close();
rk1.Close();
}
}

//step 3: Based on the entry file: ras.txt to create your own Bluetooth ras phone entry with baud rate 115200 and COM1 or 2.
//Why need this: because I can create ras entry using RasGetEntryProperties,RasSetEntryProperties,RasSetEntryDialParams, but it is very hard to
//set baud rate to 115200.
///
/// CreateRasEntry: create your own Bluetooth ras phone entry with baud rate 115200 and COM1 or 2.
///

///
param>
///
///
///
public void CreateRasEntry(string sNewRasEntryName, int iPort, ref int iOldValue1, ref string sOldValue2)
{
RegistryKey rk = Registry.CurrentUser;
using (RegistryKey rk2 = rk.CreateSubKey("\\Comm\\RasBook\\" + sNewRasEntryName))
{
RASPHONEENTRY rs = new RASPHONEENTRY();
if (iPort == 1)
{
rk2.SetValue("DevCfg", rs.byteDevCfgCOM1);
rk2.SetValue("Entry", rs.byteEntryCOM1);
}
else
{
rk2.SetValue("DevCfg", rs.byteDevCfgCOM2);
rk2.SetValue("Entry", rs.byteEntryCOM2);
}
rk2.Close();
}

using (RegistryKey rk1 = rk.CreateSubKey("\\ControlPanel\\Comm"))
{
iOldValue1 = (int)rk1.GetValue("AutoCnct");
rk1.SetValue("AutoCnct", 1);
sOldValue2 = (string)rk1.GetValue("Cnct");
rk1.SetValue("Cnct", sNewRasEntryName); //need to use this specially already created Bluetooth to connect
rk1.Close();
}
rk.Close();

rk = Registry.LocalMachine;
using (RegistryKey rk1 = rk.CreateSubKey("\\ExtModems\\bluetooth_syn"))
{
rk1.SetValue("port", iPort); //might be 2
rk1.Close();
}
rk.Close();
}

//step 4: run repllog.exe to start active connection
///
/// Run ActiveSync Connection
///

public void RunActiveSyncConnection()
{
//run repllog.exe
//ProcessStartInfo psi = new ProcessStartInfo("\\Windows\\repllog.exe","");
//Process.Start(psi);
Functions f = new Functions();
f.OpenExternalProgram("repllog.exe", "AppRunAtRs232Detect"); //activesync auto start when detects serial port connection
}
----------------------From Attched RasConnection.cs------------------

public enum RasFieldSizeConstants
{
RAS_MaxDeviceType = 16,
RAS_MaxPhoneNumber = 128,
RAS_MaxIpAddress = 15,
RAS_MaxIpxAddress = 21,
RAS_MaxEntryName = 20,
RAS_MaxDeviceName = 128,
RAS_MaxCallbackNumber = 48,
RAS_MaxParamKey = 32,
RAS_MaxParamValue = 128,

RAS_MaxAreaCode = 10,
RAS_MaxPadType = 32,
RAS_MaxX25Address = 200,
RAS_MaxFacilities = 200,
RAS_MaxUserData = 200,
RAS_MaxReplyMessage = 1024,
RAS_MaxDnsSuffix = 256,

MAX_PATH = 260,

UNLEN = 256,
PWLEN = 256,
DNLEN = 15
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct RASIPADDR
{
byte a;
byte b;
byte c;
byte d;
}

//Public Enum RasEntryOptions
// RASEO_UseCountryAndAreaCodes = &H1
// RASEO_SpecificIpAddr = &H2
// RASEO_SpecificNameServers = &H4
// RASEO_IpHeaderCompression = &H8
// RASEO_RemoteDefaultGateway = &H10
// RASEO_DisableLcpExtensions = &H20
// RASEO_TerminalBeforeDial = &H40
// RASEO_TerminalAfterDial = &H80
// RASEO_ModemLights = &H100
// RASEO_SwCompression = &H200
// RASEO_RequireEncryptedPw = &H400
// RASEO_RequireMsEncryptedPw = &H800
// RASEO_RequireDataEncryption = &H1000
// RASEO_NetworkLogon = &H2000
// RASEO_UseLogonCredentials = &H4000
// RASEO_PromoteAlternates = &H8000
// RASEO_SecureLocalFiles = &H10000
// RASEO_RequireEAP = &H20000
// RASEO_RequirePAP = &H40000
// RASEO_RequireSPAP = &H80000
// RASEO_Custom = &H100000
// RASEO_PreviewPhoneNumber = &H200000
// RASEO_SharedPhoneNumbers = &H800000
// RASEO_PreviewUserPw = &H1000000
// RASEO_PreviewDomain = &H2000000
// RASEO_ShowDialingProgress = &H4000000
// RASEO_RequireCHAP = &H8000000
// RASEO_RequireMsCHAP = &H10000000
// RASEO_RequireMsCHAP2 = &H20000000
// RASEO_RequireW95MSCHAP = &H40000000
// RASEO_CustomScript = &H80000000
// End Enum

///* RASENTRY 'dwfNetProtocols' bit flags. (session negotiated protocols)
//*/
//#define RASNP_NetBEUI 0x00000001 // Negotiate NetBEUI
//#define RASNP_Ipx 0x00000002 // Negotiate IPX
//#define RASNP_Ip 0x00000004 // Negotiate TCP/IP


///* RASENTRY 'dwFramingProtocols' (framing protocols used by the server)
//*/
//#define RASFP_Ppp 0x00000001 // Point-to-Point Protocol (PPP)
//#define RASFP_Slip 0x00000002 // Serial Line Internet Protocol (SLIP)
//#define RASFP_Ras 0x00000004 // Microsoft proprietary protocol


///* RASENTRY 'szDeviceType' strings
//*/
//#define RASDT_Direct TEXT("direct") // Direct Connect (WINCE Extension)
//#define RASDT_Modem TEXT("modem") // Modem
//#define RASDT_Isdn TEXT("isdn") // ISDN
//#define RASDT_X25 TEXT("x25") // X.25
//#define RASDT_Vpn TEXT("vpn") // PPTP
//#define RASDT_PPPoE TEXT("PPPoE") // PPPoE


//http://msdn.microsoft.com/en-us/library/aa920252.aspx
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct RASENTRY
{
public int dwSize;
public int dwfOptions;
//
// Location/phone number.
//
public int dwCountryID;
public int dwCountryCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxAreaCode + 1)]
public string szAreaCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxPhoneNumber + 1)]
public string szLocalPhoneNumber;
public int dwAlternateOffset;
//
// PPP/Ip
//
public RASIPADDR ipaddr;
public RASIPADDR ipaddrDns;
public RASIPADDR ipaddrDnsAlt;
public RASIPADDR ipaddrWins;
public RASIPADDR ipaddrWinsAlt;
//
// Framing
//
public int dwFrameSize;
public int dwfNetProtocols;
public int dwFramingProtocol;
//
// Scripting
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]//MAX_PATH
public string szScript;
//
// AutoDial
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]//MAX_PATH
public string szAutodialDll;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]//MAX_PATH
public string szAutodialFunc;
//
// Device
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxDeviceType + 1)]
public string szDeviceType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxDeviceName + 1)]
public string szDeviceName;
//
// X.25
//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxPadType + 1)]
public string szX25PadType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxX25Address + 1)]
public string szX25Address;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxFacilities + 1)]
public string szX25Facilities;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxUserData + 1)]
public string szX25UserData;
public int dwChannels;
//
// Reserved
//
public int dwReserved1;
public int dwReserved2;

//it is winCE500 dx
public int dwCustomAuthKey;

}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct RASDIALPARAMS
{
public int dwSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxEntryName + 1)]
public string szEntryName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxPhoneNumber + 1)]
public string szPhoneNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.RAS_MaxCallbackNumber + 1)]
public string szCallbackNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.UNLEN + 1)]
public string szUserName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.PWLEN + 1)]
public string szPassword;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)RasFieldSizeConstants.DNLEN + 1)]
public string szDomain;
//public uint dwSubEntry; //no need for WinCE
//public IntPtr dwCallbackId; //no need for WinCE
}

class RasConnection
{

[DllImport("coredll.dll", CharSet = CharSet.Auto)]
static extern uint RasDial(
[In]RASDIALEXTENSIONS lpRasDialExtensions,
[In]string lpszPhonebook,
[In]RASDIALPARAMS lpRasDialParams,
uint dwNotifierType,
Delegate lpvNotifier,
ref IntPtr lphRasConn);

//[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);

[DllImport("coredll.dll")]
public static extern uint RasGetEntryProperties(string
lpszPhoneBook, string szEntry, ref RASENTRY lpEntry, ref int dwsize,
char[] lpb, ref uint lpdwSize);

//public static extern uint RasGetEntryProperties(string
//lpszPhoneBook, string szEntry, ref RASENTRY lpEntry, ref int dwsize,
//int lpbDeviceInfo, int lpdwSize);

[DllImport("coredll.dll")]
public static extern uint RasSetEntryProperties(string
lpszPhoneBook, string szEntry, ref RASENTRY lpEntry, int dwEntrySize,
char[] lpb, int dwSize);

[DllImport("coredll.dll")]
public static extern uint RasSetEntryDialParams(string
lpszPhoneBook, ref RASDIALPARAMS lpRasDialParams, bool
fRemovePassword);

[DllImport("coredll.dll", SetLastError = true)]
public static extern uint RasGetEntryDialParams(
string lpszPhonebook,
[In, Out] ref RASDIALPARAMS lprasdialparams,
out bool lpfPassword);
//[DllImport("coredll.dll")]
//public static extern uint RasSetEntryDialParams(string
//lpszPhoneBook, ref RASDIALPARAMS lpRasDialParams, bool
//fRemovePassword);


[StructLayout(LayoutKind.Sequential)]
internal class RasEapInfo
{
public Int32 dwSize = Marshal.SizeOf(typeof(RasEapInfo));
public Byte[] pbEapInfo = null;
}

[StructLayout(LayoutKind.Sequential)]
internal class RASDIALEXTENSIONS
{
public readonly int dwSize = Marshal.SizeOf(typeof(RASDIALEXTENSIONS));
public uint dwfOptions = 0;
public int hwndParent = 0;
public int reserved = 0;
public int reserved1 = 0;
public RasEapInfo RasEapInfo = new RasEapInfo();
}
//public void Connect()
//{
// // Define the dial parameters
// RasDialParams parms = new RasDialParams();
// parms.szDomain = this.Domain;
// parms.szUserName = this.UserName;
// parms.szPassword = this.Password;
// parms.szEntryName = this.PhonebookEntry;

// System.UInt32 retVal =
// RasDial(null, null, dialParms, 0, null, ref RasConnectionHandle);
//}
}