Click here to Skip to main content
15,884,099 members
Articles / Desktop Programming / MFC
Article

WinHttpGateway Library

Rate me:
Please Sign up or sign in to vote.
4.17/5 (4 votes)
30 Apr 2009CDDL13 min read 26.9K   2.2K   25  
WinHttp API wrapper library with asynchronous call mechanism and support of HTTPS protocol
Image 1

Introduction

The WinHttpGateway is a dynamic library to simplify a work with the WinHttp API. It is wrapper code for this API. WinHtpp API is a replacement of WinINet API (see About WinHTTP for more information of Microsoft recommends to use WinHttp API). Feature of the given library is usage of an asynchronous mode of data transfer. The library is used as dynamically connected module and gives the simple interface that it was possible to spend from any thread calls independent of another threads of http protocol. Also the library supports (at base level) the HTTPS protocol. The library can be used in services, to organize call on HTTP/HTTPS protocols.

The quick review of library usage.

Dynamic module export function

Since the library was developed as dynamically connected actually it exports only one function (that is a GetInterface).

extern "C" LPVOID __declspec(dllexport)
GetInterface() 
{
    return static_cast(&g_winhttplauncher);
}
//WinHttpGateway\HttpGateway.cpp 

Which returns the pointer on the interface which gives functionality of the given library. For convenience of usage in C ++ a code of the given library wrapper the interface IWinHttpLauncher (class CWinHttpLauncherStub which gives the call mechanism to dynamic WinHttpGateway.dll module). And for using of library it is enough to include the file WinHttpGateway.h. And then to connect to the library module you should create class CWinHttpLauncherStub.

Usage example can be looked in project WinHttpGatewayTest.

The elementary usage of WinHttpGateway.dll module.

int _tmain(int _argc, TCHAR* _argv[], TCHAR* _envp[])
{
            // initialize MFC and print and error on failure
            if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
            {
                        // TODO: change error code to suit your needs
                        cerr << _T("Fatal Error: MFC initialization failed") << endl;
                        return 1;
            }
 
            CWinHttpLauncherStub winhttp;
            CString sPath = _T("WinHttpGateway.dll");
            if(!winhttp.load(sPath) || !winhttp)
            {
                        CString mess;
                        mess.Format(_T("Can`t load %s"),(LPCTSTR)sPath);
                        ::AfxMessageBox(mess,MB_OK|MB_ICONERROR);
                        return 1;
            }
 
            CString sProxyURL = _T("");
            CString sBypass = _T("");
            CString sLogin = _T("");
            CString sPassword = _T("");
 
            DWORD dwErrCode = 0;
            LPTSTR szError = NULL;
            if(!winhttp.initilize(IWinHttpLauncher::PAT_NO_PROXY,sProxyURL,sBypass,&dwErrCode,&szError))
            {
                        CString mess;
                        mess.Format(_T("Initialization error code = %d \"%s\""),dwErrCode,szError);
                        ::AfxMessageBox(mess,MB_OK|MB_ICONERROR);
                        winhttp.free_string(szError);
                        return 1;
            }
 
            winhttp.set_options(
                        IWinHttpLauncher::Option_ProxyLogin
                        ,IWinHttpLauncher::OptionScope_Root
                        ,(LPVOID)(LPCTSTR)sLogin
                        );
            winhttp.set_options(
                        IWinHttpLauncher::Option_ProxyPassword
                        ,IWinHttpLauncher::OptionScope_Root
                        ,(LPVOID)(LPCTSTR)sPassword
                        );
 
            CString sUrl = _T("http://www.codeproject.com/info/about.aspx");
            CString sMethod = _T("GET");
            CString sHeaders = _T("");
            CString sData2Send = _T("");
 
            LPTSTR szHeaders = NULL;
            LPTSTR szContentType = NULL;
            LPTSTR szReadedData = NULL;
 
            if(!winhttp.request(
                                   sUrl,sMethod,sData2Send,sHeaders
                                   ,&szHeaders,&szContentType,&szReadedData
                                   ,&dwErrCode,&szError
                                   )
                        )
            {
                        CString mess;
                        mess.Format(_T("Request error [url=%s] code = %d \"%s\""),(LPCTSTR)sUrl,dwErrCode,szError);
                        ::AfxMessageBox(mess,MB_OK|MB_ICONERROR);
                        winhttp.free_string(szError);
                        return 1;
            }
 
            long i = 0;
            CString sReadedData = szReadedData;
            cout << _T("Data was readed") << endl;
            cout << _T("ContentType = ") << szContentType << endl;
            cout << _T("Data length ") << sReadedData.GetLength() << endl;
            cout << _T("Data:") << endl;
 
            for(i=0;i<sReadedData.GetLength();i+=256) cout << (LPCTSTR)sReadedData.Mid(i,256);
           
            winhttp.free_string(szHeaders);
            winhttp.free_string(szContentType);
            winhttp.free_string(szReadedData);
 
            return 0;
}

