Click to return to the Networking, Protocols     
Utilizing the Win32 Inter...     Gopher Sessions     Microsoft Win32 Internet ...    
Web Workshop  |  Networking, Protocols & Data Formats

FTP Sessions


The Win32® Internet functions can be used to provide applications with the ability to navigate and manipulate directories and files on an FTP server. Applications that use a CERN proxy exclusively must use the InternetOpenUrl function because CERN proxies do not support FTP. For more information on how to use InternetOpenUrl, see Accessing URLs Directly.

To begin an FTP session, use InternetConnect to create the valid FTP session handle to be used by the FTP functions provided with the Win32 Internet functions.

The Win32 Internet functions provide the capability to navigate between directories; enumerate, create, remove, and rename directories; and rename, upload, download, and delete files on an FTP server.

Navigation is provided by the FtpGetCurrentDirectory and FtpSetCurrentDirectory functions. These functions utilize the FTP session handle created by a previous call to InternetConnect to determine which directory the application is currently in or to change to a different subdirectory.

Directory enumeration is performed by using the FtpFindFirstFile and InternetFindNextFile functions. FtpFindFirstFile uses the FTP session handle created by InternetConnect to find the first file that matches the given search criteria and returns a handle to continue the directory enumeration. InternetFindNextFile uses the handle returned by FtpFindFirstFile to return the next file that matches the original search criteria. The application should continue to call InternetFindNextFile until there are no more files left in the directory.

New directories are created by using the FtpCreateDirectory function. This function uses the FTP session handle created by InternetConnect and creates the directory specified by the string passed to the function. The string can contain a directory name relative to the current directory, or a fully qualified directory path.

To rename either files or directories, the application can call FtpRenameFile. This function replaces the original name with the new name passed to the function. The name of the file or directory can be relative to the current directory, or a fully qualified name.

To upload or place files on an FTP server, the application can use either FtpPutFile or FtpOpenFile (along with InternetWriteFile). FtpPutFile can be used if the file already exists locally, while FtpOpenFile and InternetWriteFile can be used if data needs to be written to a file on the FTP server.

To download or get files, the application can use either FtpGetFile or FtpOpenFile (with InternetReadFile). FtpGetFile is used to retrieve a file from an FTP server and store it locally, while FtpOpenFile and InternetReadFile can be used to control where the downloaded information is going (for example, it could be used to display the information in an edit box).

Deleting files on an FTP server is done by using the FtpDeleteFile function. This function removes a file name that is either relative to the current directory or a fully qualified file name from the FTP server. FtpDeleteFile requires an FTP session handle returned by InternetConnect.

FTP Function Handles

The FTP functions require certain types of HINTERNET handles to work properly. These handles must be created in a set order, starting with the root handle created by InternetOpen. InternetConnect can then create an FTP session handle.

The following diagram shows the FTP functions that are dependent on the FTP session handle returned by InternetConnect. The shaded boxes represent functions that return HINTERNET handles, while the plain boxes represent functions that use the HINTERNET handle created by the function on which they depend.

FTP functions dependent on FTP session handle returned by InternetConnect

The following diagram shows the two FTP functions that return HINTERNET handles and the functions that are dependent on the HINTERNET handles created by them. The shaded boxes represent functions that return HINTERNET handles, while the plain boxes represent functions that use the HINTERNET handle created by the function on which they depend.

FTP functions that return HINTERNET handles

For more information about HINTERNET handles and the handle hierarchy, see Appendix A: HINTERNET Handles.

Using the Win32 Internet Functions for FTP Sessions

The following Win32 Internet functions are used during FTP sessions. These functions are not recognized by CERN proxies. Applications that must function through CERN proxies should use InternetOpenUrl and access the resources directly. For more information on direct resource access, see Accessing URLs Directly.

FtpCreateDirectory Creates a new directory on the server. This function requires a handle created by InternetConnect.
FtpDeleteFile Deletes a file from the server. This function requires a handle created by InternetConnect.
FtpFindFirstFile Starts file enumeration or file search in the current directory. This function requires a handle created by InternetConnect.
FtpGetCurrentDirectory Returns the client's current directory on the server. This function requires a handle created by InternetConnect.
FtpGetFile Retrieves a file from the server. This function requires a handle created by InternetConnect.
FtpOpenFile Initiates access to a file on the server for either reading or writing. This function requires a handle created by InternetConnect.
FtpPutFile Writes a file to the server. This function requires a handle created by InternetConnect.
FtpRemoveDirectory Deletes a directory on the server. This function requires a handle created by InternetConnect.
FtpRenameFile Renames a file on the server. This function requires a handle created by InternetConnect.
FtpSetCurrentDirectory Changes the client's current directory on the server. This function requires a handle created by InternetConnect.
InternetWriteFile Writes data to an open file on the server. This function requires a handle created by FtpOpenFile.

