Click here to Skip to main content
13,348,514 members (94,166 online)
Click here to Skip to main content
Add your own
alternative version


58 bookmarked
Posted 12 Apr 2008

WinINet Test Application

, 12 Apr 2008
Rate this:
Please Sign up or sign in to vote.
A WTL application to test asynchronous WinINet functionality.


This is a WTL program that is able to test connections with web servers using just about every possible combination of requirements that are commonly encountered. The program is able to connect:

  • POST or GET
  • SSL
  • supply personal certificate, if required by the web server
  • vary receive time out
  • supply username/password for web server
  • ignore bad CA certificates

The program uses asynchronous WinINet calls to handle all communication and reporting. The program also demonstrates how to allow the user to select a personal certificate from the My store.


I put this program together to help test some issues I encountered with an unusual firewall configuration and web server security requirements. The output from the WinINet call back routine is very helpful when debugging connection issues. I have placed a number of messages in the ATLTRACE macro output as well as the main dialog of the program. While example code for most of the operations can be found in a variety of locations, I needed to tie everything together into a single application, implemented with consistent error handling.

The program started as an amalgamation of several samples from Microsoft. After a few hours of coding and a quick port to WTL, the application was pretty well gutted and rewritten. I need to give credit where credit is due for this application: the Microsoft examples saved me a lot of time (except when they were wrong or incomplete and cost me a lot of time).

Using the Code

The code is very simple to use. Simply download the demonstration and compile it. I am using WTL 8.0 with VS 2005. You may need to download WTL.

This is a WTL modal dialog application. I used some wait functions developed by Andy Smith to get around blocking issues when a modal dialog is utilized. You'll really want to examine the main WinINet loop, located in SendRequest. Here, you will learn how to handle ERROR_INTERNET_INVALID_CA, ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED, and HTTP_STATUS_DENIED. The WinInetCallback method is utilized to supply information like personal certificates or user name and password for resubmission to the web server and pass communication errors to the WinINet loop in SendRequest via the context variable.

Obtaining a Pointer to a Personal Certificate

There are times when you may need to allow a user to select a personal certificate. For instance, you are writing an application that uses WinINet. Here is some simple code that allows a user to select from a list of personal certificates loaded in their certificate store:

#include <span class="code-keyword"><prsht.h></span>
#include <span class="code-keyword"><cryptuiapi.h></span>


HCERTSTORE        m_hMyStore;
PCCERT_CONTEXT    m_pHSCertContext;


