Visual C++ 6 Unleashed

Visual C++ 6 Unleashed

By MICKEY WILLIAMS and David Bennett

Using the WinInet C API

Before we get into the meat of the WinInet C API, let's take a look at some of the basic concepts used throughout the WinInet functions, such as the handle hierarchy with which the API functions work. You also will look at how the WinInet functions handle error codes and buffer passing, as well as how asynchronous operations are implemented, before moving on to the specific functions of the WinInet API used for FTP, HTTP, and Gopher communications.

Handles

Most of the WinInet functions use a special sort of handle, HINTERNET. This handle type is used to represent Internet sessions, individual connections, and the results of various open or find calls.

These handles are similar to the file handles used in other Win32 functions, although they are not interchangeable with base Win32 handles. You cannot use an HINTERNET handle in calls such as ReadFile(), for example, and you cannot use a handle returned from CreateFile() in calls to InternetReadFile().

One difference between the HINTERNET handles and other Win32 handles is the fact that Internet handles are arranged in a tree hierarchy. The session handle returned by InternetOpen() is the root of the tree, and connection handles returned from InternetConnect() branch from that root. The handles to individual files and search results then make up the leaves of the tree.

Handles can inherit attributes, such as the asynchronous mode settings, from the handle from which they were derived. You can take advantage of the hierarchy to close the handles for a whole branch of the tree in a single call to InternetCloseHandle()[md]if you close an Internet handle, any handles descended from it also will be closed.

Each HINTERNET handle can have many different options associated with it, depending on the specific type of handle. You can access these options with the InternetQueryOption() and InternetSetOption() functions. You use these functions to access information such as the specific type of handle, timeout settings, callback and context values, buffer sizes, and many other settings.

Error Handling

The functions that make up the WinInet API handle errors the same way the general Win32 functions do. The return value of the function tells whether the call was successful—functions that return a BOOL return FALSE when an error occurs, and functions that return an HINTERNET return NULL when an error occurs or a valid handle if the function succeeded.

In the event that a function fails, more specific error information is available by way of a call to GetLastError(). In addition, if GetLastError() returns ERROR_INTERNET_EXTENDED_ERROR, you can retrieve more information about failed operations with FTP or Gopher servers with a call to InternetGetLastResponseInfo().

For HTTP operations, you also can use the InternetErrorDlg() function to display a dialog box that explains errors to users and enables them to select several choices on how to handle the errors.

Passing Buffer Parameters

Many of the WinInet API functions return variable-length strings by way of a pointer (lpszBuffer) and the buffer length (lpdwBufferLength). If the buffer size passed is too small to hold the returned string (or the pointer is NULL,) the function fails, and GetLastError() returns ERROR_INSUFFICIENT_BUFFER. The value at lpdwBufferLength, however, is updated to reflect the total space needed, including the NULL terminator. You can use this value to allocate a new buffer and repeat the call. Note that when the call completes successfully, the value at lpdwBufferLength does not include the NULL terminator in its count.

Asynchronous I/O

By default, the WinInet API functions operate synchronously. This is convenient when you want to create a separate thread for each operation. In cases where you don't want a separate thread for each call, however, it is useful to handle request completion asynchronously, particularly for operations that may take an indeterminate amount of time to complete.

To enable asynchronous operation, you set the INTERNET_FLAG_ASYNC flag in a call to InternetOpen(). Any calls made on the returned session handle, or any handles derived from it, then may complete asynchronously. In addition, you must specify a callback function and a nonzero context value in order for a call to complete asynchronously.

A callback function is attached to a handle with a call to InternetSetStatusCallback(). This callback function then may be inherited by any handle derived from the handle passed to InternetSetStatusCallback(). The callback function is called by both synchronous and asynchronous functions to report the status of an operation. You will look at the callback function in more detail in "Adding a Callback Function" later in this chapter.

A context value may be passed to many of the WinInet functions. This may be used to identify the operation that has generated a call to the callback function. If you specify a context value of 0 to any function, it will operate synchronously, even if the INTERNET_FLAG_ASYNC flag is set.

When calling functions that may complete asynchronously, you always should check the return value, because it is possible that the operation will complete immediately. If an operation will complete asynchronously, the original function call will fail, and GetLastError() will return ERROR_IO_PENDING, which simply signifies that the operation will call the callback function when it completes.

Share ThisShare This

Informit Network