Starting an FTP Session

The application establishes an FTP session by calling InternetConnect on a handle created by InternetOpen. InternetConnect needs the server name, FTP port number, user name, password, and service type (which must be set to INTERNET_SERVICE_FTP). For passive FTP semantics, the application must also set the INTERNET_FLAG_PASSIVE flag.

The INTERNET_DEFAULT_FTP_PORT and INTERNET_INVALID_PORT_NUMBER values can be used for the FTP port number. INTERNET_DEFAULT_FTP_PORT uses the default FTP port, but the service type still must be set. INTERNET_INVALID_PORT_NUMBER uses the default value for the indicated service type.

The values for the user name and password can be set to NULL. If both values are set to NULL, InternetConnect uses "anonymous" for the user name, and the user's e-mail address for the password. If only the password is set to NULL, the user name passed to InternetConnect is used for the user name, and an empty string is used for the password. If both values are not NULL, the user name and password given to InternetConnect are used.

Enumerating Directories

Enumeration of a directory on an FTP server requires the creation of a handle by FtpFindFirstFile. This handle is a branch of the FTP session handle created by InternetConnect. FtpFindFirstFile locates the first file or directory on the server and returns it in a WIN32_FIND_DATA structure. Use InternetFindNextFile until it returns ERROR_NO_MORE_FILES. This method finds all subsequent files and directories on the server. For more information on InternetFindNextFile, see Finding the Next File.

To determine if the file retrieved by FtpFindFirstFile or InternetFindNextFile is a directory, check the dwFileAttributes member of the WIN32_FIND_DATA structure to see if it is equal to FILE_ATTRIBUTE_DIRECTORY.

If the application makes changes on the FTP server or if the FTP server undergoes changes frequently, the INTERNET_FLAG_NO_CACHE_WRITE and INTERNET_FLAG_RELOAD flags should be set in FtpFindFirstFile. These flags ensure that the directory information being retrieved from the FTP server is current.

After the application completes the directory enumeration, a call to InternetCloseHandle must be made on the handle created by FtpFindFirstFile. Until that handle is closed, the application cannot call FtpFindFirstFile again on the session handle created by InternetConnect. If a call to FtpFindFirstFile is made on the same session handle before the previous call to the same function is closed, the function fails, returning ERROR_FTP_TRANSFER_IN_PROGRESS.

The following example displays the contents of an FTP directory in the list box, IDC_FTPList. The HINTERNET handle, hSecondary, is a handle returned by the InternetConnect function after it establishes an FTP session.

