From: Jin on
Hello everyone,

I'm trying to develop a FTP class, written in C#. I started building it from
a VB.NET class posted on a OPENNETCF forum. My goal is to obtain a class
which performs simple FTP transmissions both when connected to the network
via lan/gprs and even if the PocketPC is connected via Activesync to the PC.

I have a small (and old) program written in eVC++ which performs (more or
less) the same operations. It uses
FtpOpenFile()/InternetReadFile()/InternetWriteFile() to perform these
operations, and I'm trying to obtain the same behaviour rewriting the program
and making it more versatile.

When I perform the connection to the FTP site I have absolutely no problems.
I tried to connect on a remote FTP site, and on a FTP site hosted on my PC:
no problems with that.

The whole problem started when I tried to create a PutFile() method. I'm
tryng to use FtpOpenFile() in order to open the remote file and start writing
in it with InternetWriteFile(), but FtpOpenFile() ALWAYS returns a void
handle (zero, precisely).

I don't understand if the problem is related to existing ActiveSync
connection (...but the eVC++ program works perfectly using it!!!) or wrong
p/invoking or bad CSharp programming (or a mix of those ;))

I'm posting the whole class here. Maybe I simply made an error while
declaring APIs.

Any help would be greatly appriciated. If I can create a fully functional
class, I'll put in this thread so that others ca re-use it.


public class FTP : IDisposable
{
#region "Costanti per w/API"
private const int INTERNET_OPEN_TYPE_PRECONFIG = 0x0;
private const int INTERNET_OPEN_TYPE_DIRECT = 0x1;
private const int INTERNET_OPEN_TYPE_PROXY = 0x3;
private const int INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 0x4;

private const int INTERNET_DEFAULT_FTP_PORT = 21;
private const int INTERNET_FLAG_TRANSFER_BINARY = 0x02;
private const uint INTERNET_FLAG_RELOAD = 0x80000000;

private const int GENERIC_WRITE = 0x40000000;
private const int FILE_SHARE_WRITE = 0x2;
private const int OPEN_EXISTING = 0x3;

private const int FILE_ATTRIBUTE_DIRECTORY = 0x10;
private const int FILE_ATTRIBUTE_NORMAL = 0x80;

private const int INTERNET_SERVICE_FTP = 0x1;
private const int INTERNET_FLAG_PASSIVE = 0x8000000;
private const int INTERNET_FLAG_DONT_CACHE = 0x4000000;

private const int MAX_PATH = 260;
#endregion

#region "Variabili private"
IntPtr hInternet, hFtp;
int nID;
// int hInternet;
// int hFtp;
// int nID;
#endregion

#region "Dichiarazioni chiamate esterne per P/Invoke"
[DllImport("wininet.dll", SetLastError = true)]
private extern static bool InternetWriteFile(
IntPtr hFile,
byte[] sendBuffer,
Int32 dwNumberOfBytesToWrite,
ref Int32 lpdwNumberOfBytesWritten);

// Declare Function FtpOpenFile Lib "wininet.dll" Alias "FtpOpenFileA"
(ByVal hFtpSession As Integer, ByVal lpszFileName As String, ByVal fdwAccess
As Integer, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Integer
[DllImport("wininet.dll", SetLastError=true)]
private static extern IntPtr FtpOpenFile(
// int hFtpSession,
IntPtr hFtpSession,
string lpszFileName,
int fdwAccess,
int dwFlags,
int dwContext);

// Public Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal
hInet As Integer) As Short
[DllImport("wininet.dll", SetLastError=true)]
// private static extern short InternetCloseHandle(int hInet);
private static extern short InternetCloseHandle(IntPtr hInet);

// Private Declare Function InternetConnect Lib "wininet.dll" (ByVal
hInternet As Integer, ByVal lpszServerName As String, ByVal nServerPort As
Integer, ByVal lpszUserName As String, ByVal lpszPassword As String, ByVal
dwService As Int32, ByVal dwFlags As Integer, ByVal dwContext As Integer) As
Integer
[DllImport("wininet.dll", SetLastError=true)]
// private static extern int InternetConnect(
// int hInternet,
private static extern IntPtr InternetConnect(
IntPtr hInternet,
string lpszServerName,
int nServerPort,
string lpszUserName,
string lpszPassword,
Int32 dwService,
int dwFlags,
int dwContext);

// Private Declare Function InternetOpen Lib "wininet.dll" (ByVal
lpszAgent As String, ByVal dwAccessType As Integer, ByVal lpszProxy As
String, ByVal lpszProxyBypass As String, ByVal dwFlags As Integer) As Integer
[DllImport("wininet.dll", SetLastError=true)]
// private static extern int InternetOpen(
private static extern IntPtr InternetOpen(
string lpszAgent,
int dwAccessType,
string lpszProxy,
string lpszProxyBypass,
int dwFlags);

// Private Declare Function FtpPutFile Lib "wininet.dll" (ByVal hConnect
As Integer, ByVal lpszLocalFile As String, ByVal lpszNewRemoteFile As String,
ByVal dwFlags As Integer, ByVal dwContext As Integer) As Boolean
[DllImport("wininet.dll", SetLastError=true)]
private static extern bool FtpPutFile(
// int hConnect,
IntPtr hConnect,
string lpszLocalFile,
string lpszNewRemoteFile,
int dwFlags,
int dwContext);
#endregion

