Monday, January 26, 2009

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