int WINAPI DisplayDir(HWND hX, DWORD dwFlags)
{
    WIN32_FIND_DATA pDirInfo;
    HINTERNET hDir;
    DWORD dError;
    char DirList[MAX_PATH];
    DWORD dwTemp=MAX_PATH;
    LPDWORD temp =&dwTemp;
    LPVOID lpOption;
    DWORD dwSize;
    LPDWORD lpdwSize = &dwSize;

SendDlgItemMessage(hX,IDC_FTPList,LB_RESETCONTENT,0,0);
    if ( !(hDir = FtpFindFirstFile (hSecondary, TEXT ("*.*"), &pDirInfo,
        dwFlags, 0) ))
        if (GetLastError()  == ERROR_NO_MORE_FILES) 
        {
            MessageBox(hX,"There are no files here!!!","Display Dir",MB_OK);
            InternetCloseHandle(hDir);
            return 1;
        }
        else 
        {
            ErrorOut (hX, GetLastError (), "FindFirst error: ");
            InternetCloseHandle(hDir);
            return 0;
        }

        sprintf(DirList, pDirInfo.cFileName);
        if (pDirInfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
            strcat(DirList," <DIR> ");
    
        SendDlgItemMessage(hX,IDC_FTPList,LB_ADDSTRING,0,(LPARAM)DirList);

    dError = NO_ERROR;
    do
    {
         if (!InternetFindNextFile (hDir, &pDirInfo))
         {
             dError = GetLastError();
             if ( dError == ERROR_NO_MORE_FILES ) 
             {
                 InternetCloseHandle(hDir);
                 return 1;
             }
             else
             {
                 ErrorOut (hX,GetLastError(), "InternetFindNextFile");
                 InternetCloseHandle(hDir);
                 return 0;
             }
         }
         else
         {
            sprintf(DirList, pDirInfo.cFileName);
            if (pDirInfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
                strcat(DirList," <DIR> ");    
            SendDlgItemMessage(hX,IDC_FTPList,LB_ADDSTRING,0,
                (LPARAM)DirList);
         }
    }
    while ( TRUE);

    if (!InternetCloseHandle(hDir) )
    {
        InternetCloseHandle(hDir);
        ErrorOut (hX,GetLastError(), "InternetCloseHandle error");
        return 0;
    }
    else
        return 1;

}

Navigating Directories

The Win32 Internet functions FtpGetCurrentDirectory and FtpSetCurrentDirectory handle directory navigation.

FtpGetCurrentDirectory returns the application's current directory on the FTP server. The directory path from the root directory on the FTP server is included.

FtpSetCurrentDirectory changes the working directory on the server. The directory information passed to FtpSetCurrentDirectory can be either a partially or fully qualified path name relative to the current directory. For example, if the application is currently in the directory public/info and the path is ftp/example, FtpSetCurrentDirectory changes the current directory to public/info/ftp/example.

The following example uses an FTP session handle, hSecondary, returned by InternetConnect. The new directory name is stored in the edit box, IDC_FTPEdit2. Before the actual change is made, the function gets the current directory and stores it in the same edit box. DisplayDir is another function that is designed to enumerate the directory.

int WINAPI ChangeDir(HWND hX)
{
    DWORD testsz = 320;
    LPSTR lpszUrlBuffer;            // buffer to hold the URL
    LPSTR lpszDirList;

    lpszUrlBuffer = new char[testsz];
    GetDlgItemText(hX,IDC_FTPEdit2,(LPSTR)lpszUrlBuffer,testsz);
    lpszDirList = new char[testsz];
    if (!FtpGetCurrentDirectory(hSecondary,(LPSTR)lpszDirList,&testsz))
    {
        ErrorOut(hX,GetLastError(),"Change Dir");
    }
    else
        SetDlgItemText(hX,IDC_FTPEdit2,(LPSTR)lpszDirList);

    delete(lpszDirList);

    if (!(FtpSetCurrentDirectory(hSecondary,lpszUrlBuffer)))
    {
        ErrorOut(hX,GetLastError(),"InternetConnect");
        delete(lpszUrlBuffer);
        SetDlgItemText(hX,IDC_FTPEdit2,(LPSTR)lpszUrlBuffer);
        DisplayDir(hX,INTERNET_FLAG_RELOAD);
        return 0;
    }
    else
    {
        delete(lpszUrlBuffer);
        return DisplayDir(hX,0);
    }
}

Manipulating Directories on an FTP Server

The Win32 Internet functions provide the capability to create and remove directories on an FTP server to which the application has the necessary privileges. If the application must log on to a server with a specific user name and password, the values can be used in InternetConnect when creating the FTP session handle.

The FtpCreateDirectory function takes a valid FTP session handle and a NULL-terminated string that contains either a fully qualified path or a name relative to the current directory and creates a directory on the FTP server.

The following example shows two separate calls to FtpCreateDirectory. In both examples, hFtpSession is the session handle created by the InternetConnect function, and the root directory is the current directory.

FtpCreateDirectory(hFtpSession, "test");
/* This will create the directory "test" in the current directory 
    (which is the root directory). */

FtpCreateDirectory(hFtpSession, "\test\example");
/* This will create the directory "example" in the test directory. */

The FtpRemoveDirectory function takes a valid FTP session handle and a NULL-terminated string that contains either a fully qualified path or a name relative to the current directory and removes that directory from the FTP server.

The following example shows two sample calls to FtpRemoveDirectory. In both calls, hFtpSession is the session handle created by the InternetConnect function, and the root directory is the current directory. There is a directory called "test" in the root directory and a directory called "example" in the "test" directory.

FtpRemoveDirectory(hFtpSession,"\test\example");
/* Removes the "example" directory and any files or directories contained
in it from the "test" directory. */

FtpRemoveDirectory(hFtpSession, "test");
/* Removes the "test" directory and any files or directories contained
in it from the root directory. */

The following example creates the directory indicated by the string stored in the edit box, IDC_FTPEdit2. The HINTERNET handle, hSecondary, was created by InternetConnect after establishing an FTP session. DisplayDir is another function that is designed to enumerate the directory.

int WINAPI CreateDir(HWND hX)
{
    char strInFile[80];

    GetDlgItemText(hX,IDC_FTPEdit2,strInFile,80);

    if (strlen(strInFile)==0)
    {
        MessageBox(hX,"Directory Name Must Be Specified","Create Dir",MB_OK);
        return 0;
    }
    else
    {
        if(!FtpCreateDirectory(hSecondary,strInFile))
        {
            ErrorOut(hX,GetLastError(),"Create Dir");
            return 0;
        }
        else
        {
            return DisplayDir(hX,INTERNET_FLAG_RELOAD);
        }
    }
}

The following example deletes the directory indicated by the edit box, IDC_FTPEdit2. The HINTERNET handle, hSecondary, was created by InternetConnect after establishing an FTP session. DisplayDir is another function that is designed to enumerate the directory.

int WINAPI RemoveDir(HWND hX)
{
    char strInFile[80];

    GetDlgItemText(hX,IDC_FTPEdit2,strInFile,80);

    if (strlen(strInFile)==0)
    {
        MessageBox(hX,"Directory Name Must Be Specified!","Remove Dir",MB_OK);
        return 0;
    }
    else
    {
        if(!FtpRemoveDirectory(hSecondary,strInFile))
        {
            ErrorOut(hX,GetLastError(),"Remove Dir");
            return 0;
        }
        else
        {
            MessageBox(hX,"Directory Deleted","Remove Dir",MB_OK);
            return DisplayDir(hX,INTERNET_FLAG_RELOAD);
        }
    }
}

Getting Files on an FTP Server

The Win32 Internet functions offer three methods for retrieving files from an FTP server:

For more information about using the InternetReadFile function, see Reading Files.

If the URL of the file is available, the application can call InternetOpenUrl to connect to that URL and then use InternetReadFile to control the download of the file. This setup allows the application to control the download more tightly and is ideal for situations where no other operations need to be made on the FTP server. For more information on how to directly access resources, see Accessing URLs Directly.

If the application has established an FTP session handle to the server with InternetConnect, the application can call FtpOpenFile with the existing file name and with a new name for the locally stored file. The application can then use InternetReadFile to download the file. This allows the application to control the download more tightly and keep the connection to the FTP server, so more commands can be executed.

If the application does not need to tightly control the download, the application can use FtpGetFile with the FTP session handle, remote file name, and local file name to retrieve the file. FtpGetFile performs all the bookkeeping and overhead associated with reading a file from an FTP server and storing it locally.

The following example retrieves the file indicated by the IDC_FTPEdit2 edit box and stores it locally using the file name specified by the IDC_FTPEdit3 edit box. The HINTERNET handle, hSecondary, was created by InternetConnect after establishing an FTP session. DisplayDir is another function that is designed to enumerate the directory.

int WINAPI GetFile(HWND hX)
{
    char strInFile[80];
    char strOutFile[80];
    int intTransType;

    GetDlgItemText(hX,IDC_FTPEdit3,strOutFile,80);
    GetDlgItemText(hX,IDC_FTPEdit2,strInFile,80);

    if ((strlen(strOutFile)==0) | (strlen(strInFile)==0))
    {
        MessageBox(hX,"Target File or Destination File Missing","Get File",MB_OK);
        return 0;
    }
    else
    {
        intTransType = MessageBox(hX,
            "Do you want to download in ASCII (Default:Binary)?",
            "Get File",MB_YESNO);
        if (intTransType==IDYES)
        {
            if(!FtpGetFile(hSecondary,strInFile,strOutFile,FALSE,
                FILE_ATTRIBUTE_NORMAL,FTP_TRANSFER_TYPE_ASCII | 
                INTERNET_FLAG_NO_CACHE_WRITE,0))
            {
                ErrorOut(hX,GetLastError(),"Get File");
                DisplayDir(hX,INTERNET_FLAG_RELOAD);
                return 0;
            }
            else
            {
                MessageBox(hX,"ASCII Transfer Complete","Get File",MB_OK);
                return 1;
            }
        }
        else
        {
            if(!FtpGetFile(hSecondary,strInFile,strOutFile,FALSE,
                FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY |
                INTERNET_FLAG_RELOAD,0))
            {
                ErrorOut(hX,GetLastError(),"Get File");
                return 0;
            }
            else
            {
                MessageBox(hX,"Binary Transfer Complete","Get File",MB_OK);
                return 1;
            }
        }
    }
}

Placing Files on an FTP Server

An application can use two methods to place a file on an FTP server using the Win32 Internet functions:

An application that must send data to an FTP server, but does not have a local file containing all the data, should use FtpOpenFile to create and open a file on the FTP server. The application then can use InternetWriteFile to upload the information to the file.

If the file already exists locally, the application can use FtpPutFile to upload the file to the FTP server. FtpPutFile performs all the overhead that goes with uploading a local file to a remote FTP server.

The following example places the file indicated by the IDC_FTPEdit2 edit box on the FTP server, using the file name specified by the IDC_FTPEdit3 edit box. The HINTERNET handle, hSecondary, was created by InternetConnect after establishing an FTP session.

int WINAPI PutFile(HWND hX)
{
    char strInFile[80];
    char strOutFile[80];
    int intTransType;

    GetDlgItemText(hX,IDC_FTPEdit3,strOutFile,80);
    GetDlgItemText(hX,IDC_FTPEdit2,strInFile,80);

    if ((strlen(strOutFile)==0) | (strlen(strInFile)==0))
    {
        MessageBox(hX,"Target File or Destination File Missing","Put File",MB_OK);
        return 0;
    }
    else
    {
        intTransType = MessageBox(hX,
            "Do you want to upload in ASCII (Default:Binary)?",
            "Put File",MB_YESNO);

        if (intTransType==IDYES)
        {
            if(!FtpPutFile(hSecondary,strInFile,strOutFile,
                FTP_TRANSFER_TYPE_ASCII,0))
            {
                ErrorOut(hX,GetLastError(),"Get File");
                return 0;
            }
            else
            {
                MessageBox(hX,"ASCII Transfer Complete","Put File",MB_OK);
                return 1;
            }
        }
        else
        {
            if(!FtpPutFile(hSecondary,strInFile,strOutFile,
                FTP_TRANSFER_TYPE_BINARY,0))
            {
                ErrorOut(hX,GetLastError(),"Get File");
                return 0;
            }
            else
            {
                MessageBox(hX,"Binary Transfer Complete","Get File",MB_OK);
                DisplayDir(hX,INTERNET_FLAG_RELOAD);
                return 1;
            }
        }
    }
}

Deleting Files from an FTP Server

To delete a file from an FTP server, an application can use the FtpDeleteFile function. The calling application must have the necessary privileges specified to delete a file from the FTP server when InternetConnect creates the FTP session handle.

The following example deletes the file indicated by the IDC_FTPEdit2 edit box. The HINTERNET handle, hSecondary, was created by InternetConnect after establishing an FTP session. DisplayDir is another function that is designed to enumerate the directory.

int WINAPI DeleteFile(HWND hX)
{
    char strInFile[80];

    GetDlgItemText(hX,IDC_FTPEdit2,strInFile,80);

    if (strlen(strInFile)==0)
    {
        MessageBox(hX,"File Name Must Be Specified!","Remove Dir",MB_OK);
        return 0;
    }
    else
    {
        if(!FtpDeleteFile(hSecondary,strInFile))
        {
            ErrorOut(hX,GetLastError(),"Remove Dir");
            return 0;
        }
        else
        {
            MessageBox(hX,"File Deleted","Remove Dir",MB_OK);
            return DisplayDir(hX,INTERNET_FLAG_RELOAD);
        }
    }
}

Renaming Files and Directories on an FTP Server

Renaming files and directories on an FTP server can be performed by using the FtpRenameFile function. FtpRenameFile accepts two NULL-terminated strings that contain either partially or fully qualified names relative to the current directory and then renames the file designated by the first string to the name in the second string.

The following example renames the file or directory indicated by the IDC_FTPEdit2 edit box. The HINTERNET handle, hSecondary, was created by InternetConnect after establishing an FTP session. DisplayDir is another function that is designed to enumerate the directory.

int WINAPI RenameFile(HWND hX)
{
    char strInFile[80];
    char strOutFile[80];

    GetDlgItemText(hX,IDC_FTPEdit3,strOutFile,80);
    GetDlgItemText(hX,IDC_FTPEdit2,strInFile,80);

    if ((strlen(strOutFile)==0) | (strlen(strInFile)==0))
    {
        MessageBox(hX,"Target File or Destination File Missing","Put File",MB_OK);
        return 0;
    }
    else
    {
        if(!FtpRenameFile(hSecondary,strInFile,strOutFile))
        {
            ErrorOut(hX,GetLastError(),"Get File");
            DisplayDir(hX,INTERNET_FLAG_RELOAD);
            return 0;
        }
        else
        {
            return DisplayDir(hX,INTERNET_FLAG_RELOAD);
        }
    }
}


Back to topBack to top

Did you find this topic useful? Suggestions for other topics? Write us!

© 1999 Microsoft Corporation. All rights reserved. Terms of use.