#region "FTP: Open - Close - Connected"
public bool Open(string stUrl, string stUser, string stPass)
{
// FINAL VERSION
// -------------
hInternet = InternetOpen(
"FTPPDA",
INTERNET_OPEN_TYPE_DIRECT,
string.Empty,
string.Empty,
0);

if (hInternet == IntPtr.Zero)
return false;

hFtp = InternetConnect(hInternet,
stUrl,
INTERNET_DEFAULT_FTP_PORT,
stUser,
stPass,
INTERNET_SERVICE_FTP,
INTERNET_FLAG_PASSIVE,
nID);

if (hFtp == IntPtr.Zero)
{
InternetCloseHandle(hInternet);
return false;
}

return true;
}

public void Close()
{
// FINAL VERSION
// -------------
if (hFtp != IntPtr.Zero)
InternetCloseHandle(hFtp);
hFtp = IntPtr.Zero;

if (hInternet != IntPtr.Zero)
InternetCloseHandle(hInternet);
hInternet = IntPtr.Zero;
}

public bool IsFTPConnected()
{
// FINAL VERSION
// -------------
return (hFtp != IntPtr.Zero);
}
#endregion

#region "FTP: Put file"
public bool PutFile(string stSrc, string stDst)
{
// WIP VERSION - ROUTINE NOT FINISHED
// ----------------------------------
IntPtr hFile = IntPtr.Zero;
byte[] bySend;
Int32 lScrit
From: Jin on
Another clue:

After FtpOpenFile() I added:

if (hFile == IntPtr.Zero)
{
int iErrCode = Marshal.GetLastWin32Error();
System.Windows.Forms.MessageBox.Show("iErrCode: " +
iErrCode.ToString());
return false;
}

and iErrCode always is 12018

Searching in .H files I found in inetmsg.h
//
// MessageId: ERROR_INTERNET_INCORRECT_HANDLE_TYPE
//
// MessageText:
//
// The supplied handle is the wrong type for the requested operation
//
#define ERROR_INTERNET_INCORRECT_HANDLE_TYPE 12018L

So it would seem an error in p/invoke declarations...maybe!

Thanks to anyone
Jin


"Jin" wrote:

> Hello everyone,
>
> I'm trying to develop a FTP class, written in C#. I started building it from
> a VB.NET class posted on a OPENNETCF forum. My goal is to obtain a class
> which performs simple FTP transmissions both when connected to the network
> via lan/gprs and even if the PocketPC is connected via Activesync to the PC.
>
> I have a small (and old) program written in eVC++ which performs (more or
> less) the same operations. It uses
> FtpOpenFile()/InternetReadFile()/InternetWriteFile() to perform these
> operations, and I'm trying to obtain the same behaviour rewriting the program
> and making it more versatile.
>
> When I perform the connection to the FTP site I have absolutely no problems.
> I tried to connect on a remote FTP site, and on a FTP site hosted on my PC:
> no problems with that.
>
> The whole problem started when I tried to create a PutFile() method. I'm
> tryng to use FtpOpenFile() in order to open the remote file and start writing
> in it with InternetWriteFile(), but FtpOpenFile() ALWAYS returns a void
> handle (zero, precisely).
>
> I don't understand if the problem is related to existing ActiveSync
> connection (...but the eVC++ program works perfectly using it!!!) or wrong
> p/invoking or bad CSharp programming (or a mix of those ;))
>
> I'm posting the whole class here. Maybe I simply made an error while
> declaring APIs.
>
> Any help would be greatly appriciated. If I can create a fully functional
> class, I'll put in this thread so that others ca re-use it.
>
>
> public class FTP : IDisposable
> {
> #region "Costanti per w/API"
> private const int INTERNET_OPEN_TYPE_PRECONFIG = 0x0;
> private const int INTERNET_OPEN_TYPE_DIRECT = 0x1;
> private const int INTERNET_OPEN_TYPE_PROXY = 0x3;
> private const int INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 0x4;
>
> private const int INTERNET_DEFAULT_FTP_PORT = 21;
> private const int INTERNET_FLAG_TRANSFER_BINARY = 0x02;
> private const uint INTERNET_FLAG_RELOAD = 0x80000000;
>
> private const int GENERIC_WRITE = 0x40000000;
> private const int FILE_SHARE_WRITE = 0x2;
> private const int OPEN_EXISTING = 0x3;
>
> private const int FILE_ATTRIBUTE_DIRECTORY = 0x10;
> private const int FILE_ATTRIBUTE_NORMAL = 0x80;
>
> private const int INTERNET_SERVICE_FTP = 0x1;
> private const int INTERNET_FLAG_PASSIVE = 0x8000000;
> private const int INTERNET_FLAG_DONT_CACHE = 0x4000000;
>
> private const int MAX_PATH = 260;
> #endregion
>
> #region "Variabili private"
> IntPtr hInternet, hFtp;
> int nID;
> // int hInternet;
> // int hFtp;
> // int nID;
> #endregion
>
> #region "Dichiarazioni chiamate esterne per P/Invoke"
> [DllImport("wininet.dll", SetLastError = true)]
> private extern static bool InternetWriteFile(
> IntPtr hFile,
> byte[] sendBuffer,
> Int32 dwNumberOfBytesToWrite,
> ref Int32 lpdwNumberOfBytesWritten);
>
> // Declare Function FtpOpenFile Lib "wininet.dll" Alias "FtpOpenFileA"
> (ByVal hFtpSession As Integer, ByVal lpszFileName As String, ByVal fdwAccess
> As Integer, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Integer
> [DllImport("wininet.dll", SetLastError=true)]
> private static extern IntPtr FtpOpenFile(
> // int hFtpSession,
> IntPtr hFtpSession,
> string lpszFileName,
> int fdwAccess,
> int dwFlags,
> int dwContext);
>
> // Public Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal
> hInet As Integer) As Short
> [DllImport("wininet.dll", SetLastError=true)]
> // private static extern short InternetCloseHandle(int hInet);
> private static extern short InternetCloseHandle(IntPtr hInet);
>
> // Private Declare Function InternetConnect Lib "wininet.dll" (ByVal
> hInternet As Integer, ByVal lpszServerName As String, ByVal nServerPort As
> Integer, ByVal lpszUserName As String, ByVal lpszPassword As String, ByVal
> dwService As Int32, ByVal dwFlags As Integer, ByVal dwContext As Integer) As
> Integer
> [DllImport("wininet.dll", SetLastError=true)]
> // private static extern int InternetConnect(
> // int hInternet,
> private static extern IntPtr InternetConnect(
> IntPtr hInternet,
> string lpszServerName,
> int nServerPort,
> string lpszUserName,
> string lpszPassword,
> Int32 dwService,
> int dwFlags,
> int dwContext);
>
> // Private Declare Function InternetOpen Lib "wininet.dll" (ByVal
> lpszAgent As String, ByVal dwAccessType As Integer, ByVal lpszProxy As
> String, ByVal lpszProxyBypass As String, ByVal dwFlags As Integer) As Integer
> [DllImport("wininet.dll", SetLastError=true)]
> // private static extern int InternetOpen(
> private static extern IntPtr InternetOpen(
> string lpszAgent,
> int dwAccessType,
> string lpszProxy,
> string lpszProxyBypass,
> int dwFlags);
>
> // Private Declare Function FtpPutFile Lib "wininet.dll" (ByVal hConnect
> As Integer, ByVal lpszLocalFile As String, ByVal lpszNewRemoteFile As String,
> ByVal dwFlags As Integer, ByVal dwContext As Integer) As Boolean
> [DllImport("wininet.dll", SetLastError=true)]
> private static extern bool FtpPutFile(
> // int hConnect,
> IntPtr hConnect,
> string lpszLocalFile,
> string lpszNewRemoteFile,
> int dwFlags,
> int dwContext);
> #endregion
>
> #region "FTP: Open - Close - Connected"
> public bool Open(string stUrl, string stUser, string stPass)
> {
> // FINAL VERSION
> // -------------
> hInternet = InternetOpen(
> "FTPPDA",
> INTERNET_OPEN_TYPE_DIRECT,
> string.Empty,
> string.Empty,
> 0);
>
> if (hInternet == IntPtr.Zero)
> return false;
>
> hFtp
From: Guest on
> hFile = FtpOpenFile( // This ALWAYS returns IntPtr.Zero!!!
> hInternet,

You should pass the handle received from the InternetConnect() call here.

Greetings, Christian


From: Jin on
Thanks Christian,

I slightly changed the code in
..
..
..
hFile = FtpOpenFile(hFtp, stDst, GENERIC_WRITE,
INTERNET_FLAG_TRANSFER_BINARY, nID);
..
..
..
and if I run the app with Activesync connected I get an error 12029L
//
// MessageId: ERROR_INTERNET_CANNOT_CONNECT
//
// MessageText:
//
// A connection with the server could not be established
//
#define ERROR_INTERNET_CANNOT_CONNECT 12029L

if I run the app via LAN, all works perfectly!!!!
My problem is that I need to have it working also with Activesync connection
(as my old evc program).

Any ideas?
Jin

"Guest" wrote:

> > hFile = FtpOpenFile( // This ALWAYS returns IntPtr.Zero!!!
> > hInternet,
>
> You should pass the handle received from the InternetConnect() call here.
>
> Greetings, Christian
>
>
>
From: Guest on
> if I run the app via LAN, all works perfectly!!!!
> My problem is that I need to have it working also with Activesync
> connection
> (as my old evc program).
>
> Any ideas?

It won't work with an ActiveSync connection.

Take a look at this thread:
http://groups.google.de/group/microsoft.public.pocketpc.activesync/browse_thread/thread/10ef872b437f5069/78bc25b4614c974d?lnk=st&q=&rnum=4&hl=de#78bc25b4614c974d

Greetings, Christian