Source codes can be found in a folder “contest”. If it is used proxy a server it need to use other parameter at initialization and it is necessary to set URL a server proxy, and also a login and the password of the user (if is necessary).

The example of more difficult usage of library can be found in a test example (folder WinHttpGatewayTest). 

I will result the small description of interface IWinHttpLauncher.

Interface IWinHttpLauncher is documented in a code (file WinHttpGateway.h).

Enumerations.

enum ProxyAccessTypeEn – describes operating modes WinHttp API.

enum OptionsEn – describes options for customization WinHttp API, given for customization in the WinHttpGateway dynamic module. 

enum OptionScopeEn – sets a scope of an installed option (see section "The setting an options (configuration WinHttp API through WinHttpGateway)").

Functions.

void enable_tracing (BOOL _en) const – enables or disables tracing of WinHttp API (see WinHttpTraceCfg.exe, a Trace Configuration Tool for specification of details) 

BOOL check_platform () const – returns TRUE if the given operating system supports WinHttp API.

BOOL initilize (<br />IN ProxyAccessTypeEn
_proxyaccess<br />,IN LPCTSTR _proxyname<br />,IN
LPCTSTR _proxybypass<br />,OUT DWORD* _dwErrCode<br />,OUT
LPTSTR* _szError<br />);
– Function of initialization of WinHttpGateway module. It is possible to select to use a proxy server or not, to install URL of a proxy server, and also URL list for which it will be bypassed this proxy server. Further all calls will be carried out, using the sets values.

BOOL set_options(<br />IN OptionsEn _option<br />,IN
OptionScopeEn _scope<br />,IN LPVOID _lpdata<br />);
- Sets options for calls.

BOOL request(<br />IN LPCTSTR _szUrl<br />,IN
LPCTSTR _szMethod<br />,IN LPCTSTR _szData2Send<br />,IN
LPCTSTR _szHeaders2Send<br />,OUT LPTSTR*
_pszReadedHeaders<br />,OUT LPTSTR* _pszContentType<br />,OUT
LPTSTR* _pszReadedData<br />,OUT DWORD* _dwErrCode<br />,
OUT LPTSTR* _pszError<br />);
– Carries out synchronous call to the URL, set in the parameter _szUrl, by method _szMethod, with the data for transmission _szData2Send, and headers for transmission _szHeaders2Send. But it is important that at call from parallel threads independent calls (requests will be made simultaneously and independently) will be carried out.

BOOL request(<br />IN LPCTSTR _szUrl<br />,IN
LPCTSTR _szMethod<br />,IN LPCTSTR _szData2Send<br />,IN
LPCTSTR _szHeaders2Send<br />,IN LPCTSTR _szXSLTFName<br />,OUT
LPTSTR* _pszReadedHeaders<br />,OUT LPTSTR*
_pszContentType<br />,OUT LPTSTR* _pszReadedData<br />,OUT
LPTSTR** _ppszTagNames<br />,OUT LPTSTR**
_ppszTagValues<br />,OUT DWORD* _dwErrCode<br />,OUT
LPTSTR* _pszError<br />);
– Similarly previous function, but the answer from a server if it has type 'text/xml' will be returned in the form of two lists of strings (in the first list will be returned names of tags, in the second values of these tags). Also the returned data can be handled with the help of xslt conversions (parameter _szXSLTFName, setting a filename of xslt conversions (xstl file)).

void enum_certificates(<br />OUT LPTSTR**
_ppszStorage<br />,OUT LPTSTR** _ppszName<br />);
– Returns the list of the installed certificates in system. For the use of this names for installation of the used certificate for realization of calls on https (through function set_options()).

Above described functions, return TRUE if call is made successfully and FALSE in other case. In case of an error the text error message comes back in parameter _pszError, and an error code in parameter _dwErrCode.Some error codes are defined for WinHttpGateway module (see file WinHttpGateway\messages.mc) the others belong the API of operating system, including WinHttp API. Also if function returns pointers on strings or on arrays of strings they need to be freed on the client side. To release this selected data it is better to usefree_list() and free_string() functions of class CWinHttpLauncherStub.

Class CWinHttpLauncherStub.

It is intended to present the WinHttpGateway dynamic module for the programmer in the form of a class.

Functions.

bool load(LPCTSTR _szDllName) – loads WinHttpGateway module into the memory, receives the interface for operation with this dll module.

void unload() – unloads WinHttpGateway (dll module).

