Click here to Skip to main content
12,885,669 members (40,122 online)
Click here to Skip to main content
Add your own
alternative version


181 bookmarked
Posted 14 Nov 2006

Compiling and Integrating Crypto++ into the Microsoft Visual C++ Environment

, , 5 May 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Avoid common pitfalls when using Crypto++ and VC++.


The Crypto++ User Group occasionally receives questions on Crypto++ and Microsoft's environments. The questions are usually basic such as, "VC++ can't find a header file - how [where] do I..." or a more ambiguous statement, "I can't compile." This article will attempt to resolve these common issues and provide basic background information.

Source Code

The Crypto++ source code can be downloaded from the Crypto++ homepage. If the website is down, use the SourceForge page, or use an archiving service such as here.


There are three sources of documentation for Crypto++: the source code, the wiki, the Users Group. The Crypto++ wiki can be found here. The wiki has many topics with lots of sample code. The Crypto++ Users Group can be found on Google Groups at

An online version of the source code can be found at the Crypto++ Library Reference Manual and Crypto++ Class Index. Dennis Bider has authored a User Guide and help file which can be found here. Bider's help guide is a bit dated, but many concepts still apply.


The Crypto++ library includes benchmarking capabilities through the test harness using the 'cryptest b' command line. In addition, the benchmark can take arguments such as bounding time for each test and the CPU speed. See usage.dat for details or run 'cryptest' with no arguments.

There are at least three published results of benchmarking available on the web. See Crypto++ 5.5 Benchmarks, Speedtest and Comparsion of Open-Source Cryptography Libraries and Compiler Flags, and eBACS: ECRYPT Benchmarking of Cryptographic Systems.

Windows Mobile

Ugo Chirico maintains a port of Crypto++ 5.5.2 to Windows Mobile 2005 at Crypto++ 5.5.2 on Windows Mobile 2005. Dr. Chirico posts announcements to the Crypto++ user group. His initial post can be found at Crypto++ Users.

In addition, a Windows Mobile port is now included on the Crypto++ wiki located at


An iOS port of Crypto++ is available on the wiki at The wiki pages discusses changes for iPhone, iPad, and iPod Touch. According to, an alignment issue exists in the Panama self test of the test suite.

Managed Code

There are no special steps required when using managed code. Note that if we are using the FIPS DLL, we might find that some functionality is missing (see the discussion below). For a well written example, see Mike Sinclair's article, RSA Encryption with .NET 2.0 Cryptography Services and Crypto++ Wrapped as a Managed C++ Class Library.

FIPS Compliance

FIPS 140-2 certification means the library produces correct results and complies with certain cryptographic protocols. Protocols would include zeroing the memory of key material after the library is finished using it. When we refer to the FIPS compliant DLL, we will state FIPS DLL.

The FIPS DLL must be used in binary form as distributed by Wei (even though we have the source code and can build the same binary). This means we cannot build the Crypto++ DLL and claim it is FIPS compliant.

Version 5.5.2 is the last version of the library which Wei plans to submit for testing and validation. Details can be found here.

The module certification FAQ can be found under the Cryptographic Module Validation Program.

Single Threaded Versus Multi-threaded

In all cases, the Crypto++ library should be built using multi-threaded libraries. This was an issue with Visual C++ 6.0 and previous. At times, the Project Wizard would output a project using a Singe Threaded project (/ML and /MLd).

Static Versus Dynamic Linking

C Runtime Library

When integrating Crypto++, the Crypto++ library must use the same runtime library linker setting as our Visual Studio project. The runtime library refers to the C Runtime Library. A stock Crypto++ distribution is built using static linking against the runtime (/MT and /MTd).

A default Visual Studio project created by the wizard will use dynamic runtime linking. The project would specify the /MD or /MDd linker switch for dynamic runtime linking, while the Crypto++ library would be using static linking (/MT or /MTd) from its build. This will cause a plethora of LINK2005 errors when linking. To resolve this, the Crypto++ library must be rebuilt. Table 1 below summarizes this discussion:

Project SettingProject Link SwitchDesired Runtime LinkingAction Required
Static Runtime Linking/MT or /MTdStaticNone
Dynamic Runtime Linking/MD or /MDdDynamicRebuild Crypto++ Library

Rebuild Crypto++ Library means to rebuild the Crypto++ library after changing the settings to compile and link against dynamic versions of the runtime. Also see the section Unsupported Configuration below.

Static Runtime Linking

The Crypto++ library is distributed as a statically linked library. Static linking is usually preferred (versus the DLL or FIPS DLL). According to Wei Dai:

... there should not be any problems linking a DLL against a DLL. But using the static library saves on code size and I'd suggest it unless you need to use the DLL for some reason (such as FIPS compliance).

When creating a statically linked Visual Studio project, no additional settings need to be changed.

Dynamic Runtime Linking

When dynamically linking to the C Runtime (/MD or /MDd), the Crypto++ library must be rebuilt using the same link settings as the main project. Open the Crypto++ project and change the Crypto++ project setting for both Cryptlib and CryptDll. The settings should be changed to /MD or /MDd. For good measure, the setting should also be changed for Cryptest (and the validation test re-run: issue cryptest v).

Runtime Library Conflicts and the Crypto++ DLL/FIPS DLL

Runtime linking presents two difficult situations for the software author. First is the desire to link dynamically against the C runtime while using the FIPS DLL. The issue is derived as follows: Dynamic C Runtime linking is used by (/MD or /MDd) the application, but the distributed FIPS DLL is static (/MT or /MTd). The best solution is using the /NODEFAULTLIB switch and hoping that no runtime issues occur. This situation will create hard to track down runtime bugs and obscure initialization failures. Note that rebuilding the DLL using dynamic runtime linking is not available since we are using the FIPS DLL.

The second situation is created when using additional third party components. This includes MFC and ATL. Suppose we need to use the FIPS DLL. We change the project settings to use the static version of the runtime, and link using the FIPS DLL. Next, we add the third party component which only offers dynamic linking against the C Runtime. We now have the situation previously described. The preferred workaround is to contact the third party vendor and acquire a library which uses the same runtime settings as our project and Crypto++.

Unresolved External Symbols

When using the DLL or FIPS DLL, the newsgroup occasional receives reports of LNK2001 and LINK2019 such as below. This is because the DLL and FIPS DLL only includes certified algorithms. So the DLL exports AES, but it does not export DES (DES has been deprecated in various standards). Also missing from the FIPS DLL are supporting classes such as Base64Encoder.

Crypto.obj : error LNK2019: unresolved external symbol
"public: virtual void __thiscall CryptoPP::Base64Encoder::IsolatedInitialize
(class CryptoPP::NameValuePairs const &)"
(? IsolatedInitialize@Base64Encoder@CryptoPP@@UAEXABVNameValuePairs@2@@Z)
referenced in function "public: __thiscall CryptoPP::Base64Encoder::Base64Encoder
(class CryptoPP::BufferedTransformation *,bool,int)"


dlltest.obj : error LNK2001: unresolved external symbol "__declspec(dllimport)
public: __thiscall CryptoPP::DH_Domain<class 
CryptoPP::DL_GroupParameters_GFP_DefaultSafePrime, struct 
CryptoPP::EnumToType<enum CryptoPP::CofactorMultiplicationOption,0>
DLL_Debug/dlltest.exe : fatal error LNK1120: 1 unresolved externals

To resolve this, first read the "MSVC-Specific Information" in readme.txt. Wei offers two solutions to the issue:

There are two ways you can deal with this, either change Crypto++ to export those classes, by using the CRYPTOPP_DLL macro, or link with both the DLL export library and a static library that contains the non-DLL classes and functions. The latter can be built by using the "DLL-Import" configuration of the cryptlib project.

Note that in Wei's first solution, we are rebuilding the DLL (not the FIPS DLL) to export the additional functions we require by using the CRYPTO_DLL macro. We may also have to add the source files to the cryptdll project in the solution. In the second offering, we are using the FIPS DLL and supplementing it with functionality from Crypto++'s static library, since the FIPS DLL does not contain all the Crypto++ functionality we need.

Crypto++ DLL - New and Delete

At times, we might have to force Crypto++ to use new and delete from another library rather than the standard runtime. For this, we would want to call SetNewAndDeleteFunctionPointers. See dll.cpp for Wei's use of setting the function pointers for the standard runtime.

Also be aware that this usually has to be done early in the initialization process. This creates additional issues not related to Crypto++, such as linking libraries in the wrong order. Please see Knowledge Base Article 148652, LNK2005 error occurs when the CRT library and MFC libraries are linked in the wrong order in Visual C++.

Compiling Crypto++

Visit the Crypto++ homepage and fetch a version for download. This article is based on version 5.2.1, but any version should do. We should review the "Platforms" Matrix when choosing a Crypto++ distribution. When using Visual Studio 6.0, Microsoft's Processor Pack is recommended for Crypto++ 5.1 and earlier; and is required for Crypto++ 5.2 and later.

Create a directory on the hard drive for the distribution of the Crypto++ downloaded. Locate the cryptest.dsw or cryptest.sln file, and open it. In this example, the Zip file was extracted to C:\CryptoPP 5.2.1\.

By default, 32 bit binaries are built. To build a 64 bit binary, change the platform using the dropdown or Configuration Manager.

From the Build menu, select Batch Build.

For the purposes of this article, build only the Static Library by un-checking the appropriate selections.

Sample screenshot

Integrating Crypto++ into the Visual C++ Environment

This document will add the library to the Visual Studio environment rather than the Project environment. This means the settings affect every project, not just a Crypto++ project. Please see John Deters' comment below for reasons not to do so. It is a well crafted and explained commentary which should prove useful. Once the build is complete, drill into the C:\CryptoPP 5.2.1\Debug\ folder. Rename the library file from cryptlib.lib to cryptlibd.lib (notice the addition of the "d" for Debug).

Move the Debug library to the location of the header and source files. In this example, the location is C:\CryptoPP 5.2.1\. Also, move (without renaming) the Release version to the same folder.

Visual C++ Integration

Add the location of the header files, source files, and libraries to the VC++ Environment. Select Tools | Options, Directories tab. Make the appropriate entry for the previously mentioned items in the drop down menu.

Project Integration

Add the location of the header files, source files, and libraries to the VC++ Project.

This step will allow us to #include"ecp.h", rather than including ecp.h and all of its dependencies, and specifying full or relative paths. Also, since the library is on path (and appropriately named), we can now issue the following #pragma to have the linker include the library:

// Crypto++ Library

#ifdef _DEBUG
#  pragma comment ( lib, "cryptlibd" )
#  pragma comment ( lib, "cryptlib" )

Additional (Unsupported) Configuration

If interested, a project configuration exists which allows for building Crypto++ using both static and dynamic runtime linking. However, don't expect Wei to support it. The authors have used it for quite some time with both Visual Studio 8.0 and Visual Studio 9.0.

Unfortunately, the x64 build settings have been removed by the IDE because the x64 compiler and headers were not installed during installation. Fortunately, they can be easily added back into the project using the Configuration Manager.

The alternate configuration renames the cryptlib project to cryptlib.static. It also adds cryptlib.dynamic (with settings copied form cryptlib.static). Both the static and dynamic projects build debug and release libraries. ".dynamic" and ".static" were chosen rather than 'd' and 's' suffixes so that debug builds would not be confused with dynamic C runtime linking builds. Files offered by the configurations are:

  • cryptlib.static.lib
  • cryptlibd.static.lib
  • cryptlib.dynamic.lib
  • cryptlibd.dynamic.lib

To use the configuration, unzip the files on top of the Crypto++ files, replacing as required. For those who are concerned with the library size (before the linker removes unused functions), dynamic runtime linking produces considerably smaller code.

After building the four variants, use copylib.cmd to copy the libraries to the root of the Crypto++ distribution. Finally, include CryptlibInclude.h in the project. CryptlibInclude.h performs a switch based on _DLL (defined when using dynamic runtime linking) and DEBUG:

Also note that both the static and dynamic libraries use dll.cpp, even though we are not building the DLL. If we don't use dll.cpp, we will receive LNK2001 errors staing that a function (using _thiscall) could not be found, despite the fact that we specify _cdecl for compilation in the source file's properties. Below, VerifyHash (an ATL project which requires dynamic runtime linking) is using cryptlib.dynamic without dll.cpp.

Missing Adhoc.cpp

We receive 20 errors (10 pairs) similar to below. The first error claims that the program cannot be linked because of a missing function in VerifyHash.obj. The second (referring to the same function) claims the function cannot be found in the Crypto++ library.

VerifyHash.obj : error LNK2001: unresolved external symbol 
  "public: virtual void __thiscall CryptoPP::IteratedHashBase<unsigned int,class 
  CryptoPP::HashTransformation>::Update(unsigned char const *,unsigned int)" 

cryptlibd.dynamic.lib(md5.obj) : error LNK2001: unresolved external symbol 
   "public: virtual void __thiscall CryptoPP::IteratedHashBase<unsigned int,class 
   CryptoPP::HashTransformation>::Update(unsigned char const *,unsigned int)" 

I can't explain why functions from iterbase.h and iterbase.cpp are affected by inclusion or exclusion of dll.cpp.

Common Errors

This section will discuss common compiler and linker errors encountered when using the Crypto+ library. They are usually encountered because of an oversight in following these instructions. Once you have verified that these instructions were followed, please post your question to the Crypto++ User Group.

Compile Error 1001

If you receive Internal Compile Error COMPILE 1001 (C1001) shown below:

You should perform the following:

  • Verify your source code is correct
  • Verify config.h (see below)
  • Rearrange functions (note: the CL Error will output the source code line where the compiler encountered problems - see below)
  • Disable precompiled headers
  • Update the library
  • Update the compiler
  • Post to the Crypto++ Newsgroup
  • Contact Microsoft support

Verify config.h

Depending on the version of Visual Studio, some compile time changes are invoked. One suspect to pay particular attention to is _MSC_VER < 1300. If using Visual Studio 7.1 or above, changing to below may do the trick.

// how to declare class constants

#if defined(_MSC_VER) && _MSC_VER <= 1300
#  define CRYPTOPP_CONSTANT(x) enum {x};

#  define CRYPTOPP_CONSTANT(x) static const int x;

Rearrange Functions

Function A
   { ... }
Function B
   { ... }

Change the above to:

Function B
   { ... }
Function A
   { ... }

I can't explain this one, but it has worked for me in the past when working with Crypto++ Elliptic Curve functions.

Compile Error 1083

If you do not add the path to the Crypto++ header files to the Visual C++ environment or your Project, COMPILE 1083 (C1083) Errors similar to below will be displayed.

Compile Error 1189

If you incorrectly match the C Runtime with MFC (for example, MFC as a DLL, Crypto++ and C Runtime as a Static Library), COMPILE 1189 (C1189) errors similar to those below will be displayed.

You should revisit the section Static Versus Dynamic Linking. MFC uses dynamic runtime linking.

Compile Warning 4530

If you receive Compile Warning COMPILE 4530 (C4530) ...

... then you should enable exception handling.

Link Error 1103

If you receive LINK 1103 (LNK1103) "debugging information corrupt" when using Visual C++ 6.0 and the latest Platform SDK (shown below) with libraries uuid.lib, shell32.lib, msxml2.lib, etc ...

... then you should roll back the Platform SDK to February 2003. You may be able to change the directory order in Visual C++ 6.0.

Link Error 1104

If you do not install MFC Unicode Library Versions (mfc42u.lib, mfc42ud.lib, etc.), but define UNICODE, LINK 1104 (LNK1104), then errors similar to those below will be displayed. This is a Visual C++ 6.0 and previous error, since Visual Studio 7.0 and above do not allow a non-Unicode installation.

To resolve this, rerun the setup and install the Unicode Libraries (performing a custom installation).

Link Error 1104

If you do not place the Crypto++ Library on the VC++ IDE path, LINK 1104 (LNK1104) errors similar to those below will be displayed.

Link Error 2001

If you do not link the Crypto++ Library to the project, LINK 2001 (LNK2001) errors similar to those below will be displayed.

To resolve this, add the following to StdAfx.h (if using precompiled headers) or to the source file using Crypto++.

// Crypto++ Library

#ifdef _DEBUG
#  pragma comment ( lib, "cryptlibd" )
#  pragma comment ( lib, "cryptlib" )

Alternately, one can add the Crypto++ Library through the Visual C++ IDE.

Link Error 2001

The Crypto++ output libraries are located at Win32\output\debug\cryptlib.lib and Win32\output\release\cryptlib.lib. The DLL and its export library are in Win32\dll_output. Note the "dll_" in the path name. Verify that you are using the correct paths.

Link Error 2005

If you do not change the C Runtime Library settings on the Project, LINK 2005 (LNK2005) errors similar to those below will be displayed.

You should use the Multithreaded versions of the C++ Runtime Library:

Link Error 2005 When Using ATL

Should you encounter LNK2005 when using ATL, recompile the Crypto++ library using the Multithreaded DLL and Multithreaded Debug DLL choices of the runtime library. This was not an issue in Visual C++ 6.0, but it is an issue in Visual Studio 2005.

Link Error 2019 When Using the FIPS DLL

This error is due to the FIPS DLL only exporting certified algorithms such as AES. Wei offers two solutions to the issue. First, you can statically link against the library. Second, you must use the DLL version of the library (not the FIPS DLL). Then, to export the missing classes of interest, add the CRYPTOPP_DLL macro to the class declaration. Then rebuild the DLL-Import project.

Integer Class std::cout Formatting

As distributed, the Integer class displays a suffix ('o', '.', or 'h') to denote base. In addition, the library uses uppercase characters for all hexadecimal output. To change the behavior so that Integer does not use a suffix and honors the ios::uppercase flag, perform the following. First, remove the declaration for suffix and change the switch statement.

  case std::ios::oct :
    base = 8;
    block = 8;
  case std::ios::hex :
    base = 16;
    block = 4;
  default :
    base = 10;
    block = 3;

Next, add the following:

const char* vec = NULL;
const char upper[]="0123456789ABCDEF";
const char lower[]="0123456789abcdef";

if( out.flags() & (long)std::ios::uppercase )
{ vec = upper; }
{ vec = lower; }


// No longer can return out << suffix;

return out;

Crypto++ Integer


  • 01.12.2009 Added Benchmark links
  • 07.08.2008 Added link to NIST certification FAQ
  • 05.27.2008 Added Adhoc.cpp information
  • 05.27.2008 Added Dr. Chirico's Windows CE port
  • 05.25.2008 Removed HashFilter AlgorithmName() fix
  • 05.25.2008 Added alternate configuration (Static and Dynamic C Runtime Projects)
  • 04.20.2008 Added alternate website and download links
  • 03.21.2008 Added Managed Code section
  • 02.22.2008 Added Link Error 2019 (LNK2019)
  • 02.22.2008 Added information on the CRYPTOPP_DLL macro
  • 11.29.2007 Added the Single versus Multi-Threaded section
  • 11.28.2007 Added the FIPS Compliance section
  • 11.28.2007 Reworked the Static versus Dynamic Linking Section
  • 11.28.2007 Removed the sample project
  • 06.04.2007 Added Link Error 2005 when using ATL (LNK2005)
  • 12.31.2006 Added Crypto++ wiki site link
  • 12.27.2006 Updated Crypto++ class and library reference (Crypto++ 5.4 release)
  • 12.23.2006 Added additional fix to Internal Compiler Error (C1001)
  • 12.22.2006 Added link to Chris Deter's comments
  • 12.22.2006 Added startup project information
  • 12.17.2006 Added Link Error 1103 (LNK1103)
  • 12.15.2006 Updated article graphics
  • 12.13.2006 Added HashFilter AlgorithName()
  • 12.13.2006 Added FAQ, User Guide, and Crypto++ user newsgroup
  • 12.12.2006 Added Compile Warning 4530
  • 12.11.2006 Added VC7 Directories dialog
  • 12.09.2006 Added Unicode library installation
  • 12.09.2006 Added Additional Fix Internal Compiler Error (C1001)
  • 11.21.2006 Added Internal Compiler Error (C1001)
  • 11.16.2006 Added Integer std::cout formatting
  • 11.15.2006 Added Static versus Dynamic Crytpo++ Linking
  • 11.14.2006 Initial release


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


About the Authors

Garth J Lancaster
Architect Currently Retrenched - Looking at Consulting
Australia Australia
No Biography provided

Jeffrey Walton
Systems / Hardware Administrator
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralRe: Another way to integrate... Pin
Jeffrey Walton14-Sep-11 4:50
memberJeffrey Walton14-Sep-11 4:50 
GeneralX64 build Pin
hamidehkarimi27-Apr-11 0:52
memberhamidehkarimi27-Apr-11 0:52 
GeneralRe: X64 build Pin
Garth J Lancaster2-May-11 16:17
memberGarth J Lancaster2-May-11 16:17 
GeneralRe: X64 build Pin
hamidehkarimi2-May-11 20:02
memberhamidehkarimi2-May-11 20:02 
GeneralRe: X64 build Pin
Garth J Lancaster3-May-11 13:15
memberGarth J Lancaster3-May-11 13:15 
Generalthe changes for 2k10 Pin
Nicholas Skradski8-Aug-10 9:42
memberNicholas Skradski8-Aug-10 9:42 
General[SOLVED] Can't compile cryptopp in Visual Studio 2010 Pin
hjkhjghjk18-May-10 9:51
memberhjkhjghjk18-May-10 9:51 
GeneralRe: [SOLVED] Can't compile cryptopp in Visual Studio 2010 Pin
Garth J Lancaster18-May-10 12:01
memberGarth J Lancaster18-May-10 12:01 
thanks Bill - I dont have VS2010 so I doubt I could do much with your code/update the article .. how many changes did you need to make ? - maybe we can post them here

QuestionTrying to Link with Cryptlib.dynamic Pin
orouit23-Mar-10 5:56
memberorouit23-Mar-10 5:56 
Generalcomparison between RSA and ECC as encryption method not signing Pin
Member 151309928-Oct-09 4:16
memberMember 151309928-Oct-09 4:16 
Generallinking errors while using cryptopp.lib Pin
Mahesh_Nag1-Oct-09 3:57
memberMahesh_Nag1-Oct-09 3:57 
Generalerror C2373: '_InterlockedCompareExchange' Pin
curt watson15-Sep-09 16:03
membercurt watson15-Sep-09 16:03 
GeneralRe: error C2373: '_InterlockedCompareExchange' Pin
aslm20-Oct-09 6:11
memberaslm20-Oct-09 6:11 
GeneralRe: error C2373: '_InterlockedCompareExchange' Pin
cjoker23-Jun-10 3:35
membercjoker23-Jun-10 3:35 
GeneralDifference between Crypto++ encryption and C# .NET encryption Pin
Nicolas Stuardo11-May-09 11:50
memberNicolas Stuardo11-May-09 11:50 
GeneralRe: Difference between Crypto++ encryption and C# .NET encryption Pin
Nicolas Stuardo15-May-09 7:25
memberNicolas Stuardo15-May-09 7:25 
GeneralRe: Difference between Crypto++ encryption and C# .NET encryption Pin
Jeffrey Walton15-May-09 7:31
memberJeffrey Walton15-May-09 7:31 
GeneralAttention: v5.6.0 requires RTTI Pin
Avi Bueno17-Apr-09 13:12
memberAvi Bueno17-Apr-09 13:12 
Newsupdated vc90 project files Pin
Sorin Sbarnea5-Apr-09 9:32
memberSorin Sbarnea5-Apr-09 9:32 
GeneralRe: updated vc90 project files Pin
Jeffrey Walton5-Apr-09 10:57
memberJeffrey Walton5-Apr-09 10:57 
GeneralRe: updated vc90 project files Pin
Sorin Sbarnea5-Apr-09 11:07
memberSorin Sbarnea5-Apr-09 11:07 
GeneralRe: updated vc90 project files Pin
Jeffrey Walton5-Apr-09 11:15
memberJeffrey Walton5-Apr-09 11:15 
GeneralRe: updated vc90 project files Pin
Sorin Sbarnea5-Apr-09 11:29
memberSorin Sbarnea5-Apr-09 11:29 
GeneralRe: updated vc90 project files Pin
Jeffrey Walton5-Apr-09 12:00
memberJeffrey Walton5-Apr-09 12:00 
GeneralRe: updated vc90 project files Pin
Sorin Sbarnea8-Apr-09 20:04
memberSorin Sbarnea8-Apr-09 20:04 

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
Web02 | 2.8.170424.1 | Last Updated 5 May 2011
Article Copyright 2006 by Garth J Lancaster, Jeffrey Walton
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid