This tutorial describes how to create a status callback function that can be used to monitor the status of an Internet request that was initiated using the Microsoft® Win32® Internet functions.
Status callback functions receive status callbacks on any Internet requests that originated from any Win32 Internet function that was passed a nonzero context value.
Application developers who want to create a status callback function must have an understanding of C/C++ programming, a familiarity with Win32 programming, and a familiarity with the Win32 Internet functions.
To compile programs using any of the Win32 Internet functions, make sure the Wininet.h header file is in the include directory and the Wininet.lib library file is in the library directory of the C/C++ compiler you are using.
The following steps are necessary for creating a status callback function:
The context value can be any unsigned long integer value. Ideally, the context value should identify what request has just been completed and the location of any associated resources (if needed).
One of the most useful ways to use the context value is to pass the address of a structure and cast it as a DWORD. The structure can be used to store information about the request, so that it will be passed to the status callback function.
The following structure is an example of a possible context value. The members of the structure have been chosen with the InternetOpenUrl function in mind.
typedef struct{ HWND hWindow; // window handle int nStatusList // ID of the list box control to hold the callbacks HINTERNET hResource; // HINTERNET handle created by InternetOpenUrl char szMemo[512]; // string to store status memo } REQUEST_CONTEXT;
In this example, the status callback function would have access to the window handle, which would allow it to display a user interface; the HINTERNET handle created by InternetOpenUrl, which could be passed to another function that can download the resource; and an array of characters that can be used to pass information about the request.
The members of the structure can be changed to fit the needs of a particular application, so do not feel constrained by this example.
The status callback function must follow the format of INTERNET_STATUS_CALLBACK. To do this:
The following example shows a sample declaration.
void __stdcall CallMaster(HINTERNET, DWORD, DWORD, LPVOID, DWORD);
In general, using a switch function using dwInternetStatus as the switch value and the status values for the case statements works the best. Depending on the types of functions your application is calling, you can ignore some of the status values. For a definition of the different status values, see the listing under the dwInternetStatus parameter of INTERNET_STATUS_CALLBACK.
The following switch statement is an example of how to handle status callbacks.
switch (dwInternetStatus) { case INTERNET_STATUS_REQUEST_COMPLETE: // Some code. break; default: // Some code. break; }
The code to handle each of the status values depends heavily on what you are using the status callback function for. For applications that are just tracking the progress of a request, writing a string to a list box might be all you need. For asynchronous operations, the code must handle some of the data returned in the callback. For details on asynchronous operations, see the Calling Win32 Functions Asynchronously article.
The following status callback function uses a switch function to determine what the status value is and creates a string that includes the name of the status value and the previous function called (which is stored in the szMemo member of the REQUEST_CONTEXT structure).
void __stdcall CallMaster( HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength ) { // Copy that context value to a pointer so I don't have to keep // casting the context value as a REQUEST_CONTEXT pointer. REQUEST_CONTEXT *cpContext; cpContext = (REQUEST_CONTEXT*)dwContext; char szStatusText[80]; switch (dwInternetStatus) { case INTERNET_STATUS_CLOSING_CONNECTION: sprintf(szStatusText,"%s CLOSING_CONNECTION", cpContext->szMemo); break; case INTERNET_STATUS_CONNECTED_TO_SERVER: sprintf(szStatusText,"%s CONNECTED_TO_SERVER", cpContext->szMemo); break; case INTERNET_STATUS_CONNECTING_TO_SERVER: sprintf(szStatusText,"%s CONNECTING_TO_SERVER", cpContext->szMemo); break; case INTERNET_STATUS_CONNECTION_CLOSED: sprintf(szStatusText,"%s CONNECTION_CLOSED", cpContext->szMemo); break; case INTERNET_STATUS_HANDLE_CLOSING: sprintf(szStatusText,"%s HANDLE_CLOSING", cpContext->szMemo); break; case INTERNET_STATUS_HANDLE_CREATED: sprintf(szStatusText,"%s HANDLE_CREATED", cpContext->szMemo); break; case INTERNET_STATUS_INTERMEDIATE_RESPONSE: sprintf(szStatusText,"%s INTERMEDIATE_RESPONSE", cpContext->szMemo); break; case INTERNET_STATUS_NAME_RESOLVED: sprintf(szStatusText,"%s NAME_RESOLVED", cpContext->szMemo); break; case INTERNET_STATUS_RECEIVING_RESPONSE: sprintf(szStatusText,"%s RECEIVING_RESPONSE", cpContext->szMemo); break; case INTERNET_STATUS_RESPONSE_RECEIVED: sprintf(szStatusText,"%s RESPONSE_RECEIVED", cpContext->szMemo); break; case INTERNET_STATUS_REDIRECT: sprintf(szStatusText,"%s REDIRECT", cpContext->szMemo); break; case INTERNET_STATUS_REQUEST_COMPLETE: sprintf(szStatusText,"%s REQUEST_COMPLETE", cpContext->szMemo); break; case INTERNET_STATUS_REQUEST_SENT: sprintf(szStatusText,"%s REQUEST_SENT", cpContext->szMemo); break; case INTERNET_STATUS_RESOLVING_NAME: sprintf(szStatusText,"%s RESOLVING_NAME", cpContext->szMemo); break; case INTERNET_STATUS_SENDING_REQUEST: sprintf(szStatusText,"%s SENDING_REQUEST", cpContext->szMemo); break; case INTERNET_STATUS_STATE_CHANGE: sprintf(szStatusText,"%s STATE_CHANGE", cpContext->szMemo); break; default: sprintf(szStatusText,"%s Unknown Status %d Given", cpContext->szMemo, dwInternetStatus); break; } SendDlgItemMessage(cpContext->hWindow,cpContext->nStatusList, LB_ADDSTRING,0,(LPARAM)szStatusText); }
The following example demonstrates how to set a status callback function.
HINTERNET hOpen; // root HINTERNET handle INTERNET_STATUS_CALLBACK iscCallback; // holder for the callback function // Create the root HINTERNET handle. hOpen = InternetOpen("Test Application", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); // Set the status callback function. iscCallback = InternetSetStatusCallback(hOpen, (INTERNET_STATUS_CALLBACK)CallMaster);
The following tutorial covers one use of a status callback function:
The following references are related to status callback functions: