Using WinInet

Recall that in order to start a new Internet session through WinInet, you must first get an Internet handle. Note that HINTERNET handles are not the same as file system handles, and cannot be used with other functions outside of the WinInet API.

There are basically four steps in performing any operation through WinInet:

  1. Open a new Internet session by using the InternetOpen() function. A HINTERNET connection handle for your current session is returned if successful.

  2. Connect to a server using the InternetOpenUrl() or InternetConnect() functions. You will be returned a connection HINTERNET handle for your new connection if successful.

  3. Perform the necessary protocol-specific operations to send and receive data (see the sections "Hypertext Transfer Protocol (HTTP and HTTPS)" and "File Transfer Protocol (FTP)").

  4. Close your HINTERNET handles in reverse order. This is important because Internet handles are hierarchical?you must close your connection HINTERNET handle (which was derived from InternetOpenUrl() or InternetConnect()) before you call InternetCloseHandle() on your main Internet session.

To create a new Internet session, you must call the InternetOpen() function:

HINTERNET InternetOpen(LPCWSTR lpszAgent, DWORD dwAccessType,
   LPCWSTR lpszProxy, LPCWSTR lpszProxyBypass, DWORD dwFlags);

When you call this function, the lpszAgent parameter is a string that contains the name of the application creating the session, and will be sent as the User-Agent header value on HTTP requests. The next parameter describes how your connection will be established with the server. The dwAccessType parameter can be set to one of the following:

  • INTERNET_OPEN_TYPE_DIRECT if you are making a direct connection to the server.

  • INTERNET_OPEN_TYPE_PROXY if you are going to be using a proxy server to connect to a server.

  • INTERNET_OPEN_TYPE_PRECONFIG to get the configuration information from the registry. This will use the information that the user has configured in Pocket Internet Explorer for his or her Internet connection.

To set the name of the proxy server, use the lpszProxy parameter. This value can be NULL if there is no proxy server. The next parameter, lpszProxyBypass, is ignored by Pocket PC and should be set to NULL. Finally, the dwFlags parameter can be set to INTERNET_FLAG_ASYNC to enable asynchronous (nonblocking) mode on the InternetReadFile() and InternetQueryDataAvailable() functions when a callback is configured with the InternetSetStatusCallback() function. If everything works correctly, InternetOpen() should return a valid HINTERNET handle for your session.

In order to receive data asynchronously (if you used the INTERNET_FLAG_ASYNC flag), you must also set up a callback routine:

INTERNET_STATUS_CALLBACK InternetSetStatusCallback
   (HINTERNET hInternet, INTERNET_STATUS_CALLBACK
   lpfnInternetCallback);

The first parameter is the handle to the Internet session you just created, and lpfnInternetCallback is a pointer to the address of an INTERNET_STATUS_CALLBACK function, which you write using the following prototype:

void CALLBACK INTERNET_STATUS_CALLBACK(HINTERNET hInternet,
   DWORD dwContext, DWORD dwInternetStatus, LPVOID
   lpvStatusInformation, DWORD dwStatusInformationLength);

When this function is called, you are passed the handle of the Internet session calling the callback, as well as an application-defined context value in the dwContext parameter (which you set when calling InternetConnect() or InternetOpenUrl()). The next parameter, dwInternetStatus, is the most important one, as it contains the status code for which the callback is being called (and is defined in wininet.h). The final two parameters, lpvStatusInformation and dwStatusInformationLength, contain the size and buffer for any additional callback information. The return value is INTERNET_INVALID_STATUS_CALLBACK if the callback could not be created.

Now that you have completed setting up your Internet session, let's open a connection to a server. This can be accomplished by using the InternetConnect() and InternetOpenUrl() functions. Which function you use depends on what information you have about the server with which you are trying to connect. If you have all the connection information for your server in a well-formed URL address, use InternetOpenUrl(); otherwise, InternetConnect() is probably your better option.

The InternetConnect() function is defined as follows:

HINTERNET InternetConnect(HINTERNET hInternet, LPCWSTR
   lpszServerName, INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
   LPCWSTR lpszPassword, DWORD dwService, DWORD wFlags, DWORD
   dwContext);

The first parameter is the handle to your Internet session, followed by lpszServerName, which is a null-terminated string containing the host name of the server with which you want to connect. This can also be an address in dotted notation, such as 10.0.5.50. The next parameter, nServerPort, is the server port with which you want to connect. It can be any IANA port or one of the defaults for a specific protocol: INTERNET_DEFAULT_FTP_PORT (port 21), INTERNET_DEFAULT_HTTP_PORT (port 80), INTERNET_DEFAULT_HTTPS_PORT (port 443), or INTERNET_DEFAULT_SOCKS_PORT (port 1080).

The next two parameters, lpszUserName and lpszPassword, are null-terminated strings that set up authorization on the server and that InternetConnect() will use to log on with. If both the username and password parameters are NULL, it will use the system default of "Anonymous" for the username, and the client's e-mail address for the password. The dwService parameter specifies the protocol you want to use, and can be either INTERNET_SERVICE_FTP or INTERNET_SERVICE_HTTP. If you want an FTP connection in passive mode, you need to set the wFlags parameter to INTERNET_FLAG_PASSIVE; otherwise, it can be set to 0. Finally, to associate an application-defined context value with the connection handle, use the dwContext parameter. If everything proceeds smoothly, you will be returned a HINTERNET handle once a connection is opened; otherwise, a NULL will indicate failure.

If you already have the server information in URL format, it's a lot easier to use the InternetOpenUrl() function to create a connection. InternetOpenUrl() will parse the address, protocol, username, and password from the URL for you; it is defined as follows:

HINTERNET InternetOpenUrl(HINTERNET hInternet, LPCWSTR
   lpszUrl, LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD
   dwFlags, DWORD dwContext);

The first parameter is the handle to your Internet session, followed by lpszUrl, which is a null-terminated string containing the server URL. Pocket PC supports only URLs that point to FTP, HTTP, or HTTPS addresses. If you are using HTTP, the next parameter, lpszHeaders, is used if you want to add any additional header strings to the HTTP connection. Use dwHeadersLength to specify the size of any added headers. The dwFlags parameter contains any additional option flags for the request, and it can be set to INTERNET_FLAG_RAW_DATA, INTERNET_FLAG_RELOAD, or INTERNET_FLAG_SECURE.

The INTERNET_FLAG_RAW_DATA option is only for FTP requests. If set, directory data will be returned to a WIN32_FILE_DATA structure (the same that is used with FindFirstFile()), instead of an HTML representation of the directory. INTERNET_FLAG_RELOAD forces the request to get information over the Internet without looking at the local cache. Finally, you can use INTERNET_FLAG_SECURE if you want to establish an HTTPS connection. The final parameter, dwContext, works the same as in the InternetConnect() function. Once a connection is opened, you will be returned an HINTERNET handle for the connection, or NULL if the connection failed.

Once you are finished with an Internet connection or session, you can close any HINTERNET handle by using the InternetCloseHandle() function:

BOOL InternetCloseHandle(HINTERNET hInternet);

Remember that HINTERNET handles derive from their parent, so you will want to close the handles returned to you from InternetConnect() and InternetOpenUrl() before closing the main Internet session handle that was returned from InternetOpen().

Let's look at a short example of how you can set up a basic WinInet session to connect to Microsoft's Web site using InternetConnect() and InternetOpenUrl():

HINTERNET hInternet = NULL, hIConnect = NULL, hIUrlConnect =
  NULL;

// First, open the Internet connection
hInternet = InternetOpen(TEXT("Sample Application"),
  INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);

// Make sure there are no errors
if(!hInternet)
   return FALSE;

// Next, connect to the Internet via InternetConnect
hIConnect = InternetConnect(hInternet, TEXT("www.
   microsoft.com"), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
   INTERNET_SERVICE_HTTP, 0, 0);

// Here would go your functions to download data

// Finally, close the handle
InternetCloseHandle(hIConnect);

// -OR- Connect to the Internet via InternetOpenUrl
hIUrlConnect = InternetOpenUrl(hInternet, TEXT("http://www.
  microsoft.com"), NULL, 0, 0, 0);

// Here would go your functions to download data

// Finally, close the handle
InternetCloseHandle(hIUrlConnect);

// Remember to close the main Internet open handle when you
// are complete.
InternetCloseHandle(hInternet);

One last note: If your application needs to make multiple Internet requests, you can typically make a single call to InternetOpen(), and continuously reuse the HINTERNET session handle for various InternetConnect() and InternetOpenUrl() connections. Naturally, if your basic connection type (i.e., your proxy connection) needs to change between each connection, you can always call InternetOpen() again to get a new session handle.