- Table of Contents
- Copyright
- About the Authors
- About the Contributors
- Acknowledgments
- Tell Us What You Think!
- Introduction
- How to Use This Book
- What You Need to Use This Book
- What's New in Visual C++ 6.0
- Contacting the Main Author
- Part I: Introduction
- Chapter 1. The Visual C++ 6.0 Environment
- Part II: MFC Programming
- Chapter 2. MFC Class Library Overview
- Chapter 3. MFC Message Handling Mechanism
- Chapter 4. The Document View Architecture
- Chapter 5. Creating and Using Dialog Boxes
- Chapter 6. Working with Device Contexts and GDI Objects
- Chapter 7. Creating and Using Property Sheets
- Chapter 8. Working with the File System
- Chapter 9. Using Serialization with File and Archive Objects
- Part III: Internet Programming with MFC
- Chapter 10. MFC and the Internet Server API (ISAPI)
- Chapter 11. The WinInet API
- Chapter 12. MFC HTML Support
- Part IV: Advanced Programming Topics
- Chapter 13. Using the Standard C++ Library
- Chapter 14. Error Detection and Exception Handling Techniques
- Chapter 15. Debugging and Profiling Strategies
- Chapter 16. Multithreading
- Chapter 17. Using Scripting and Other Tools to Automate the Visual C++ IDE
- Part V: Database Programming
- Chapter 18. Creating Custom AppWizards
- Chapter 19. Database Overview
- Chapter 20. ODBC Programming
- Chapter 21. MFC Database Classes
- Chapter 22. Using OLE DB
- Chapter 23. Programming with ADO
- Part VI: MFC Support for COM and ActiveX
- Chapter 24. Overview of COM and Active Technologies
- Chapter 25. Active Documents
- Chapter 26. Active Containers
- Chapter 27. Active Servers
- Chapter 28. ActiveX Controls
- Part VII: Using the Active Template Library
- Chapter 29. ATL Architecture
- Chapter 30. Creating COM Objects Using ATL
- Chapter 31. Creating ActiveX Controls Using ATL
- Chapter 32. Using ATL to Create MTS and COM+ Components
- Part VIII: Finishing Touches
- Chapter 33. Adding Windows Help
- Part IX: Appendix
General Internet Functions
Many functions in the WinInet API are used for any sort of Internet connection, such as beginning a session, enabling asynchronous I/O, and manipulating URLs. Here, you will take a look at these general functions before moving on to the protocol-specific elements of the WinInet API.
Beginning a WinInet Session
Before using most of the WinInet functions, you must open a new session with a call to InternetOpen(), which initializes the WinInet library and returns a session handle that will be the root of the handle hierarchy for the rest of your operations within that session. The following is the prototype for InternetOpen():
HINTERNET InternetOpen(LPCTSTR lpszAgent, DWORD dwAccessType,
LPCTSTR lpszProxyName, LPCSTR lpszProxyBypass, DWORD dwFlags);
InternetOpen() enables you to specify how this session will use a proxy server. The dwAccessType parameter may specify INTERNET_OPEN_TYPE_DIRECT to resolve all addresses locally, INTERNET_OPEN_TYPE_PROXY to send requests to the proxy server, or INTERNET_OPEN_TYPE_PRECONFIG to retrieve proxy configuration information from the Registry. In cases where you are using a proxy server, its name is passed in lpszProxyName, although this can be NULL to read proxy information from the Registry.
You also can specify a list of addresses that will be resolved locally in the lpszProxyBypass string. Requests for any address contained in this string will not be forwarded to the proxy server but will be resolved locally.
You may specify the INTERNET_FLAG_OFFLINE flag in dwFlags to specify that all download requests for this session be handled by the persistent cache. If a requested file is not in the cache, operations to access it will fail.
You also may specify the INTERNET_FLAG_ASYNC flag to enable asynchronous operations for this session handle, as well as any handles derived from it.
The INTERNET_FLAG_FROM_CACHE flag returns all requested items from the cache alone. If the item is not found in the cache, an error such as ERROR_FILE_NOT_FOUND (or whatever is most appropriate) is returned. The function InternetOpen uses this flag.
When you are finished with a session, you should close the session handle with a call to InternetCloseHandle(). This also closes any handles that have been derived from the session handle.
Setting Handle Options
If you want to use certain options for all the Internet handles that you will be using in this session, it is easiest to set the options on the session handle. Any handles that are derived from the session handle, such as connection handles created by InternetConnect(), will inherit the options from the session handle. In addition, you could set options for a connection handle, which will be inherited by any handles derived from that connection handle. Note however, that only new handles derived from the modified handle will inherit the new settings. Handles that already have been created will maintain their current settings.
You set specific option settings for an Internet handle with a call to the InternetSetOption() function:
BOOL InternetSetOption(HINTERNET hInternet, DWORD dwOption,
LPVOID lpBuffer, DWORD dwBufferLength);
The handle to be modified is passed in hInternet. The buffer passed by lpBuffer, and its length passed in dwBufferLength, are used to pass in data for the specific option that is to be set. You specify the option to set by the value dwOption, and you can use one of the following values:
- INTERNET_OPTION_ASYNC_PRIORITY is the priority for an asynchronous download (not currently implemented).
- INTERNET_OPTION_CALLBACK is the address of the callback function for this handle.
- INTERNET_OPTION_CONNECT_BACKOFF is the delay value, in milliseconds, to wait between connection retries.
- INTERNET_OPTION_CONNECT_RETRIES is the number of times to retry a connection request.
- INTERNET_OPTION_CONNECT_TIMEOUT is the timeout value, in milliseconds, for connection requests.
- INTERNET_OPTION_CONTEXT_VALUE is the context value to be used with this handle.
- INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT is the timeout value, in milliseconds, for receiving control information for FTP sessions.
- INTERNET_OPTION_CONTROL_SEND_TIMEOUT is the timeout value, in milliseconds, for sending control information for FTP.
- INTERNET_OPTION_DATA_RECEIVE_TIMEOUT is the timeout value, in milliseconds, for receiving data.
- INTERNET_OPTION_DATA_SEND_TIMEOUT is the timeout value, in milliseconds, for sending data.
- INTERNET_OPTION_PASSWORD is the password for handles created with InternetConnect().
- INTERNET_OPTION_PROXY is proxy information for this handle or for global proxy information if hInternet is NULL. lpBuffer should point to an INTERNET_PROXY_INFO structure.
- INTERNET_OPTION_READ_BUFFER_SIZE is the size, in bytes, of the buffer for reading data.
- INTERNET_OPTION_REFRESH allows options for this handle to be reloaded from the Registry.
- INTERNET_OPTION_USER_AGENT is the user agent string to use for HTTP requests.
- INTERNET_OPTION_USERNAME is the username for handles created with InternetConnect().
- INTERNET_OPTION_WRITE_BUFFER_SIZE is the size, in bytes, of the buffer for writing data.
Note that this is just a partial list, for there are over 50 internet options available.
You also can set the options for a handle with the InternetSetOptionEx() function, which takes an additional dwFlags parameter. You may set the flags to ISO_GLOBAL to modify the settings globally or to ISO_REGISTRY to modify the settings in the Registry.
Querying Handle Options
You can query the current settings for a handle's options with the InternetQueryOption() function:
BOOL InternetQueryOption(HINTERNET hInternet, DWORD dwOption,
LPVOID lpBuffer, LPDWORD lpdwBufferLength);
This function works much like InternetSetOption() and enables you to query all the options listed previously. In addition, you can query several additional values that are not set with InternetSetOption():
- INTERNET_OPTION_ASYNC is not yet implemented.
- INTERNET_OPTION_CACHE_STREAM_HANDLE returns the file handle used for writing cached data.
- INTERNET_OPTION_DATAFILE_NAME returns the filename for the file backing a download.
- INTERNET_OPTION_EXTENDED_ERROR returns the actual Winsock error code from the last error.
- INTERNET_OPTION_HANDLE_TYPE returns one of the following constants, indicating the type of handle:
- INTERNET_HANDLE_TYPE_CONNECT_FTP
- INTERNET_HANDLE_TYPE_CONNECT_GOPHER
- INTERNET_HANDLE_TYPE_CONNECT_HTTP
- INTERNET_HANDLE_TYPE_FILE_REQUEST
- INTERNET_HANDLE_TYPE_FTP_FILE
- INTERNET_HANDLE_TYPE_FTP_FILE_HTML
- INTERNET_HANDLE_TYPE_FTP_FIND
- INTERNET_HANDLE_TYPE_FTP_FIND_HTML
- INTERNET_HANDLE_TYPE_GOPHER_FILE
- INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML
- INTERNET_HANDLE_TYPE_GOPHER_FIND
- INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML
- INTERNET_HANDLE_TYPE_HTTP_REQUEST
- INTERNET_HANDLE_TYPE_INTERNET
- INTERNET_OPTION_KEEP_CONNECTION returns one of the following constants indicating this handle's use of persistent connections:
- INTERNET_KEEP_ALIVE_DISABLED
- INTERNET_KEEP_ALIVE_ENABLED
- INTERNET_KEEP_ALIVE_UNKNOWN
- INTERNET_OPTION_OFFLINE_MODE is not yet implemented.
- INTERNET_OPTION_PARENT_HANDLE returns the handle from which this handle was derived.
- INTERNET_OPTION_REFRESH returns TRUE if the handle's settings may be reloaded from the Registry.
- INTERNET_OPTION_REQUEST_FLAGS returns flags concerning the current download. Currently, only a request flag value of INTERNET_REQFLAG_FROM_CACHE is supported, indicating that the request is being satisfied from the cache.
- INTERNET_OPTION_SECURITY_CERTIFICATE returns a formatted string containing the certificate for an SSL/PCT server.
- INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT returns an INTERNET_ CERTIFICATE_INFO structure containing the certificate for SSL/PCT servers.
- INTERNET_OPTION_SECURITY_FLAGS returns a combination of the following security flags:
- SECURITY_FLAG_40BIT
- SECURITY_FLAG_56BIT
- SECURITY_FLAG_128BIT
- SECURITY_FLAGE_FORTEZZA
- SECURITY_FLAG_IETFSSL4
- SECURITY_FLAG_IGNORE_CERT_CN_INVALID
- SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
- SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP
- SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS
- SECURITY_FLAG_IGNORE_REVOCATION
- SECURITY_FLAG_IGNORE_UNKNOWN_CA
- SECURITY_FLAG_IGNORE_WRONG_USAGESECURITY_FLAG_STRENGTH_MEDIUM
- SECURITY_FLAG_STRENGTH_STRONG
- SECURITY_FLAG_STRENGTH_WEAK
- SECURITY_FLAG_NORMALBITNESS
- SECURITY_FLAG_PCT
- SECURITY_FLAG_PCT4
- SECURITY_FLAG_SECURE
- SECURITY_FLAG_SSL
- SECURITY_FLAG_SSL3
- SECURITY_FLAG_UNKNOWNBIT
- INTERNET_OPTION_SECURITY_KEY_BITNESS returns the size of the encryption key in bits.
- INTERNET_OPTION_URL returns the URL of a download.
- INTERNET_OPTION_VERSION returns an INTERNET_VERSION_INFO structure containing the version of WinInet.dll.
Verifying Internet Connectivity
If your application is capable of operating with or without an Internet connection, you may want to use the InternetAttemptConnect() function, which attempts to connect to the Internet. If this returns ERROR_SUCCESS, the connection was successful and your application should be able to access information on the Internet. If any other error is returned, the connection could not be established and your application should respond appropriately, perhaps operating in an offline mode.
Connecting to a Server
For most cases, in order to communicate with an FTP, HTTP, or Gopher server, you first must establish a connection, although you will see that InternetOpenUrl() does not require you to create a session explicitly before retrieving files. Establishing a connection is done with the InternetConnect() function, which returns a handle (HINTERNET) for the connection. The new connection handle is derived from a session handle created by InternetOpen() and inherits the attributes of the session handle, like the asynchronous mode.
For the FTP protocol, InternetConnect() establishes a genuine connection to the server, although for protocols such as Gopher and HTTP, the actual connection is not established until a specific request is made. The connection represented by the handle returned by InternetConnect() is a sort of "virtual connection" and can be used to store configuration information for the connection.
The prototype for InternetConnect() follows:
HINTERNET InternetConnect(HINTERNET hInternet, LPCTSTR lpszServerName,
INTERNET_PORT nServerPort, LPCTSTR lpszUsername, LPCTSTR lpszPassword,
DWORD dwService, DWORD dwFlags, DWORD dwContext);
The handle passed in hInternet comes from a call to InternetOpen(), and the lpszServerName and nServerPort parameters refer to the desired server. You can specify a value of INTERNET_INVALID_PORT_NUMBER to use the default port for the requested service, or you may use one of the following constants:
- INTERNET_DEFAULT_FTP_PORT
- INTERNET_DEFAULT_GOPHER_PORT
- INTERNET_DEFAULT_HTTP_PORT
- INTERNET_DEFAULT_HTTPS_PORT
- INTERNET_DEFAULT_SOCKS_PORT
The optional lpszUsername and lpszPassword parameters may be required to connect to servers that require a login.
The dwService parameter specifies the service to which to connect. This can be one of the following constants:
- INTERNET_SERVICE_FTP
- INTERNET_SERVICE_GOPHER
- INTERNET_SERVICE_HTTP
The dwFlags parameter is used to specify options for the service. Currently, only the INTERNET_CONNECT_FLAG_PASSIVE flag is implemented, which specifies the use of passive mode for FTP connections.
If an error occurs in InternetConnect(), it returns NULL, and you can call GetLastError() or InternetGetLastResponseInfo() for more details on the error. If the connection is established successfully, InternetConnect() returns a valid connection handle, which can be used in the protocol-specific functions that you will explore soon.
Adding a Callback Function
InternetConnect(), like many other functions that you will look at in this chapter, can be used asynchronously. To do this, the INTERNET_FLAG_ASYNC flag must have been set when the session handle was created by InternetOpen(). You also must assign a context value and have a callback function assigned to the handle. A callback function is attached to a handle with the InternetSetStatusCallback() function:
INTERNET_STATUS_CALLBACK InternetSetStatusCallback(
HINTERNET hInternet, INTERNET_STATUS_CALLBACK lpfnInternetCallback);
The hInternet parameter specifies the handle that will use the callback function specified in lpfnInternetCallback. Any handles that are derived from this handle—after the callback is attached—also will use this callback function.
The callback function specified in lpfnInternetCallback should have the following prototype:
void CALLBACK myCallback(HINTERNET hInternet, DWORD dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength);
When the callback function is called to report the status of an asynchronous operation, the hInternet and dwContext parameters give the Internet handle and context value used in the operation, and the reason for calling the function is given in dwInternetStatus. The data returned through lpvStatusInformation (of length dwStatusInformationLength) is dependent on the reason for the callback, given in dwInternetStatus. The following are possible values for dwInternetStatus:
- INTERNET_STATE_BUSY—Indicates network requests are being made.
- INTERNET_STATE_CONNECTED—Indicates the current connection state.
- INTERNET_STATE_DISCONNECTED—Indicates the connection is disconnected.
- INTERNET_STATE_DISCONNECTED_BY_USER—Indicates the connection is disconnected by user request.
- INTERNET_STATE_IDLE—Indicates no network requests are being made.
- INTERNET_STATUS_DETECTING_PROXY—Notifies the application that a Proxy has been detected.
- INTERNET_STATUS_HANDLE_CLOSING—The handle in hInternet has been closed.
- INTERNET_STATUS_HANDLE_CREATED—A new handle has been created by InternetConnect(). This occurs before the connection is established.
- INTERNET_STATUS_CLOSING_CONNECTION—The connection to the server is closing. lpvStatusInformation will be NULL.
- INTERNET_STATUS_CTL_RESPONSE_RECEIVED—Is not currently implemented.
- INTERNET_STATUS_CONNECTED_TO_SERVER—The connection to the server at the address specified in the SOCKADDR structure at lpvStatusInformation was successful.
- INTERNET_STATUS_CONNECTING_TO_SERVER—Connecting to the server specified by the SOCKADDR structure at lpvStatusInformation.
- INTERNET_STATUS_CONNECTION_CLOSED—The connection closed successfully. lpvStatusInformation will be NULL.
- INTERNET_STATUS_INTERMEDIATE_RESPONSE—An intermediate status code (100 level) was received.
- INTERNET_STATUS_NAME_RESOLVED—The name contained in lpvStatusInformation was resolved successfully.
- INTERNET_STATUS_PREFETCH—Not currently implemented.
- INTERNET_STATUS_RECEIVING_RESPONSE—Waiting to receive a response. lpvStatusInformation will be NULL.
- INTERNET_STATUS_REDIRECT—An HTTP request is about to be redirected to a new URL. lpvStatusInformation points to the new URL string.
- INTERNET_STATUS_REQUEST_COMPLETE—An asynchronous operation has completed. lpvStatusInformation points to an INTERNET_ASYNC_RESULT structure containing the dwResult and dwError fields. dwResult contains the value that was returned from the operation, and dwError contains the error code for the operation.
- INTERNET_STATUS_REQUEST_SENT—The request was sent successfully. lpvStatusInformation points to a DWORD holding the number of bytes sent.
- INTERNET_STATUS_RESOLVING_NAME—The name being resolved is contained in lpvStatusInformation.
- INTERNET_STATUS_RESPONSE_RECEIVED—A response was received successfully. lpvStatusInformation points to a DWORD holding the number of bytes received.
- INTERNET_STATUS_SENDING_REQUEST—A request is being sent to the server. lpvStatusInformation will be NULL.
- INTERNET_STATUS_STATE_CHANGE—Indicates a move between a secure and non-secure server.
- INTERNET_STATUS_USER_INPUT_REQUIRED— Indicates the request requires user input.
In many cases, your application may be concerned only with handling the completion of asynchronous operations, specified by a call to the callback function with a value of INTERNET_STATUS_REQUEST_COMPLETE passed in dwInternetStatus, although some operations may generate many other calls to the callback function. A call to InternetConnect(), for example, may generate a dozen or so different calls to the callback function. Because your callback may be called many times, you should try to minimize the operations performed within the callback. Spending excessive time in the callback, like displaying a dialog box, may cause some operations to time out before the callback returns.
Working with URLs
The WinInet API provides several functions that can be useful in simplifying the processing of URLs. You can parse a URL into its various components with InternetCrackUrl(), and you can use InternetCreateUrl() to create a URL string from the individual components. You can use the InternetCanonicalizeUrl() function to convert a URL to canonical form, as well as to convert any unsafe characters into escape sequences. You also can merge a base URL and a relative URL into a single URL string with InternetCombineUrl().
Basic File Operations
For many WinInet functions, you need to explicitly establish a connection (using InternetConnect()) before using the protocol-specific functions. However, the WinInet API does provide a simple method for retrieving data from an FTP, HTTP, or Gopher server in a somewhat generic manner using the InternetOpenUrl() function:
HINTERNET InternetOpenUrl(HINTERNET hInternetSession,
LPCTSTR lpszUrl, LPCTSTR lpszHeaders, DWORD dwHeadersLength,
DWORD dwFlags, DWORD dwContext);
Each call to InternetOpenUrl() establishes its own connection, so you do not need to create one explicitly with a call to InternetConnect(). However, you do need to pass a valid session handle returned from InternetOpen() in hInternetSession.
InternetOpenUrl() returns an Internet handle for the file requested by the URL string passed by lpszUrl. If this completes successfully, you can use this handle in calls to functions such as InternetReadFile(), as you will see shortly.
For HTTP requests, you can specify a pointer to an additional header string in the lpszHeaders. The length of this string should be passed in dwHeadersLength, although you can pass a length of -1 if the header's string is null-terminated—InternetOpenUrl() then figures out the length of the header's string.
The following are option flags that may be included in dwFlags:
- INTERNET_FLAG_DONT_CACHE means do not cache the data. The preferred method to use is INTERNET_FLAG_NO_CACHE_WRITE.
- INTERNET_FLAG_EXISTING_CONNECT attempts to use an existing connection if possible.
- INTERNET_FLAG_NO_CACHE_WRITE means do not cache the data.
- INTERNET_FLAG_RAW_DATA returns raw data (FIND_DATA structures). Otherwise, directories are returned in HTML formatting.
- INTERNET_FLAG_RELOAD reloads the file from the network, even if it is cached locally.
- INTERNET_FLAG_SECURE requests use of the Secure Sockets Layer or PCT for HTTP requests.
Querying Data Availability
If InternetOpenUrl() completes successfully, it returns an Internet file handle. You can check to see how much data is available for this file handle by calling InternetQueryDataAvailable(), which also can be used with the file handles returned by the protocol-specific functions that you will see later.
The InternetQueryDataAvailable() function takes an Internet file handle and a pointer to a DWORD where the number of bytes available will be written. Currently, the dwFlags and dwContext parameters must be 0:
BOOL InternetQueryDataAvailable(HINTERNET hFile,
LPDWORD lpdwNumberOfBytesAvailable,
DWORD dwFlags, DWORD dwContext);
InternetQueryDataAvailable() returns the amount of data that can be read immediately by a call to InternetReadFile(). If the end-of-file has not been reached and no data is immediately available for reading, this function blocks until data is available.
Reading Data
You can read data from a file handle with InternetReadFile(). This can be used for handles returned from InternetOpenUrl(), as well as handles returned from protocol-specific functions such as FtpOpenFile(), GopherOpenFile(), or HttpOpenRequest(). The following is the prototype for InternetReadFile():
BOOL InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
DWORD dwNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead);
InternetReadFile() attempts to read the number of bytes specified in dwNumberOfBytesToRead into the buffer at lpBuffer. Upon completion, the DWORD at lpNumberOfBytesRead contains the number of bytes actually read. If there is not enough data currently available to satisfy the request, it blocks until enough data is received. The only time the actual number of bytes requested will be less than the number requested is when the end-of-file has been reached.
Moving the File Pointer
You can move the file pointer for calls to InternetReadFile() by calling the InternetSetFilePointer() function:
BOOL InternetSetFilePointer(HINTERNET hFile, LONG IDistanceToMove,
PVOID pReserved, DWORD dwMoveMethod, DWORD dwContext);
The file handle passed in hFile can be any file handle returned from calls such as InternetOpenUrl() or FtpOpenFile(), with the exception that caching must be enabled for the handle—that is, it must not have been created with the INTERNET_FLAG_DONT_CACHE or INTERNET_FLAG_NO_CACHE_WRITE option.
The lDistanceToMove parameter specifies the number of bytes to move the file pointer from a location specified by dwMoveMethod, which can have the following values:
- FILE_BEGIN moves from the beginning of the file.
- FILE_CURRENT moves from the current position.
- FILE_END moves from the end-of-file.
Positive values of lDistanceToMove move forward in the file, and negative values move backward.
Currently, pReserved and dwContext must be 0. This operation always completes synchronously, although subsequent calls to InternetReadFile() may complete asynchronously.
Writing to Internet Files
For Internet file handles that have been opened with InternetOpenUrl(), as well as other functions such as FtpOpenFile(), you can write data to a file with the InternetWriteFile() function:
BOOL InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer,
DWORD dwNumberOfBytesToWrite, LPDWORD lpdwNumberOfBytesWritten);
This function will write the number of bytes in dwNumberOfBytesToWrite from lpBuffer to the file specified by hFile. On completion, the DWORD at lpdwNumberOfBytesWritten will contain the actual number of bytes written.
Note that the transfer may not be completed until you call InternetCloseHandle() to close the file handle and flush its buffers.
FTP Client Functions | Next Section

Account Sign In
View your cart