operator bool() - gives the information of validity of class CWinHttpLauncherStub. A class valid if the module is successfully loaded and it is possible to call the functions given by interface IWinHttpLauncher of this module. The class is inherited from interface IWinHttpLauncher and readdresses to the loaded dynamic module calls if it is loaded (or only outputs assert and don`t make any calls).

static void free_list(LPTSTR* _ppsz) – function releases the memory selected for the list of string values, the functions of interface IWinHttpLauncher received by calls (WinHttpGateway module).

static long get_listlength(LPTSTR* _ppsz) – function returning length of the list of string values returned by interface IWinHttpLauncher functions (WinHttpGateway module).

static void free_string(LPTSTR _psz) – the function releasing memory selected for string value in WinHttpGateway module and returned to a code that use this module.

More information about the library.

The setting an options (configuration WinHttp API through WinHttpGateway).

Since the usual circuit of creation/use the WinHttpGateway module the creation of class CWinHttpLauncherStub in one (usually main thread), and further parallel usage in different threads (workflows) the setter of a scope of installed options is provided. Therefore distinguish root options (options which can be used, as options by default, in all threads) and options of a current thread which are used only in this thread. I.e. if in any thread use some option as the option by default, not the current thread option than this option takes from root options set (by default they initialized by default values (see file WinHttpGateway\WinHttpGateway.h, the description of listing OptionsEn for specification of such values)).

The internal view of library.

The short description of classes (in alphabetic order).

class CAutoLock - a class realizing automatic locking for some code snippet with usage of a critical section.

template class CAutoRefPtr - a template class for implementation of intellectual pointers of the data. In a code this template class is used for support of separate parts of the data received on demand.

struct CBuffer – the data buffer. It is intended (at present) for internal data storage. Realizes data conversions for usage of this data in different representations.

class CCertificate – a class for presentation of certificates. Stores a name of storage of the certificate and a certificate name, and also gives PCCERT_CONTEXT for certificate representation in system.

class CCertificates – the list of certificates. The list is formed of all certificates installed on the computer for the given user or the computer (the data about a possible set is extracted from the register).

struct CHttpVersionInfo – structure is a wrapper of system structure HTTP_VERSION_INFO.

class CmpStrNoCase – a class extending the CString class and supporting matching without case sensitivity.

class CPassword – a class for password representation.

template class CPropertyBase – a template class for implementation of a class of options from fundamental types of the data.

class CPropMassAction – realizes operations over all options.

class CPropMassActionIni – extends CPropMassAction and realizes saving/loading of options in/from the register.

struct CRefCounter – a base class of count of references.

struct CUrlComponents – a wrapper of system structure URL_COMPONENTSW.

class CWinHttp – an asynchronous class operation with WinHttp API.

struct CWinHttp::CRequestInfo - an information set about request.

struct CWinHttpAsyncResult – a wrapper for system structure WINHTTP_ASYNC_RESULT.

struct CWinHttpAutoproxyOptions – a wrapper for system structure WINHTTP_AUTOPROXY_OPTIONS.

struct CWinHttpCertificateInfo – a wrapper for system structure WINHTTP_CERTIFICATE_INFO.

struct CWinHttpCurrentUserIEProxyConfig – a wrapper for system structure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG.

class CWinHttpError – a class an exception used in the WinHttpGateway module.

class CWinHttpGatewayApp - a class of module implementation.

class CWinHttpLauncher - implementation of the unit for data reading under the circuit: one thread one request. Internal implementation of interface IWinHttpLauncher.

class CWinHttpLauncherStub – a wrapper (for the programmer – users of the WinHttpGateway module) interface IWinHttpLauncher. The class is intended for simplification of operation with WinHttpGateway module from a client code.

class CWinHttpLog – file implementation of a log of WinHttpGateway module.

struct CWinHttpProxyInfo – a wrapper of system structure WINHTTP_PROXY_INFO.

struct CWinHttpRequest – implementation of one request.

struct CXSLTFile – a class for support of pooling of xslt files for optimisation of conversions.

class CXSLTProcessor – the processor of the data. Realises xslt conversion.

template class IniAccessorBase – a template class for implementation traits of the data which are used as an option.

template class IniAccessorMassAction – template implementation of the mechanism (strategy) of saving of the data for options in a ini file.

interface IWinHttpLauncher – the interface for call with WinHttpGateway module

interface IWinHttpRequest – the interface for operation with the one request.

template class NullAccessorAction – template implementation of the mechanism (strategy) null savings of the data (don`t save/load anything).

The review of functioning of library

Class of the interface IWinHttpLauncher.

class CWinHttpLauncher – is internal implementation of interface IWinHttpLauncher with which help functionality of library WinHttpGateway is given. The given class stores in itself a set of options, for support of configuration WinHttp API. The reference to class CWinHttp which realizes directly operation with WinHttp API (realizing the mechanism of asynchronous calls). And also the list of certificates a variable of class CCertificates which is used for storage and data representation about certificates in system for support of operation with certificates in WinHttpGateway module.

At initialization phase is created an object of class CWinHttp which is used further for the organization of requests.

The main works of this class occurs in functions request(). In it there is an object of class CWinHttpRequest, is initialized, transferred in class CWinHttp and simply waits the end of this request (line: request.waitEOR();).

Setting of options occurs through function set_options() which simply sets value of the internal variable storing the list of options. (The error comes back through SetLastError(), and can be received by calling of GetLastError() function, if set_options() has returned value FALSE).

A class of a kernel of operation with WinHttp API

class CWinHttp - is a basis of functioning of the given library. It will organize asynchronous processing of requests: installation of function of a callback, support of callbacks, data transfer, waiting of possibility of data transfer, saving/accumulation of the data received by call. And also support of processing of some errors which the given module automatically can handle and to inform the user of WinHttpGateway module only at impossibility automatically to handle this errors.

As operation to be made asynchronously almost all works of a class consists in operation callback functions CWinHttp::WinHttpStatusCallback() which calls initiate all operation of WinHttpGateway module on operation with HTTP/HTTPS requests. We will consider messages from WinHttp API and functions which handle these messages.


WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
WINHTTP_CALLBACK_STATUS_REDIRECT
WINHTTP_CALLBACK_STATUS_RESOLVING_NAME

Are handled by function CWinHttp::RequestStatus() which simply hands over the information on the status to a class of request CWinHttpRequest.


WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
WINHTTP_CALLBACK_STATUS_HANDLE_CREATED

– Are not handled.


WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE

It is handled by function CWinHttp::RequestDataAvailable(). The given message comes in the presence of the data for reception or for informing that no more data will be available. If all data is transferred (the size == 0) the request will be closed and it processing will be ended. If the size is more then zero, then the buffer will be created, and function for query of the data of request will be called from WinHttp API.


WINHTTP_CALLBACK_STATUS_HEADERS_AVAILAB

It is handled by function CWinHttp::RequestHeadersAvalable(). The given function supports possibility of authentification both: from a site, and from a proxy server if a proxy server or a site request such operations.

If authentification it is not necessary, the header of the come data is simply requested. And further the size of the data for reading of this request is requested.

As "errors" which can be handled WinHttpGateway module (Is the query of the certificate and necessity to transfer request repeatedly ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED, ERROR_WINHTTP_RESEND_REQUEST) are in addition handled.


WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE

It is handled by function CWinHttp::RequestIntermediateResponse(), which in other does nothing.


WINHTTP_CALLBACK_STATUS_READ_COMPLETE

It is handled by function CWinHttp::RequestReadComplete(). Which transfere the buffer from the status “reading of the data”, in the status “the data was readed” and query a new chunk of data.


WINHTTP_CALLBACK_STATUS_REQUEST_ERROR

It is handled CWinHttp::RequestError(). The given function handles errors which WinHttpGateway module can handle, or forms error message which are transferred to the object of class CWinHttpRequest, representing the request data.


WINHTTP_CALLBACK_STATUS_SECURE_FAILURE

It is handled by function CWinHttp::RequestSecureFailure(). The given function instal ignoring of some errors for operations with certificates.


WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE

It is handled by function CWinHttp::RequestSendCompleted(). The given message comes, if the dispatched query consists of several parts and the given function forces transmission of consecutive number of pieces of the data. If all data is sent, data receiving is initiated.


WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE

It is handled by function CWinHttp::RequestWriteCompleted(), which is almost exact copy of function CWinHttp::RequestSendCompleted(), possessing the same functionality.


Other functions.

CWinHttp::create() – creates request under its description by the pointer on the object of class CWinHttpRequest which is transferred as parametre of the given function. In this function there is an analysis of URL of request, opening of the request and sending it.

CWinHttp::Send() – sends request. How it is necessary to dispatch request (from the data about errors and/or messages from WinHttp API), the given function install the given authentifications and then dispatches request (also and repeatedly).

CWinHttp::set_Certificate() – frames operation on installation of the certificate for some request.

CWinHttp::add_request(), CWinHttp::find_request(), CWinHttp::remove_request() – support functions: request addition in the internal list of requests, search of the necessary request on its descriptor, and also request removal (the termination of operation with request).

void CWinHttp::free() – function of a stop of operation of the object of class CWinHttp

Attention: customization of possible level of safety on operation with certificates it is possible/is necessary to make at CWinHttp::RequestSecureFailure().

An request class

struct CWinHttpRequest – a class giving request. This class implements interface IWinHttpRequest which is used in class CWinHttp for operation with request. The class is intended for a request configuration at a phase before its transmission to class CWinHttp and further for data acquisition on demand.

Attention: at present it is not realized any mechanisms of synchronization of this class.

Other classes.

template class CPool – a template class for the organization of a pool. Classes of objects of a pool must be inherited from a class template struct Construct which imposes certain agreements for a pool data item.

 

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Software Developer
Belarus Belarus
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --