Showing posts with label ActiveSync. Show all posts
Showing posts with label ActiveSync. Show all posts

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

Thursday, September 25, 2008

Copying files from Desktop to a CE device

http://blogs.msdn.com/harsh/archive/2008/05/08/copying-files-from-desktop-to-a-ce-device.aspx

So I have this problem, where I need to create a tool that creates a folder with a bunch of files on the PC and then copies all these files over to a CE device. The method of choice here was via ActiveSync over USB. One of the design goals was to be able to copy these files to a number of devices simultaneously. However, research revealed that this is not really possible since, activesync only supports one active connection at a time. So much for the great idea.

So now we are faced with this problem of copying files over to the device over ActiveSync. Since the app had a lot of GUI, I created that in C#. The .NET framework exposes excellent API for file manipulation based on paths. The problem with ActiveSync connections is when the device is cradled, there is no drive letter associated with the connection. So all device paths are then \My Documents\ or \Program Files\ etc.

This creates a problem as far as the File manipulation API in System.IO. Since these methods accept relative as well as fully qualified paths, any path like the above, would be treated as a relative path and not a fully qualified path, thereby causing a lot of grief.

The only way to get past this so far has been to use RAPI.

RAPI stands for Remote Application Programming Interface, and was created ages ago with the first wave of activesync and windows mobile products.

RAPI has some documentation on MSDN at: http://msdn.microsoft.com/en-us/library/aa458022.aspx

However since RAPI is a native API, almost all the documentation is geared towards native implementation.

After searching the intertubes for a suitable solution, I couldn’t find one that was recent, and that was guaranteed to work.

Below is the solution:




using System;
using System.Threading;
using System.Runtime.InteropServices;
using COMTYPES = System.Runtime.InteropServices.ComTypes;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Logger = Microsoft.MobileDevices.Tools.Utilities.Logger;


namespace Microsoft.MobileDevices.Tools.RAPILibrary
{
public class RAPILibrary
{
# region RAPI EXTERN
// -------------------------------------------------------
// RAPI.DLL Definitions
// -------------------------------------------------------

public const int MAX_PATH = 260;
public const uint MAXDWORD = 0xFFFFFFFF;
public const uint S_OK = 0;

public struct RAPIINIT
{
public int cbSize;
public IntPtr heRapiInit;
public int hrRapiInit;
};

// From WINBASE.H -- for CeCreateFile
public enum ACCESS : uint
{
READ = 0x80000000,
WRITE = 0x40000000,
}
// From WINBASE.H -- for CeCreateFile
public enum SHARE
{
READ = 0x00000001,
WRITE = 0x00000002,
}
// From WINBASE.H -- for CeCreateFile
public enum ACTION
{
CREATE_NEW = 1,
CREATE_ALWAYS = 2,
OPEN_EXISTING = 3,
OPEN_ALWAYS = 4,
TRUNCATE_EXISTING = 5
}

// From WINBASE.H -- for CeCreateFile
public enum FILEFLAGATT : uint
{
ATTRIBUTE_READONLY = 0x00000001,
ATTRIBUTE_HIDDEN = 0x00000002,
ATTRIBUTE_SYSTEM = 0x00000004,
ATTRIBUTE_DIRECTORY = 0x00000010,
ATTRIBUTE_ARCHIVE = 0x00000020,
ATTRIBUTE_INROM = 0x00000040,
ATTRIBUTE_ENCRYPTED = 0x00000040,
ATTRIBUTE_NORMAL = 0x00000080,
ATTRIBUTE_TEMPORARY = 0x00000100,
ATTRIBUTE_SPARSE_FILE = 0x00000200,
ATTRIBUTE_REPARSE_POINT = 0x00000400,
ATTRIBUTE_COMPRESSED = 0x00000800,
ATTRIBUTE_OFFLINE = 0x00001000,
ATTRIBUTE_ROMSTATICREF = 0x00001000,
ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
ATTRIBUTE_ROMMODULE = 0x00002000,
FLAG_WRITE_THROUGH = 0x80000000,
FLAG_OVERLAPPED = 0x40000000,
FLAG_NO_BUFFERING = 0x20000000,
FLAG_RANDOM_ACCESS = 0x10000000,
FLAG_SEQUENTIAL_SCAN = 0x08000000,
FLAG_DELETE_ON_CLOSE = 0x04000000,
FLAG_BACKUP_SEMANTICS = 0x02000000,
FLAG_POSIX_SEMANTICS = 0x01000000,
}


///
/// Closes handle passed in
///

/// handle to be closed
///
[DllImport("rapi.DLL", CharSet = CharSet.Unicode)]
public static extern int CeCloseHandle(IntPtr hObject);

///
/// Creates file on device
///

/// path of file
/// Read/Write
/// Share mode
///
/// File creation options
/// Flags and attributes
///
/// pointer to the created file
[DllImport("rapi.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr CeCreateFile(string lpFileName, ACCESS dwDesiredAccess, SHARE dwShareMode, int Res1, ACTION dwCreationDisposition, FILEFLAGATT dwFlagsAndAttributes, int Res2);

///
/// Reads the file
///

/// handle to the file
/// buffer to copy data to
/// file size to read
/// file size read
///
///
[DllImport("rapi.DLL", CharSet = CharSet.Unicode)]
public static extern int CeReadFile(IntPtr hFile, IntPtr lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, int Reserved);

///
/// Writes file to device
///

/// handle of file to write to
/// data to write
/// length of buffer
/// length of file on device
///
///
[DllImport("rapi.DLL", CharSet = CharSet.Unicode)]
public static extern int CeWriteFile(IntPtr hFile, IntPtr lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, int Reserved);

///
/// Copies file from desktop to device
///

/// Full path of file on the desktop including filename
/// Path of file name on the device. '\' denotes root
public static void CopyFiletoDevice(string deskFile, string devFilePath)
{
try
{
int numTries=0;
// Verify file exists on desktop
FileInfo fInfo = new FileInfo(deskFile);
if (fInfo.Exists)
{
IntPtr devFileHandle;
// create a file on the device
do // force valid handle in the loop
{
devFileHandle = CeCreateFile(devFilePath, ACCESS.READ | ACCESS.WRITE, SHARE.READ | SHARE.WRITE, 0, ACTION.CREATE_ALWAYS, FILEFLAGATT.ATTRIBUTE_NORMAL, 0);
if (devFileHandle.ToInt32() < 0)
{
CeCloseHandle(devFileHandle);
}
} while (devFileHandle.ToInt32() < 0);


// read file from desktop into a byte buffer
Byte[] buffer;
ReadFileAsBinary(deskFile, out buffer);

int numBytesWritten = 0;
unsafe
{
fixed(byte* bufferPtr = buffer)
{
int retVal = CeWriteFile(devFileHandle, (IntPtr)(bufferPtr), (int)fInfo.Length, ref numBytesWritten, 0);
if (retVal == 0)
{
throw new IOException("RAPILibrary:CopyFileToDevice() Error Writing file on device. " + CeGetLastError().ToString());
}
}
}

// close handles
CeCloseHandle(devFileHandle);
}
else
{
Logger.WriteLog("RAPILibrary:CopyFileToDevice() File does not exist on desktop: " + deskFile);
}

}
catch (IOException ioEx)
{
Logger.WriteLog(ioEx.Message);
}
catch (Exception ex)
{
Logger.WriteLog(ex.ToString());
}
}

///
/// Reads file and returns byte[]
///

/// Full path of file
/// byte array for file data
private static void ReadFileAsBinary(string path, out Byte[] buffer)
{
Logger.WriteLog("RAPILibrary:ReadFileAsBinary() Reading the file " + path);
FileInfo fInfo = new FileInfo(path);
long fileLength = fInfo.Length;
buffer = new Byte[fileLength];
FileStream fs = fInfo.OpenRead();
fs.Read(buffer, 0, (int)fileLength);
fs.Close();
Logger.WriteLog("RAPILibrary:ReadFileAsBinary() Exit");
}
}
}