// Open the 'MY' certificate store to be presented to the user
if(!(m_hMyStore = CertOpenStore(
    // Let the user know we could not open the store.
    CString tMsg, tTitle;
    GetErrorMessage(GetLastError(), &tMsg);
    MessageBox((LPCTSTR) tMsg, 
               (LPCTSTR) tTitle.LoadString(IDS_TITLEFAILED), 
    return FALSE;
    // If we get to this stage, the certificate store
    // was opened successfully.
    // Display a selection of certificates to choose from.
    m_pHSCertContext = CryptUIDlgSelectCertificateFromStore(

//Show an error if a certificate is not seleted.
if (!m_pHSCertContext)
    CString tMsg, tTitle;
    MessageBox((LPCTSTR) tMsg.LoadString(IDS_ERR1), 
               (LPCTSTR) tTitle.LoadString(IDS_ERRT1), 
    return FALSE;

Supplying a Personal Certificate on a WinINet Handle

TCP/IP communications are a little tricky, in that you cannot supply the certificate when you make the request. You need to call OpenRequest, and then wait for the INTERNET_STATUS_REQUEST_COMPLETE signal in your Callback routine. You can then check the returned error, looking for ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED in the INTERNET_ASYNC_RESULT struct. When you get the error, you need to use InternetSetOption on your OpenRequest handle to supply the certificate and then repeat the OpenRequest. It's really pretty simple. It's just that the docs and samples leave out a lot of the error checking and recovery work that you need. It helps to have a server setup with a valid SSL certificate and require personal certificates in order to connect. Here is a code fragment for handling ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:

        //check for errors
            // The server requires a certificate

            // Save dwError so we can act on it.
            cpMainDlg->m_dwError = pRes->dwError;
            sMsg.Format("%s: CLIENT_AUTH_CERT_NEEDED (%d)", 
                        cpMainDlg->m_szMemo, pRes->dwError);

            // Check that we have a certificate pointer,
            // otherwise, it's time to fall over dead.
            if(cpMainDlg->m_pHSCertContext == NULL)
                //write the callback information to the buffer
                sMsg += _T(" No cert provided by user");
                // We have a pointer (there's no guarantee it's valid)
                // We have to be careful and check all returns for errors
                // as the pointer could point to la-la land if someone in
                // a different thread has closed the certificate store.

                // Attempt to set the option
                if (!::InternetSetOption( cpMainDlg->hRequest,
                    (LPVOID) cpMainDlg->m_pHSCertContext,
                    sizeof(CERT_CONTEXT) ))
                    // Display the error.
                    CString sErrMsg;
                    cpMainDlg->GetErrorMessage(GetLastError(), &sErrMsg);
                    sMsg += _T(" ");
                    sMsg += sErrMsg;
        } // end if (ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED == dwError)

Future Plans

I will add authentication handling for proxy servers in a future revision. Currently, only one set of credentials may be supplied, but the program needs to allow for two sets of credentials, one for the proxy server and one for the web server. I also want to add a file attachment dialog for testing the POST method with binary data or pseudo form data attached.


  • Version 1.0 - First release.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Gene OK
Business Analyst Southwest Research Institute
United States United States
I am a C++ coder. I am also proficient with Oracle PL/SQL. A lot of folks dislike Oracle, but I find Oracle is a significant revenue enhancer. Customers pay for first rate Oracle programming skills.

I have extensive experience with COM+, COM, ATL, WTL and installation package development. I've developed several packages in C#, but I prefer managed/native C++. I've been coding for nearly thirty plus years, getting my start with atomic and molecular orbital calculations in FORTRAN. I've been working with C or C++ since the days of QuickC, Desmet C, Datalight C and MSC 5.1.

One of my pet peeves in life is a programmer's lack of attention to the details of error handling. Most example code I see on the internet lacks depth. No use of Window's Event Logging and a lack of understanding as to how to handle exceptions. If folks actually think about how to properly debug and test, there would be fewer "slop" articles and a lot higher quality.

Including instrumentation in your software to allow proper diagnosis of failures is far more important to a user than the latest Gee-Whiz-Bang visual effects. Graphical gotta-haves fade like the lettuce in a refrigerator, but solid programs just keep on running, no matter what environment they are placed in.

My Web Site, Blog & Wiki

You may also be interested in...


Comments and Discussions

QuestionMalicious users Pin
peter.roca10-Mar-15 8:05
memberpeter.roca10-Mar-15 8:05 
AnswerRe: Malicious users Pin
Gene OK25-Jul-16 3:14
memberGene OK25-Jul-16 3:14 
GeneralMy vote of 5 Pin
Yiannis Spyridakis5-Nov-11 4:54
memberYiannis Spyridakis5-Nov-11 4:54 
GeneralMy vote of 5 Pin
lyricC8-Oct-10 16:34
grouplyricC8-Oct-10 16:34 
GeneralThanks! Pin
Volodymyr Metlyakov24-Feb-09 4:43
memberVolodymyr Metlyakov24-Feb-09 4:43 
kellykwai15-Sep-08 1:15
memberkellykwai15-Sep-08 1:15 
CodeWizard195115-Sep-08 5:32
memberCodeWizard195115-Sep-08 5:32 
The web server has to be setup to accept personal certificates.

You have to wait for the server to request the personal certificate. You cannot send the certificate with the initial Send Request.

Both the client and server must be setup to recognize the certificate authority used to generate the certificate.

The certificate you are using must be created for personal use. You cannot use a test certificate generated for use with a web server as a personal certificate.

I am not sure of the source of your error, but my guess is there is something wrong with your certificate, or your machine does not recognize the certificate authority.


-- Life is not a spectator sport. I came to play.
My Web Site, Blog & Wiki

kellykwai15-Sep-08 6:09
memberkellykwai15-Sep-08 6:09 
CodeWizard195115-Sep-08 6:21
memberCodeWizard195115-Sep-08 6:21 
kellykwai15-Sep-08 6:55
memberkellykwai15-Sep-08 6:55 
kellykwai17-Sep-08 2:03
memberkellykwai17-Sep-08 2:03 
CodeWizard195117-Sep-08 2:51
memberCodeWizard195117-Sep-08 2:51 
kellykwai17-Sep-08 3:20
memberkellykwai17-Sep-08 3:20 
CodeWizard195117-Sep-08 4:17
memberCodeWizard195117-Sep-08 4:17 
kellykwai17-Sep-08 6:55
memberkellykwai17-Sep-08 6:55 
CodeWizard195117-Sep-08 8:33
memberCodeWizard195117-Sep-08 8:33 
kellykwai17-Sep-08 17:45
memberkellykwai17-Sep-08 17:45 
kellykwai21-Sep-08 23:35
memberkellykwai21-Sep-08 23:35 
QuestionHow to get response message? Pin
kellykwai9-Sep-08 21:35
memberkellykwai9-Sep-08 21:35 
GeneralNo certificates are showed Pin
kellykwai9-Sep-08 1:42
memberkellykwai9-Sep-08 1:42 
GeneralRe: No certificates are showed Pin
CodeWizard19519-Sep-08 2:02
memberCodeWizard19519-Sep-08 2:02 
GeneralCompile problem Pin
Anders Karlsson18-Jun-08 6:11
memberAnders Karlsson18-Jun-08 6:11 
AnswerRe: Compile problem Pin
CodeWizard195118-Jun-08 6:50
memberCodeWizard195118-Jun-08 6:50 
QuestionProxy Authentication w/ Wininet ...Can it be Done???? Pin
V3RO12-May-08 9:31
memberV3RO12-May-08 9:31 
AnswerRe: Proxy Authentication w/ Wininet ...Can it be Done???? Pin
CodeWizard195112-May-08 10:09
memberCodeWizard195112-May-08 10:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180111.1 | Last Updated 12 Apr 2008
Article Copyright 2008 by Gene OK
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid