[SmartcardServices-Changes] [72] trunk/SmartCardServices/src

source_changes at macosforge.org source_changes at macosforge.org
Thu Dec 17 00:49:39 PST 2009


Revision: 72
          http://trac.macosforge.org/projects/smartcardservices/changeset/72
Author:   ludovic.rousseau at gmail.com
Date:     2009-12-17 00:49:36 -0800 (Thu, 17 Dec 2009)
Log Message:
-----------
Add Gemalto PKCS#11 module for .net v2 cards.
The library is licensed GNU LGPL v2.1.

Closes ticket #18

Added Paths:
-----------
    trunk/SmartCardServices/src/PKCS11dotNetV2/
    trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1
    trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4
    trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4
    trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh
    trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh
    trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp
    trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,510 @@
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard.  To achieve this, non-free programs must
+be allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at least
+    three years, to give the same user the materials specified in
+    Subsection 6a, above, for a charge no more than the cost of
+    performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James
+  Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,3 @@
+SUBDIRS = PKCS11Module2
+
+EXTRA_DIST = autogen.sh c-mac.sh LGPL-2.1

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,136 @@
+lib_LTLIBRARIES = libgtop11dotnet.la
+
+libgtop11dotnet_la_LDFLAGS = -shared
+
+libgtop11dotnet_la_SOURCES = \
+	$(top_srcdir)/cppMarshaller/Array.cpp \
+	$(top_srcdir)/cppMarshaller/Array.h \
+	$(top_srcdir)/cppMarshaller/Except.h \
+	$(top_srcdir)/cppMarshaller/MarshallerCfg.h \
+	$(top_srcdir)/cppMarshaller/Marshaller.cpp \
+	$(top_srcdir)/cppMarshaller/Marshaller.h \
+	$(top_srcdir)/cppMarshaller/PCSC.cpp \
+	$(top_srcdir)/cppMarshaller/PCSC.h \
+	algo_des.cpp \
+	algo_des.h \
+	algo_md5.cpp \
+	algo_md5.h \
+	algo_sha1.cpp \
+	algo_sha1.h \
+	algo_sha256.cpp \
+	algo_sha256.h \
+	algo_utils.cpp \
+	algo_utils.h \
+	application.cpp \
+	application.h \
+	attrcert.cpp \
+	attrcert.h \
+	beroctet.cpp \
+	beroctet.h \
+	cardcache.cpp \
+	cardcache.h \
+	cardmoduleservice.cpp \
+	cardmoduleservice.h \
+	certificateobject.cpp \
+	certificateobject.h \
+	cert_utils.cpp \
+	cert_utils.h \
+	config.h \
+	critsect.cpp \
+	critsect.h \
+	dataobject.cpp \
+	dataobject.h \
+	des.cpp \
+	des.h \
+	digest.cpp \
+	digest.h \
+	error.cpp \
+	error.h \
+	event.cpp \
+	event.h \
+	keyobject.cpp \
+	keyobject.h \
+	md5.cpp \
+	md5.h \
+	mutex.cpp \
+	mutex.h \
+	pkcs11.cpp \
+	pkcs11f.h \
+	pkcs11.h \
+	pkcs11t.h \
+	platconfig.h \
+	privatekeyobject.cpp \
+	privatekeyobject.h \
+	publickeyobject.cpp \
+	publickeyobject.h \
+	resource.h \
+	rsa/cr_digit.cpp \
+	rsa/cr_digit.h \
+	rsa/cr_global.h \
+	rsa/cr_nn.cpp \
+	rsa/cr_nn.h \
+	rsa/cr_random.cpp \
+	rsa/cr_random.h \
+	rsa/cr_rsa.cpp \
+	rsa/cr_rsa.h \
+	rsa/ha_config.h \
+	rsaprivatekeyobject.cpp \
+	rsaprivatekeyobject.h \
+	rsapublickeyobject.cpp \
+	rsapublickeyobject.h \
+	sctoken.cpp \
+	sctoken.h \
+	secretkeyobject.cpp \
+	secretkeyobject.h \
+	session.cpp \
+	session.h \
+	sha1.cpp \
+	sha1.h \
+	sha256.cpp \
+	sha256.h \
+	slot.cpp \
+	slot.h \
+	stdafx.cpp \
+	stdafx.h \
+	storageobject.cpp \
+	storageobject.h \
+	symmalgo.cpp \
+	symmalgo.h \
+	tdes.cpp \
+	tdes.h \
+	template.cpp \
+	template.h \
+	thread.cpp \
+	thread.h \
+	timer.cpp \
+	timer.h \
+	transaction.cpp \
+	transaction.h \
+	util.cpp \
+	util.h \
+	x509cert.cpp \
+	x509cert.h \
+	x509pubkeycertobject.cpp \
+	x509pubkeycertobject.h \
+	log.h \
+	log.cpp
+
+AM_CPPFLAGS = -DINCLUDE_EVENTING=1 -DCRYPTOKI_EXPORTS=1 \
+	-DUNIX $(PTHREAD_CFLAGS) \
+	-Wall \
+	-Wextra \
+	-pedantic
+
+INCLUDES = \
+	-I$(top_srcdir)/cppMarshaller \
+	-I$(top_srcdir)/PKCS11Module2 \
+	-I$(top_srcdir)/PKCS11Module2/rsa \
+	$(PCSC_CFLAGS)
+
+LIBS = $(PCSC_LIBS) $(PTHREAD_LIBS) -lz
+
+# see http://wiki.cacert.org/wiki/Pkcs11TaskForce
+install-exec-hook:
+	$(MKDIR_P) $(DESTDIR)/$(prefix)/lib/pkcs11
+	cd $(DESTDIR)/$(prefix)/lib/pkcs11 ; rm -f libgtop11dotnet. at DYN_LIB_EXT@ ; $(LN_S) ../libgtop11dotnet. at DYN_LIB_EXT@
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,410 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+typedef struct _DES_Context
+{
+    u4 encrypt_subkeys[32];
+    u4 decrypt_subkeys[32];
+} _DES_Context;
+
+typedef struct _3DES_Context
+{
+    u4 encrypt_subkeys[96];
+    u4 decrypt_subkeys[96];
+} _3DES_Context;
+
+/*
+ * The s-box values are permuted according to the 'primitive function P'
+ * and are rotated one bit to the left.
+ */
+static const u4 sbox1[64] =
+{
+  0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+  0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+  0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+  0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+  0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+  0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+  0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+  0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const u4 sbox2[64] =
+{
+  0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+  0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+  0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+  0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+  0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+  0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+  0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+  0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const u4 sbox3[64] =
+{
+  0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+  0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+  0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+  0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+  0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+  0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+  0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+  0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const u4 sbox4[64] =
+{
+  0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+  0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+  0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+  0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+  0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+  0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+  0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+  0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const u4 sbox5[64] =
+{
+  0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+  0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+  0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+  0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+  0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+  0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+  0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+  0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const u4 sbox6[64] =
+{
+  0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+  0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+  0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+  0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+  0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+  0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+  0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+  0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const u4 sbox7[64] =
+{
+  0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+  0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+  0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+  0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+  0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+  0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+  0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+  0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const u4 sbox8[64] =
+{
+  0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+  0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+  0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+  0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+  0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+  0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+  0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+  0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+static const u4 leftkey_swap[16] =
+{
+  0x00000000, 0x00000001, 0x00000100, 0x00000101,
+  0x00010000, 0x00010001, 0x00010100, 0x00010101,
+  0x01000000, 0x01000001, 0x01000100, 0x01000101,
+  0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const u4 rightkey_swap[16] =
+{
+  0x00000000, 0x01000000, 0x00010000, 0x01010000,
+  0x00000100, 0x01000100, 0x00010100, 0x01010100,
+  0x00000001, 0x01000001, 0x00010001, 0x01010001,
+  0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+static const u1 encrypt_rotate_tab[16] =
+{
+  1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+#define DO_PERMUTATION(a, temp, b, offset, mask)	\
+    temp = ((a>>offset) ^ b) & mask;			\
+    b ^= temp;						\
+    a ^= temp<<offset;
+
+#define INITIAL_PERMUTATION(left, temp, right)		\
+    DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)	\
+    DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)	\
+    DO_PERMUTATION(right, temp, left, 2, 0x33333333)	\
+    DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)	\
+    right =  (right << 1) | (right >> 31);		\
+    temp  =  (left ^ right) & 0xaaaaaaaa;		\
+    right ^= temp;					\
+    left  ^= temp;					\
+    left  =  (left << 1) | (left >> 31);
+
+#define FINAL_PERMUTATION(left, temp, right)		\
+    left  =  (left << 31) | (left >> 1);		\
+    temp  =  (left ^ right) & 0xaaaaaaaa;		\
+    left  ^= temp;					\
+    right ^= temp;					\
+    right  =  (right << 31) | (right >> 1);		\
+    DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff)	\
+    DO_PERMUTATION(right, temp, left, 2, 0x33333333)	\
+    DO_PERMUTATION(left, temp, right, 16, 0x0000ffff)	\
+    DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)
+
+#define DES_ROUND(from, to, work, subkey)		\
+    work = from ^ *subkey++;				\
+    to ^= sbox8[  work	    & 0x3f ];			\
+    to ^= sbox6[ (work>>8)  & 0x3f ];			\
+    to ^= sbox4[ (work>>16) & 0x3f ];			\
+    to ^= sbox2[ (work>>24) & 0x3f ];			\
+    work = ((from << 28) | (from >> 4)) ^ *subkey++;	\
+    to ^= sbox7[  work	    & 0x3f ];			\
+    to ^= sbox5[ (work>>8)  & 0x3f ];			\
+    to ^= sbox3[ (work>>16) & 0x3f ];			\
+    to ^= sbox1[ (work>>24) & 0x3f ];
+
+#define READ_64BIT_DATA(data, left, right)					\
+    left  = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];	\
+    right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
+
+#define WRITE_64BIT_DATA(data, left, right)					\
+    data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; 		\
+    data[2] = (left >> 8) &0xff; data[3] = left &0xff;				\
+    data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff;		\
+    data[6] = (right >> 8) &0xff; data[7] = right &0xff;
+
+
+static void algo_DES_KeySchedule(const u1 * rawkey, u4 * subkey)
+{
+    u4 left, right, work;
+    u1 round;
+
+    READ_64BIT_DATA (rawkey, left, right)
+
+    DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f)
+    DO_PERMUTATION (right, work, left, 0, 0x10101010)
+
+    left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2)
+        | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf])
+        | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6)
+        | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4);
+
+    left &= 0x0fffffff;
+
+    right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2)
+        | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf])
+        | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6)
+        | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4);
+
+    right &= 0x0fffffff;
+
+    for (round = 0; round < 16; ++round) {
+
+        left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+        right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+
+        *subkey++ = ((left << 4) & 0x24000000)
+            | ((left << 28) & 0x10000000)
+            | ((left << 14) & 0x08000000)
+            | ((left << 18) & 0x02080000)
+            | ((left << 6) & 0x01000000)
+            | ((left << 9) & 0x00200000)
+            | ((left >> 1) & 0x00100000)
+            | ((left << 10) & 0x00040000)
+            | ((left << 2) & 0x00020000)
+            | ((left >> 10) & 0x00010000)
+            | ((right >> 13) & 0x00002000)
+            | ((right >> 4) & 0x00001000)
+            | ((right << 6) & 0x00000800)
+            | ((right >> 1) & 0x00000400)
+            | ((right >> 14) & 0x00000200)
+            | (right & 0x00000100)
+            | ((right >> 5) & 0x00000020)
+            | ((right >> 10) & 0x00000010)
+            | ((right >> 3) & 0x00000008)
+            | ((right >> 18) & 0x00000004)
+            | ((right >> 26) & 0x00000002)
+            | ((right >> 24) & 0x00000001);
+
+        *subkey++ = ((left << 15) & 0x20000000)
+            | ((left << 17) & 0x10000000)
+            | ((left << 10) & 0x08000000)
+            | ((left << 22) & 0x04000000)
+            | ((left >> 2) & 0x02000000)
+            | ((left << 1) & 0x01000000)
+            | ((left << 16) & 0x00200000)
+            | ((left << 11) & 0x00100000)
+            | ((left << 3) & 0x00080000)
+            | ((left >> 6) & 0x00040000)
+            | ((left << 15) & 0x00020000)
+            | ((left >> 4) & 0x00010000)
+            | ((right >> 2) & 0x00002000)
+            | ((right << 8) & 0x00001000)
+            | ((right >> 14) & 0x00000808)
+            | ((right >> 9) & 0x00000400)
+            | ((right) & 0x00000200)
+            | ((right << 7) & 0x00000100)
+            | ((right >> 7) & 0x00000020)
+            | ((right >> 3) & 0x00000011)
+            | ((right << 2) & 0x00000004)
+            | ((right >> 21) & 0x00000002);
+    }
+}
+
+static void algo_DES_Setkey(_DES_Context *ctx, const u1 * key)
+{
+    u1 i;
+
+    algo_DES_KeySchedule(key, ctx->encrypt_subkeys);
+
+    for(i = 0; i < 32; i += 2) {
+        ctx->decrypt_subkeys[i]	= ctx->encrypt_subkeys[30-i];
+        ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
+    }
+}
+
+static void algo_DES_Set2keys(_3DES_Context *ctx, const u1 * key1, const u1 * key2)
+{
+    u1 i;
+
+    algo_DES_KeySchedule(key1, ctx->encrypt_subkeys);
+    algo_DES_KeySchedule(key2, &(ctx->decrypt_subkeys[32]));
+
+    for(i = 0; i < 32; i += 2) {
+        ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i];
+        ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
+
+        ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
+        ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
+
+        ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i];
+        ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1];
+
+        ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i];
+        ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1];
+    }
+}
+
+static void algo_DES_Set3keys(_3DES_Context *ctx, const u1 * key1, const u1 * key2, const u1 * key3)
+{
+    u1 i;
+
+    algo_DES_KeySchedule(key1, ctx->encrypt_subkeys);
+    algo_DES_KeySchedule(key2, &(ctx->decrypt_subkeys[32]));
+    algo_DES_KeySchedule(key3, &(ctx->encrypt_subkeys[64]));
+
+    for(i = 0; i < 32; i += 2) {
+        ctx->decrypt_subkeys[i]	 = ctx->encrypt_subkeys[94-i];
+        ctx->decrypt_subkeys[i+1]  = ctx->encrypt_subkeys[95-i];
+        ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
+        ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
+        ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i];
+        ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i];
+    }
+}
+
+void algo_DES_DESProcess(u1* key, u1* from, u1* to, u1 mode)
+{
+    _DES_Context ctx;
+    u4 left, right, work;
+    u4 *keys;
+
+    algo_DES_Setkey(&ctx, key);
+
+    keys = (mode == TRUE) ? ctx.encrypt_subkeys : ctx.decrypt_subkeys;
+
+    READ_64BIT_DATA(from, left, right)
+    INITIAL_PERMUTATION(left, work, right)
+
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+    FINAL_PERMUTATION(right, work, left)
+    WRITE_64BIT_DATA(to, right, left)
+}
+
+void algo_DES_3DESProcess(u1 keyLength, u1* key, u1 * from, u1 * to, u1 mode)
+{
+    _3DES_Context ctx;
+    u4 left, right, work;
+    u4 *keys;
+
+    if (keyLength == 0x10) {
+        algo_DES_Set2keys(&ctx, &key[0], &key[8]);
+    } else {
+        algo_DES_Set3keys(&ctx, &key[0], &key[8], &key[16]);
+    }
+
+    keys = (mode == TRUE) ? ctx.encrypt_subkeys : ctx.decrypt_subkeys;
+
+    READ_64BIT_DATA(from, left, right)
+    INITIAL_PERMUTATION(left, work, right)
+
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+    DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+    DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+    FINAL_PERMUTATION(right, work, left)
+    WRITE_64BIT_DATA(to, right, left)
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,28 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_des_h
+#define _include_algo_des_h
+
+extern void algo_DES_DESProcess(u1* key, u1* input, u1* output, u1 mode);
+extern void algo_DES_3DESProcess(u1 keyLength, u1* key, u1* input, u1* output, u1 mode);
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,225 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_md5.h"
+
+const u1 md5_padding[64] = {
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define md5_S(x,n)              ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define md5_P(a,b,c,d,k,s,t)    {a += F(b,c,d) + data[k] + t; a = md5_S(a,s) + b;}
+
+void algo_md5_starts(algo_md5_context* ctx)
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->digest[0] = 0x67452301;
+    ctx->digest[1] = 0xEFCDAB89;
+    ctx->digest[2] = 0x98BADCFE;
+    ctx->digest[3] = 0x10325476;
+}
+
+
+static void algo_md5_compress(algo_md5_context *ctx, u4* data)
+{
+    u4 A, B, C, D;
+
+    // big endian processing
+    if (IS_BIG_ENDIAN)
+    {
+        u1 i;
+        for (i = 0; i < (MD5_BLOCK_LENGTH / sizeof(u4)); i++) {
+            data[i] = swapbytes_u4(data[i]);
+        }
+    }
+
+    A = ctx->digest[0];
+    B = ctx->digest[1];
+    C = ctx->digest[2];
+    D = ctx->digest[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+    md5_P(A, B, C, D,  0,  7, 0xD76AA478);
+    md5_P(D, A, B, C,  1, 12, 0xE8C7B756);
+    md5_P(C, D, A, B,  2, 17, 0x242070DB);
+    md5_P(B, C, D, A,  3, 22, 0xC1BDCEEE);
+    md5_P(A, B, C, D,  4,  7, 0xF57C0FAF);
+    md5_P(D, A, B, C,  5, 12, 0x4787C62A);
+    md5_P(C, D, A, B,  6, 17, 0xA8304613);
+    md5_P(B, C, D, A,  7, 22, 0xFD469501);
+    md5_P(A, B, C, D,  8,  7, 0x698098D8);
+    md5_P(D, A, B, C,  9, 12, 0x8B44F7AF);
+    md5_P(C, D, A, B, 10, 17, 0xFFFF5BB1);
+    md5_P(B, C, D, A, 11, 22, 0x895CD7BE);
+    md5_P(A, B, C, D, 12,  7, 0x6B901122);
+    md5_P(D, A, B, C, 13, 12, 0xFD987193);
+    md5_P(C, D, A, B, 14, 17, 0xA679438E);
+    md5_P(B, C, D, A, 15, 22, 0x49B40821);
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+    md5_P(A, B, C, D,  1,  5, 0xF61E2562);
+    md5_P(D, A, B, C,  6,  9, 0xC040B340);
+    md5_P(C, D, A, B, 11, 14, 0x265E5A51);
+    md5_P(B, C, D, A,  0, 20, 0xE9B6C7AA);
+    md5_P(A, B, C, D,  5,  5, 0xD62F105D);
+    md5_P(D, A, B, C, 10,  9, 0x02441453);
+    md5_P(C, D, A, B, 15, 14, 0xD8A1E681);
+    md5_P(B, C, D, A,  4, 20, 0xE7D3FBC8);
+    md5_P(A, B, C, D,  9,  5, 0x21E1CDE6);
+    md5_P(D, A, B, C, 14,  9, 0xC33707D6);
+    md5_P(C, D, A, B,  3, 14, 0xF4D50D87);
+    md5_P(B, C, D, A,  8, 20, 0x455A14ED);
+    md5_P(A, B, C, D, 13,  5, 0xA9E3E905);
+    md5_P(D, A, B, C,  2,  9, 0xFCEFA3F8);
+    md5_P(C, D, A, B,  7, 14, 0x676F02D9);
+    md5_P(B, C, D, A, 12, 20, 0x8D2A4C8A);
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+    md5_P(A, B, C, D,  5,  4, 0xFFFA3942);
+    md5_P(D, A, B, C,  8, 11, 0x8771F681);
+    md5_P(C, D, A, B, 11, 16, 0x6D9D6122);
+    md5_P(B, C, D, A, 14, 23, 0xFDE5380C);
+    md5_P(A, B, C, D,  1,  4, 0xA4BEEA44);
+    md5_P(D, A, B, C,  4, 11, 0x4BDECFA9);
+    md5_P(C, D, A, B,  7, 16, 0xF6BB4B60);
+    md5_P(B, C, D, A, 10, 23, 0xBEBFBC70);
+    md5_P(A, B, C, D, 13,  4, 0x289B7EC6);
+    md5_P(D, A, B, C,  0, 11, 0xEAA127FA);
+    md5_P(C, D, A, B,  3, 16, 0xD4EF3085);
+    md5_P(B, C, D, A,  6, 23, 0x04881D05);
+    md5_P(A, B, C, D,  9,  4, 0xD9D4D039);
+    md5_P(D, A, B, C, 12, 11, 0xE6DB99E5);
+    md5_P(C, D, A, B, 15, 16, 0x1FA27CF8);
+    md5_P(B, C, D, A,  2, 23, 0xC4AC5665);
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+    md5_P(A, B, C, D,  0,  6, 0xF4292244);
+    md5_P(D, A, B, C,  7, 10, 0x432AFF97);
+    md5_P(C, D, A, B, 14, 15, 0xAB9423A7);
+    md5_P(B, C, D, A,  5, 21, 0xFC93A039);
+    md5_P(A, B, C, D, 12,  6, 0x655B59C3);
+    md5_P(D, A, B, C,  3, 10, 0x8F0CCC92);
+    md5_P(C, D, A, B, 10, 15, 0xFFEFF47D);
+    md5_P(B, C, D, A,  1, 21, 0x85845DD1);
+    md5_P(A, B, C, D,  8,  6, 0x6FA87E4F);
+    md5_P(D, A, B, C, 15, 10, 0xFE2CE6E0);
+    md5_P(C, D, A, B,  6, 15, 0xA3014314);
+    md5_P(B, C, D, A, 13, 21, 0x4E0811A1);
+    md5_P(A, B, C, D,  4,  6, 0xF7537E82);
+    md5_P(D, A, B, C, 11, 10, 0xBD3AF235);
+    md5_P(C, D, A, B,  2, 15, 0x2AD7D2BB);
+    md5_P(B, C, D, A,  9, 21, 0xEB86D391);
+
+#undef F
+
+    ctx->digest[0] += A;
+    ctx->digest[1] += B;
+    ctx->digest[2] += C;
+    ctx->digest[3] += D;
+}
+
+void algo_md5_update(algo_md5_context* ctx, u1* input, u4 length)
+{
+    u4 left, fill;
+
+    if (!length) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = MD5_BLOCK_LENGTH - left;
+
+    ctx->total[0] += length;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if(ctx->total[0] < length) {
+        ctx->total[1]++;
+    }
+
+    if (left && (length >= fill)) {
+        memcpy(ctx->input + left,input,fill);
+        algo_md5_compress(ctx, (u4*)ctx->input);
+        length -= fill;
+        input  += fill;
+        left = 0;
+    }
+
+    while(length >= MD5_BLOCK_LENGTH) {
+        algo_md5_compress(ctx, (u4*)input);
+        length -= MD5_BLOCK_LENGTH;
+        input  += MD5_BLOCK_LENGTH;
+    }
+
+    if (length) {
+        memcpy(ctx->input + left,input,length);
+    }
+}
+
+void algo_md5_finish(algo_md5_context *ctx)
+{
+    u4 last, padn;
+    u4 msglen[2];
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        msglen[0] = (ctx->total[0] << 3);
+        msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+    }
+    // big endian processing
+    else
+    {
+        msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+        msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+    }
+
+    last = ctx->total[0] & 0x3F;
+    padn = (last < (MD5_BLOCK_LENGTH - sizeof(msglen))) ? ((MD5_BLOCK_LENGTH - sizeof(msglen)) - last) : (((2 * MD5_BLOCK_LENGTH) - sizeof(msglen)) - last);
+
+    algo_md5_update(ctx, (u1*)md5_padding, padn);
+    algo_md5_update(ctx, (u1*)msglen, sizeof(msglen));
+
+	// big endian processing
+    if (IS_BIG_ENDIAN)
+    {
+        u1 i;
+        for (i = 0; i < (MD5_HASH_LENGTH / sizeof(u4)); i++) {
+            ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+        }
+    }
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,38 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_md5_h
+#define _include_algo_md5_h
+
+typedef struct algo_md5_context{
+    u4 total[2];
+    u4* digest;
+    u1* input;
+} algo_md5_context;
+
+#define MD5_HASH_LENGTH 16
+#define MD5_BLOCK_LENGTH 64
+
+extern void algo_md5_starts(algo_md5_context* ctx);
+extern void algo_md5_update(algo_md5_context* ctx, u1* input, u4 length);
+extern void algo_md5_finish(algo_md5_context* ctx);
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,254 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_sha1.h"
+
+const u1 sha1_padding[64] = {
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define sha1_S(x,n)             ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define sha1_R(t)               (temp = data[(t - 3) & 0x0F] ^ data[(t - 8) & 0x0F] ^ data[(t - 14) & 0x0F] ^ data[t & 0x0F], (data[t & 0x0F] = sha1_S(temp,1)))
+
+#define sha1_P(a,b,c,d,e,x)     {e += sha1_S(a,5) + F(b,c,d) + K + x; b = sha1_S(b,30);}
+
+void algo_sha1_starts(algo_sha1_context *ctx)
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->digest[0] = 0x67452301;
+    ctx->digest[1] = 0xEFCDAB89;
+    ctx->digest[2] = 0x98BADCFE;
+    ctx->digest[3] = 0x10325476;
+    ctx->digest[4] = 0xC3D2E1F0;
+}
+
+static void algo_sha1_compress(algo_sha1_context *ctx, u4* data)
+{
+    u4 temp, A, B, C, D, E;
+    u1 i;
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        for (i = 0; i < (SHA1_BLOCK_LENGTH / sizeof(u4)); i++) {
+            data[i] = swapbytes_u4(data[i]);
+        }
+    }
+
+    A = ctx->digest[0];
+    B = ctx->digest[1];
+    C = ctx->digest[2];
+    D = ctx->digest[3];
+    E = ctx->digest[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+    sha1_P(A, B, C, D, E, data[0]);
+    sha1_P(E, A, B, C, D, data[1]);
+    sha1_P(D, E, A, B, C, data[2]);
+    sha1_P(C, D, E, A, B, data[3]);
+    sha1_P(B, C, D, E, A, data[4]);
+    sha1_P(A, B, C, D, E, data[5]);
+    sha1_P(E, A, B, C, D, data[6]);
+    sha1_P(D, E, A, B, C, data[7]);
+    sha1_P(C, D, E, A, B, data[8]);
+    sha1_P(B, C, D, E, A, data[9]);
+    sha1_P(A, B, C, D, E, data[10]);
+    sha1_P(E, A, B, C, D, data[11]);
+    sha1_P(D, E, A, B, C, data[12]);
+    sha1_P(C, D, E, A, B, data[13]);
+    sha1_P(B, C, D, E, A, data[14]);
+    sha1_P(A, B, C, D, E, data[15]);
+    sha1_P(E, A, B, C, D, sha1_R(16));
+    sha1_P(D, E, A, B, C, sha1_R(17));
+    sha1_P(C, D, E, A, B, sha1_R(18));
+    sha1_P(B, C, D, E, A, sha1_R(19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+    sha1_P(A, B, C, D, E, sha1_R(20));
+    sha1_P(E, A, B, C, D, sha1_R(21));
+    sha1_P(D, E, A, B, C, sha1_R(22));
+    sha1_P(C, D, E, A, B, sha1_R(23));
+    sha1_P(B, C, D, E, A, sha1_R(24));
+    sha1_P(A, B, C, D, E, sha1_R(25));
+    sha1_P(E, A, B, C, D, sha1_R(26));
+    sha1_P(D, E, A, B, C, sha1_R(27));
+    sha1_P(C, D, E, A, B, sha1_R(28));
+    sha1_P(B, C, D, E, A, sha1_R(29));
+    sha1_P(A, B, C, D, E, sha1_R(30));
+    sha1_P(E, A, B, C, D, sha1_R(31));
+    sha1_P(D, E, A, B, C, sha1_R(32));
+    sha1_P(C, D, E, A, B, sha1_R(33));
+    sha1_P(B, C, D, E, A, sha1_R(34));
+    sha1_P(A, B, C, D, E, sha1_R(35));
+    sha1_P(E, A, B, C, D, sha1_R(36));
+    sha1_P(D, E, A, B, C, sha1_R(37));
+    sha1_P(C, D, E, A, B, sha1_R(38));
+    sha1_P(B, C, D, E, A, sha1_R(39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+    sha1_P(A, B, C, D, E, sha1_R(40));
+    sha1_P(E, A, B, C, D, sha1_R(41));
+    sha1_P(D, E, A, B, C, sha1_R(42));
+    sha1_P(C, D, E, A, B, sha1_R(43));
+    sha1_P(B, C, D, E, A, sha1_R(44));
+    sha1_P(A, B, C, D, E, sha1_R(45));
+    sha1_P(E, A, B, C, D, sha1_R(46));
+    sha1_P(D, E, A, B, C, sha1_R(47));
+    sha1_P(C, D, E, A, B, sha1_R(48));
+    sha1_P(B, C, D, E, A, sha1_R(49));
+    sha1_P(A, B, C, D, E, sha1_R(50));
+    sha1_P(E, A, B, C, D, sha1_R(51));
+    sha1_P(D, E, A, B, C, sha1_R(52));
+    sha1_P(C, D, E, A, B, sha1_R(53));
+    sha1_P(B, C, D, E, A, sha1_R(54));
+    sha1_P(A, B, C, D, E, sha1_R(55));
+    sha1_P(E, A, B, C, D, sha1_R(56));
+    sha1_P(D, E, A, B, C, sha1_R(57));
+    sha1_P(C, D, E, A, B, sha1_R(58));
+    sha1_P(B, C, D, E, A, sha1_R(59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+    sha1_P(A, B, C, D, E, sha1_R(60));
+    sha1_P(E, A, B, C, D, sha1_R(61));
+    sha1_P(D, E, A, B, C, sha1_R(62));
+    sha1_P(C, D, E, A, B, sha1_R(63));
+    sha1_P(B, C, D, E, A, sha1_R(64));
+    sha1_P(A, B, C, D, E, sha1_R(65));
+    sha1_P(E, A, B, C, D, sha1_R(66));
+    sha1_P(D, E, A, B, C, sha1_R(67));
+    sha1_P(C, D, E, A, B, sha1_R(68));
+    sha1_P(B, C, D, E, A, sha1_R(69));
+    sha1_P(A, B, C, D, E, sha1_R(70));
+    sha1_P(E, A, B, C, D, sha1_R(71));
+    sha1_P(D, E, A, B, C, sha1_R(72));
+    sha1_P(C, D, E, A, B, sha1_R(73));
+    sha1_P(B, C, D, E, A, sha1_R(74));
+    sha1_P(A, B, C, D, E, sha1_R(75));
+    sha1_P(E, A, B, C, D, sha1_R(76));
+    sha1_P(D, E, A, B, C, sha1_R(77));
+    sha1_P(C, D, E, A, B, sha1_R(78));
+    sha1_P(B, C, D, E, A, sha1_R(79));
+
+#undef K
+#undef F
+
+    ctx->digest[0] += A;
+    ctx->digest[1] += B;
+    ctx->digest[2] += C;
+    ctx->digest[3] += D;
+    ctx->digest[4] += E;
+}
+
+void algo_sha1_update(algo_sha1_context* ctx, u1* input, u4 length)
+{
+    u4 left, fill;
+
+    if (!length) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = SHA1_BLOCK_LENGTH - left;
+
+    ctx->total[0] += length;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if(ctx->total[0] < length) {
+        ctx->total[1]++;
+    }
+
+    if (left && (length >= fill)) {
+        //CopyVolatile(input, ctx->input + left, fill);
+        memcpy(ctx->input + left,input,fill);
+        algo_sha1_compress(ctx, (u4*)ctx->input);
+        length -= fill;
+        input  += fill;
+        left = 0;
+    }
+
+    while(length >= SHA1_BLOCK_LENGTH) {
+        algo_sha1_compress(ctx, (u4*)input);
+        length -= SHA1_BLOCK_LENGTH;
+        input  += SHA1_BLOCK_LENGTH;
+    }
+
+    if (length) {
+        //CopyVolatile(input, ctx->input + left, length);
+        memcpy(ctx->input + left,input,length);
+    }
+}
+
+void algo_sha1_finish(algo_sha1_context *ctx)
+{
+    u4 last, padn;
+    u4 msglen[2];
+    u1 i;
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+        msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+    }
+    else
+    {
+        msglen[0] = (ctx->total[0] << 3);
+        msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+    }
+
+    last = ctx->total[0] & 0x3F;
+    padn = (last < (SHA1_BLOCK_LENGTH - sizeof(msglen))) ? ((SHA1_BLOCK_LENGTH - sizeof(msglen)) - last) : (((2 * SHA1_BLOCK_LENGTH) - sizeof(msglen)) - last);
+
+    algo_sha1_update(ctx, (u1*)sha1_padding, padn);
+    algo_sha1_update(ctx, (u1*)msglen, 8);
+
+	// little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        for (i = 0; i < (SHA1_HASH_LENGTH / sizeof(u4)); i++) {
+            ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+        }
+    }
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_sha1_h
+#define _include_algo_sha1_h
+
+typedef struct algo_sha1_context
+{
+    u4 total[2];
+    u4* digest;
+    u1* input;
+} algo_sha1_context;
+
+#define SHA1_HASH_LENGTH  20
+#define SHA1_BLOCK_LENGTH 64
+
+extern void algo_sha1_starts(algo_sha1_context* ctx);
+extern void algo_sha1_update(algo_sha1_context* ctx, u1* input, u4 length);
+extern void algo_sha1_finish(algo_sha1_context* ctx);
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,370 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_sha256.h"
+
+const u1 sha256_padding[64] =
+{
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define SHR(x,n)  ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define SHA256_S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
+#define SHA256_S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
+#define SHA256_S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^  ROTR(x,22))
+#define SHA256_S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^  ROTR(x,25))
+
+#define SHA256_F0(x,y,z) ((x & y) | (z & (x | y)))
+#define SHA256_F1(x,y,z) (z ^ (x & (y ^ z)))
+
+void algo_sha256_starts(algo_sha256_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->digest[0] = 0x6A09E667;
+    ctx->digest[1] = 0xBB67AE85;
+    ctx->digest[2] = 0x3C6EF372;
+    ctx->digest[3] = 0xA54FF53A;
+    ctx->digest[4] = 0x510E527F;
+    ctx->digest[5] = 0x9B05688C;
+    ctx->digest[6] = 0x1F83D9AB;
+    ctx->digest[7] = 0x5BE0CD19;
+}
+
+#ifdef _SHA256_SIZE_OPTIMIZED_VERSION
+
+    static algo_sha256_context* algo_sha256_tmpCtx;
+
+    static void sha256_P(u4 a, u4 b, u4 c, u4* d, u4 e, u4 f, u4 g, u4* h, u1 i, u4 K)
+    {
+        u4 temp1;
+        u4 temp2;
+
+	    if (i > 15) {
+    	    algo_sha256_tmpCtx->processingBuffer[i] = SHA256_S1(algo_sha256_tmpCtx->processingBuffer[i -  2]) + algo_sha256_tmpCtx->processingBuffer[i -  7] + SHA256_S0(algo_sha256_tmpCtx->processingBuffer[i - 15]) + algo_sha256_tmpCtx->processingBuffer[i - 16];
+	    }
+
+	    temp1 = *h + SHA256_S3(e) + SHA256_F1(e,f,g) + K + algo_sha256_tmpCtx->processingBuffer[i];
+	    temp2 = SHA256_S2(a) + SHA256_F0(a,b,c);
+
+        *d += temp1;
+	    *h = temp1 + temp2;
+    }
+
+    static void algo_sha256_compress(algo_sha256_context *ctx, u4* input)
+    {
+
+        u4 A, B, C, D, E, F, G, H;
+        u1 i;
+
+        // little endian processing
+        if (IS_LITTLE_ENDIAN)
+        {
+            for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+                ctx->processingBuffer[i] = swapbytes_u4(input[i]);
+            }
+        }
+        A = ctx->digest[0];
+        B = ctx->digest[1];
+        C = ctx->digest[2];
+        D = ctx->digest[3];
+        E = ctx->digest[4];
+        F = ctx->digest[5];
+        G = ctx->digest[6];
+        H = ctx->digest[7];
+
+        algo_sha256_tmpCtx = ctx;
+
+        sha256_P(A, B, C, &D, E, F, G, &H, 0, 0x428A2F98);
+        sha256_P(H, A, B, &C, D, E, F, &G, 1, 0x71374491);
+        sha256_P(G, H, A, &B, C, D, E, &F, 2, 0xB5C0FBCF);
+        sha256_P(F, G, H, &A, B, C, D, &E, 3, 0xE9B5DBA5);
+        sha256_P(E, F, G, &H, A, B, C, &D, 4, 0x3956C25B);
+        sha256_P(D, E, F, &G, H, A, B, &C, 5, 0x59F111F1);
+        sha256_P(C, D, E, &F, G, H, A, &B, 6, 0x923F82A4);
+        sha256_P(B, C, D, &E, F, G, H, &A, 7, 0xAB1C5ED5);
+        sha256_P(A, B, C, &D, E, F, G, &H, 8, 0xD807AA98);
+        sha256_P(H, A, B, &C, D, E, F, &G, 9, 0x12835B01);
+        sha256_P(G, H, A, &B, C, D, E, &F, 10, 0x243185BE);
+        sha256_P(F, G, H, &A, B, C, D, &E, 11, 0x550C7DC3);
+        sha256_P(E, F, G, &H, A, B, C, &D, 12, 0x72BE5D74);
+        sha256_P(D, E, F, &G, H, A, B, &C, 13, 0x80DEB1FE);
+        sha256_P(C, D, E, &F, G, H, A, &B, 14, 0x9BDC06A7);
+        sha256_P(B, C, D, &E, F, G, H, &A, 15, 0xC19BF174);
+        sha256_P(A, B, C, &D, E, F, G, &H, 16, 0xE49B69C1);
+        sha256_P(H, A, B, &C, D, E, F, &G, 17, 0xEFBE4786);
+        sha256_P(G, H, A, &B, C, D, E, &F, 18, 0x0FC19DC6);
+        sha256_P(F, G, H, &A, B, C, D, &E, 19, 0x240CA1CC);
+        sha256_P(E, F, G, &H, A, B, C, &D, 20, 0x2DE92C6F);
+        sha256_P(D, E, F, &G, H, A, B, &C, 21, 0x4A7484AA);
+        sha256_P(C, D, E, &F, G, H, A, &B, 22, 0x5CB0A9DC);
+        sha256_P(B, C, D, &E, F, G, H, &A, 23, 0x76F988DA);
+        sha256_P(A, B, C, &D, E, F, G, &H, 24, 0x983E5152);
+        sha256_P(H, A, B, &C, D, E, F, &G, 25, 0xA831C66D);
+        sha256_P(G, H, A, &B, C, D, E, &F, 26, 0xB00327C8);
+        sha256_P(F, G, H, &A, B, C, D, &E, 27, 0xBF597FC7);
+        sha256_P(E, F, G, &H, A, B, C, &D, 28, 0xC6E00BF3);
+        sha256_P(D, E, F, &G, H, A, B, &C, 29, 0xD5A79147);
+        sha256_P(C, D, E, &F, G, H, A, &B, 30, 0x06CA6351);
+        sha256_P(B, C, D, &E, F, G, H, &A, 31, 0x14292967);
+        sha256_P(A, B, C, &D, E, F, G, &H, 32, 0x27B70A85);
+        sha256_P(H, A, B, &C, D, E, F, &G, 33, 0x2E1B2138);
+        sha256_P(G, H, A, &B, C, D, E, &F, 34, 0x4D2C6DFC);
+        sha256_P(F, G, H, &A, B, C, D, &E, 35, 0x53380D13);
+        sha256_P(E, F, G, &H, A, B, C, &D, 36, 0x650A7354);
+        sha256_P(D, E, F, &G, H, A, B, &C, 37, 0x766A0ABB);
+        sha256_P(C, D, E, &F, G, H, A, &B, 38, 0x81C2C92E);
+        sha256_P(B, C, D, &E, F, G, H, &A, 39, 0x92722C85);
+        sha256_P(A, B, C, &D, E, F, G, &H, 40, 0xA2BFE8A1);
+        sha256_P(H, A, B, &C, D, E, F, &G, 41, 0xA81A664B);
+        sha256_P(G, H, A, &B, C, D, E, &F, 42, 0xC24B8B70);
+        sha256_P(F, G, H, &A, B, C, D, &E, 43, 0xC76C51A3);
+        sha256_P(E, F, G, &H, A, B, C, &D, 44, 0xD192E819);
+        sha256_P(D, E, F, &G, H, A, B, &C, 45, 0xD6990624);
+        sha256_P(C, D, E, &F, G, H, A, &B, 46, 0xF40E3585);
+        sha256_P(B, C, D, &E, F, G, H, &A, 47, 0x106AA070);
+        sha256_P(A, B, C, &D, E, F, G, &H, 48, 0x19A4C116);
+        sha256_P(H, A, B, &C, D, E, F, &G, 49, 0x1E376C08);
+        sha256_P(G, H, A, &B, C, D, E, &F, 50, 0x2748774C);
+        sha256_P(F, G, H, &A, B, C, D, &E, 51, 0x34B0BCB5);
+        sha256_P(E, F, G, &H, A, B, C, &D, 52, 0x391C0CB3);
+        sha256_P(D, E, F, &G, H, A, B, &C, 53, 0x4ED8AA4A);
+        sha256_P(C, D, E, &F, G, H, A, &B, 54, 0x5B9CCA4F);
+        sha256_P(B, C, D, &E, F, G, H, &A, 55, 0x682E6FF3);
+        sha256_P(A, B, C, &D, E, F, G, &H, 56, 0x748F82EE);
+        sha256_P(H, A, B, &C, D, E, F, &G, 57, 0x78A5636F);
+        sha256_P(G, H, A, &B, C, D, E, &F, 58, 0x84C87814);
+        sha256_P(F, G, H, &A, B, C, D, &E, 59, 0x8CC70208);
+        sha256_P(E, F, G, &H, A, B, C, &D, 60, 0x90BEFFFA);
+        sha256_P(D, E, F, &G, H, A, B, &C, 61, 0xA4506CEB);
+        sha256_P(C, D, E, &F, G, H, A, &B, 62, 0xBEF9A3F7);
+        sha256_P(B, C, D, &E, F, G, H, &A, 63, 0xC67178F2);
+
+        ctx->digest[0] += A;
+        ctx->digest[1] += B;
+        ctx->digest[2] += C;
+        ctx->digest[3] += D;
+        ctx->digest[4] += E;
+        ctx->digest[5] += F;
+        ctx->digest[6] += G;
+        ctx->digest[7] += H;
+    }
+
+#else
+
+    #define SHA256_R(t)                                       \
+    (                                                         \
+        ctx->processingBuffer[t] = SHA256_S1(ctx->processingBuffer[t -  2]) + ctx->processingBuffer[t -  7] +    \
+                SHA256_S0(ctx->processingBuffer[t - 15]) + ctx->processingBuffer[t - 16]      \
+    )
+
+    #define SHA256_P(a,b,c,d,e,f,g,h,x,K)                         \
+    {                                                             \
+        temp1 = h + SHA256_S3(e) + SHA256_F1(e,f,g) + K + x;      \
+        temp2 = SHA256_S2(a) + SHA256_F0(a,b,c);                  \
+        d += temp1; h = temp1 + temp2;                            \
+    }
+
+    static void algo_sha256_compress(algo_sha256_context *ctx, u4* input)
+    {
+        u4 temp1, temp2;
+        u4 A, B, C, D, E, F, G, H;
+        u1 i;
+
+        // little endian processing
+        if (IS_LITTLE_ENDIAN)
+        {
+            for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+                ctx->processingBuffer[i] = swapbytes_u4(input[i]);
+            }
+        }
+        else
+        {
+            for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+                ctx->processingBuffer[i] = input[i];
+            }
+        }
+
+        A = ctx->digest[0];
+        B = ctx->digest[1];
+        C = ctx->digest[2];
+        D = ctx->digest[3];
+        E = ctx->digest[4];
+        F = ctx->digest[5];
+        G = ctx->digest[6];
+        H = ctx->digest[7];
+
+        SHA256_P( A, B, C, D, E, F, G, H, ctx->processingBuffer[ 0], 0x428A2F98 );
+        SHA256_P( H, A, B, C, D, E, F, G, ctx->processingBuffer[ 1], 0x71374491 );
+        SHA256_P( G, H, A, B, C, D, E, F, ctx->processingBuffer[ 2], 0xB5C0FBCF );
+        SHA256_P( F, G, H, A, B, C, D, E, ctx->processingBuffer[ 3], 0xE9B5DBA5 );
+        SHA256_P( E, F, G, H, A, B, C, D, ctx->processingBuffer[ 4], 0x3956C25B );
+        SHA256_P( D, E, F, G, H, A, B, C, ctx->processingBuffer[ 5], 0x59F111F1 );
+        SHA256_P( C, D, E, F, G, H, A, B, ctx->processingBuffer[ 6], 0x923F82A4 );
+        SHA256_P( B, C, D, E, F, G, H, A, ctx->processingBuffer[ 7], 0xAB1C5ED5 );
+        SHA256_P( A, B, C, D, E, F, G, H, ctx->processingBuffer[ 8], 0xD807AA98 );
+        SHA256_P( H, A, B, C, D, E, F, G, ctx->processingBuffer[ 9], 0x12835B01 );
+        SHA256_P( G, H, A, B, C, D, E, F, ctx->processingBuffer[10], 0x243185BE );
+        SHA256_P( F, G, H, A, B, C, D, E, ctx->processingBuffer[11], 0x550C7DC3 );
+        SHA256_P( E, F, G, H, A, B, C, D, ctx->processingBuffer[12], 0x72BE5D74 );
+        SHA256_P( D, E, F, G, H, A, B, C, ctx->processingBuffer[13], 0x80DEB1FE );
+        SHA256_P( C, D, E, F, G, H, A, B, ctx->processingBuffer[14], 0x9BDC06A7 );
+        SHA256_P( B, C, D, E, F, G, H, A, ctx->processingBuffer[15], 0xC19BF174 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(16), 0xE49B69C1 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(17), 0xEFBE4786 );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(18), 0x0FC19DC6 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(19), 0x240CA1CC );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(20), 0x2DE92C6F );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(21), 0x4A7484AA );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(22), 0x5CB0A9DC );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(23), 0x76F988DA );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(24), 0x983E5152 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(25), 0xA831C66D );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(26), 0xB00327C8 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(27), 0xBF597FC7 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(28), 0xC6E00BF3 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(29), 0xD5A79147 );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(30), 0x06CA6351 );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(31), 0x14292967 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(32), 0x27B70A85 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(33), 0x2E1B2138 );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(34), 0x4D2C6DFC );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(35), 0x53380D13 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(36), 0x650A7354 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(37), 0x766A0ABB );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(38), 0x81C2C92E );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(39), 0x92722C85 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(40), 0xA2BFE8A1 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(41), 0xA81A664B );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(42), 0xC24B8B70 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(43), 0xC76C51A3 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(44), 0xD192E819 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(45), 0xD6990624 );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(46), 0xF40E3585 );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(47), 0x106AA070 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(48), 0x19A4C116 );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(49), 0x1E376C08 );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(50), 0x2748774C );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(51), 0x34B0BCB5 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(52), 0x391C0CB3 );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(53), 0x4ED8AA4A );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(54), 0x5B9CCA4F );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(55), 0x682E6FF3 );
+        SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(56), 0x748F82EE );
+        SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(57), 0x78A5636F );
+        SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(58), 0x84C87814 );
+        SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(59), 0x8CC70208 );
+        SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(60), 0x90BEFFFA );
+        SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(61), 0xA4506CEB );
+        SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(62), 0xBEF9A3F7 );
+        SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(63), 0xC67178F2 );
+
+        ctx->digest[0] += A;
+        ctx->digest[1] += B;
+        ctx->digest[2] += C;
+        ctx->digest[3] += D;
+        ctx->digest[4] += E;
+        ctx->digest[5] += F;
+        ctx->digest[6] += G;
+        ctx->digest[7] += H;
+    }
+
+#endif
+
+
+void algo_sha256_update(algo_sha256_context *ctx, u1 *input, u4 length )
+{
+    u4 left, fill;
+
+    if(!length ) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = SHA256_BLOCK_LENGTH - left;
+
+    ctx->total[0] += length;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < length )
+        ctx->total[1]++;
+
+    if( left && length >= fill )
+    {
+        memcpy(ctx->input + left,input,fill);
+
+        algo_sha256_compress( ctx,(u4*)ctx->input );
+        length -= fill;
+        input  += fill;
+        left = 0;
+    }
+
+    while( length >= SHA256_BLOCK_LENGTH )
+    {
+        algo_sha256_compress( ctx, (u4*)input );
+        length -= SHA256_BLOCK_LENGTH;
+        input  += SHA256_BLOCK_LENGTH;
+    }
+
+    if( length ){
+        memcpy(ctx->input + left,input,length);
+    }
+}
+
+void algo_sha256_finish(algo_sha256_context *ctx)
+{
+    u4 last, padn;
+    u4 msglen[2];
+    u1 i;
+
+    // little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+        msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+    }
+    else
+    {
+        msglen[0] = (ctx->total[0] << 3);
+        msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+    }
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    algo_sha256_update( ctx, (u1*)sha256_padding, padn );
+    algo_sha256_update( ctx, (u1*)msglen, 8 );
+
+    // little endian processing
+    if (IS_LITTLE_ENDIAN)
+    {
+        for (i = 0; i < (SHA256_HASH_LENGTH / sizeof(u4)); i++) {
+            ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+        }
+    }
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,40 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_sha256_h
+#define _include_algo_sha256_h
+
+#define SHA256_HASH_LENGTH  32
+#define SHA256_BLOCK_LENGTH 64
+
+typedef struct algo_sha256_context
+{
+    u4  total[2];
+    u4  processingBuffer[SHA256_BLOCK_LENGTH];
+    u4* digest;
+    u1* input;
+} algo_sha256_context;
+
+extern void algo_sha256_starts(algo_sha256_context* ctx);
+extern void algo_sha256_update(algo_sha256_context* ctx, u1* input, u4 length);
+extern void algo_sha256_finish(algo_sha256_context* ctx);
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,34 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+
+u4 swapbytes_u4(u4 val)
+{
+    u4 res;
+    res =  val << 24;
+    res |= (val << 8) & 0x00FF0000;
+    res |= (val >> 8) & 0x0000FF00;
+    res |= val >> 24;
+    return (res);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,27 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_algo_utils_h
+#define _include_algo_utils_h
+
+extern u4 swapbytes_u4(u4 val);
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,738 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <winscard.h>
+#include "cardmoduleservice.h"
+
+#include <string>
+
+#include <assert.h>
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "session.h"
+#include "slot.h"
+#include "application.h"
+#include "log.h"
+
+#ifdef _XCL_
+#include <xcl_utils.h>
+#endif // _XCL_
+
+#ifdef __sun
+typedef LPSTR LPTSTR;
+#endif
+
+// Initialization of Static fields
+SCARDCONTEXT Application::_hContext = 0;
+
+Slot* Application::_slotCache[CONFIG_MAX_SLOT] = {
+   NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,
+   NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR
+};
+
+CK_ULONG Application::_numSlots = 0;
+
+#ifdef _XCL_
+xCL_DeviceHandle Application::_deviceHandle = 0; // asadali
+#endif // _XCL_
+
+
+/*
+*/
+#ifndef _XCL_
+CK_RV Application::InitApplication( )
+{
+   Log::begin( "Application::InitApplication" );
+
+   // do the enumeration of slots
+   CK_ULONG hResult = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &Application::_hContext );
+
+   Log::log( "Application::InitApplication - SCardEstablishContext <%#02x>", hResult );
+   Log::log( "Application::InitApplication - Application::_hContext <%#02x>", Application::_hContext );
+
+   if( SCARD_S_SUCCESS != hResult )
+   {
+      return CKR_GENERAL_ERROR;
+   }
+
+#ifdef __APPLE__
+   /* Apple bug 5256035 */
+   {
+      SCARDHANDLE h;
+      DWORD p;
+      SCardConnect(Application::_hContext, "fake reader", SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &h, &p);
+   }
+#endif
+
+   Log::end( "Application::InitApplication" );
+
+   return CKR_OK;
+}
+
+#else // _XCL_
+
+CK_RV Application::InitApplication( )
+{
+    Log::begin( "Application::InitApplication" );
+    u4 deviceID;
+    u4 rv;
+    xCL_DevicePtr deviceList;
+    xCL_DevicePtr device;
+    u4 numberOfDevices;
+    u4 i;
+
+    PRINT_MSG("IN Application::Init");
+
+    rv = xCL_InterfaceInit();
+
+    rv = xCL_DiscoverDevices(&deviceList, &numberOfDevices);
+    if (rv == 0 && numberOfDevices != 0)
+    {
+        // Pick the first device, with ID=0
+        device = deviceList + 0;
+        deviceID = device->deviceID ;
+        PRINT_DATA(NULL, 0, (char*)device->uniqueName);
+
+        // Create device handle
+        rv = xCL_CreateHandleFromDeviceID(deviceID, &Application::_deviceHandle);
+        if (rv == 0)
+        {
+            PRINT_MSG("IN Application::Init , device handle created");
+        }
+
+        // Free memory for all devices
+        for (i=0; i<numberOfDevices; i++)
+        {
+            rv = xCL_FreeDeviceMemory(deviceList + i);
+        }
+    }
+    return CKR_OK;
+}
+
+#endif // _XCL_
+
+
+/*
+*/
+
+#ifndef _XCL_
+
+CK_RV Application::Enumerate( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+   Log::begin( "Application::Enumerate" );
+
+   CK_ULONG   slotNb              = 0;
+   LPTSTR     pReader             = NULL;
+   CK_LONG    hResult             = 0;
+   CK_SLOT_ID sid                 = 0;
+
+   if( NULL_PTR == pulCount )
+   {
+      Log::error( "Application::Enumerate", "CKR_ARGUMENTS_BAD" );
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   // Get the supported readers from the current cache
+   std::string currentCache[ CONFIG_MAX_SLOT ];
+   for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      currentCache[ i ] = "";
+      if( NULL_PTR != Application::_slotCache[ i ] )
+      {
+         currentCache[ i ] = *(Application::_slotCache[ i ]->_readerName);
+         Log::log( "Application::Enumerate - currentCache[ %d ] <%s>", i, currentCache[ i ].c_str( ) );
+      }
+   }
+
+   // Get the readers from the PCSC layer
+   DWORD readerListCharLength = 0;
+   hResult = SCardListReaders( Application::_hContext, NULL, NULL, &readerListCharLength );
+   Log::log( "Application::Enumerate - readerListCharLength <%#02x>", readerListCharLength );
+   Log::log( "Application::Enumerate - SCardListReaders <%#02x>", hResult );
+   if( SCARD_S_SUCCESS != hResult )
+   {
+      Log::error( "Application::Enumerate", "CKR_GENERAL_ERROR" );
+      return CKR_GENERAL_ERROR;
+   }
+
+   LPTSTR pReaderList = (lpCharPtr)malloc( sizeof(char) * readerListCharLength );
+   if( NULL == pReaderList )
+   {
+      Log::error( "Application::Enumerate", "CKR_HOST_MEMORY" );
+      return CKR_HOST_MEMORY;
+   }
+   memset( pReaderList, 0, sizeof(char) * readerListCharLength );
+
+   hResult = SCardListReaders( Application::_hContext, NULL, pReaderList, &readerListCharLength);
+   Log::log( "Application::Enumerate - SCardListReaders 2 <%#02x>", hResult );
+   if( SCARD_S_SUCCESS != hResult )
+   {
+      free( pReaderList );
+      Log::error( "Application::Enumerate", "CKR_GENERAL_ERROR" );
+      return CKR_GENERAL_ERROR;
+   }
+
+   // Construct the PCSC reader list
+   std::string currentPcscList[ CONFIG_MAX_SLOT ];
+   for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      currentPcscList[ i ] = "";
+   }
+   pReader = pReaderList; //readers;
+   int i = 0;
+   while( pReader && ( '\0' != *pReader ) )
+   {
+      currentPcscList[ i ] = pReader;
+      Log::log( "Application::Enumerate - PCSC List[ %d ] <%s>", i, currentPcscList[ i ].c_str( ) );
+      i++;
+      if( i > CONFIG_MAX_SLOT )
+      {
+         /*
+         free( pReaderList );
+         Log::error( "Application::Enumerate", "CKR_HOST_MEMORY" );
+         return CKR_HOST_MEMORY;
+         */
+         break;
+      }
+
+      // Advance to the next value.
+      size_t readerNameLen = strlen( (const char*)pReader );
+      pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+   }
+   free( pReaderList );
+
+   // Does a reader desappeared ?
+   for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      if( NULL_PTR != Application::_slotCache[ i ] )
+      {
+         //printf( "Application::_slotCache[ %lu ]->_readerName <%s>\n", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+
+         bool bFound = false;
+         for( int j = 0 ; j < CONFIG_MAX_SLOT; j++ )
+         {
+            //printf( "currentPcscList[ %d ] <%s>\n", j, currentPcscList[ j ].c_str( ) );
+
+            if( 0 == (Application::_slotCache[ i ]->_readerName)->compare( currentPcscList[ j ] ) )
+            {
+               bFound = true;
+               //printf( "!! Found !!\n" );
+               break;
+            }
+         }
+         if( false == bFound )
+         {
+            // Not found into the PCSC reader list
+            deleteSlot( i );
+            //printf( "!! Not Found -> delete !!\n" );
+         }
+      }
+   }
+
+   // Does a new reader appears ?
+   //printf( "\n\nDoes a new reader appears ?\n" );
+   for( int i = 0; i < CONFIG_MAX_SLOT; i++ )
+   {
+      if( false == currentPcscList[ i ].empty( ) )
+      {
+         //printf( "currentPcscList[ %d ] <%s>\n", i, currentPcscList[ i ].c_str( ) );
+
+         bool bFound = false;
+         for( int j = 0 ; j < CONFIG_MAX_SLOT; j++ )
+         {
+            if( 0 != Application::_slotCache[ j ] )
+            {
+               //printf( "   Application::_slotCache[ %d ] <%s>\n", j, Application::_slotCache[ j ]->_readerName->c_str( ) );
+               if( 0 == ( currentPcscList[ i ].compare( *(Application::_slotCache[ j ]->_readerName) ) ) )
+               {
+                  bFound = true;
+                  //printf( "   !! Found !!\n" );
+                  break;
+               }
+            }
+         }
+         if( false == bFound )
+         {
+            //printf( "!! Not Found -> add !!\n" );
+
+            CK_RV rv = addSlot( currentPcscList[ i ] );
+            if( CKR_OK != rv )
+            {
+               Log::error( "Application::Enumerate", "addSlot failed" );
+               return rv;
+            }
+         }
+      }
+   }
+
+
+   // Scan Reader List
+   slotNb = 0;
+   Application::_numSlots = 0;
+   for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+   {
+      // Existing Slots only are scanned
+      if (Application::_slotCache[i] != NULL_PTR)
+      {
+         //Log::log( "Application::Enumerate - New Cache[ %d ] <%s>", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+         Application::_numSlots++;
+
+         SCARD_READERSTATE readerStates;
+         memset( &readerStates, 0, sizeof( SCARD_READERSTATE ) );
+         readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+         readerStates.szReader = Application::_slotCache[i]->_readerName->c_str();
+
+         // Lets check if token is present or not
+         if (SCardGetStatusChange(Application::_hContext, 100, &readerStates, 1) == SCARD_S_SUCCESS)
+         {
+            if ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+            {
+               // We found a card in this reader
+               Application::_slotCache[i]->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+               Log::log( "Application::Enumerate - New Cache[ %d ] - Name <%s> - Token present", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+            }
+            else
+            {
+               // No card in this reader
+               Application::_slotCache[i]->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+               Log::log( "Application::Enumerate - New Cache[ %d ] - Name <%s> - Token NOT present", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+            }
+         }
+
+         // Slots with Token Present
+         if((tokenPresent == TRUE) &&
+            (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+         {
+            slotNb++;
+         }
+         // All slots
+         else if (tokenPresent == FALSE)
+         {
+            slotNb++;
+         }
+      }
+   }
+
+   // If pSlotList is not NULL then *pulCount contains the buffer size of pSlotList
+   // so we need to check if size passed is valid or not.
+   if((pSlotList != NULL_PTR)&&(*pulCount < slotNb))
+   {
+      *pulCount = slotNb;
+      Log::error( "Application::Enumerate", "CKR_BUFFER_TOO_SMALL" );
+      return CKR_BUFFER_TOO_SMALL;
+   }
+
+   *pulCount = slotNb;
+
+   // Fill slot list if not NULL
+   if (pSlotList != NULL_PTR)
+   {
+      for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+      {
+         // Existing Slots only are scanned
+         if (Application::_slotCache[i] != NULL_PTR)
+         {
+            CK_BBOOL IsFound = FALSE;
+
+            // Slots with Token Present
+            if((tokenPresent == TRUE) &&
+               (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+            {
+               IsFound = TRUE;
+            }
+
+            // All slots
+            else if (tokenPresent == FALSE)
+            {
+               IsFound = TRUE;
+            }
+
+            // Fill Slot List
+            if(IsFound == TRUE)
+            {
+               pSlotList[sid++] = Application::_slotCache[i]->_slotId;
+            }
+         }
+      }
+   }
+
+   Log::end( "Application::Enumerate" );
+
+   return CKR_OK;
+}
+
+#else // _XCL_
+
+CK_RV Application::Enumerate( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+    PRINT_MSG("IN Application::Enumerate");
+
+    LPTSTR     pReaderList         = NULL;
+    CK_SLOT_ID slotIdx             = 0;
+    CK_ULONG   slotNb              = 0;
+    LPTSTR     pReader             = NULL;
+    CK_LONG    hResult             = 0;
+    CK_SLOT_ID sid                 = 0;
+
+    if(pulCount == NULL_PTR){
+        return CKR_ARGUMENTS_BAD;
+    }
+
+    DWORD readerListCharLength = SCARD_AUTOALLOCATE;
+
+    // asadali
+    // Get reader list, For now only ONE SEG-Lite token ...
+    pReaderList = (char *) malloc(64);
+    strcpy(pReaderList, "xCL_Token");
+    readerListCharLength = strlen(pReaderList);
+    *(pReaderList + readerListCharLength) = '\0';
+    *(pReaderList + readerListCharLength + 1) = '\0';
+
+    // Get Reader List if not already Get
+    if (Application::_numSlots == 0)
+    {
+        // clear the slot cache
+        //CSlot::ClearCache();
+
+        pReader = pReaderList;
+
+        while ('\0' != *pReader )
+        {
+            size_t readerNameLen = strlen((const char*)pReader);
+            size_t sd;
+
+            Slot* slot         = new Slot();
+            slot->_slotId      = slotIdx++;
+
+            // fill in the slot description
+            for(sd = 0; sd < readerNameLen; sd++)
+            {
+                slot->_slotInfo.slotDescription[sd] = pReader[sd];
+            }
+
+            if(slotIdx > CONFIG_MAX_SLOT){
+                return CKR_HOST_MEMORY;
+            }
+
+            slotNb++;
+
+            slot->_readerName  = new std::string(pReader);
+
+// GD            Application::AddSlotToCache(slot);
+                Application::addSlot (slot);
+
+            // Advance to the next value.
+            pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+        }
+
+        free(pReaderList);
+        Application::_numSlots = slotNb;
+    }
+
+    // Scan Reader List
+    slotNb = 0;
+
+    for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+    {
+        // Existing Slots only are scanned
+        if (Application::_slotCache[i] != NULL_PTR)
+        {
+            SCARD_READERSTATE readerStates;
+
+            readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+            readerStates.szReader = Application::_slotCache[i]->_readerName->c_str();
+
+            // Lets check if token is present or not
+
+            // asadali
+            if (xCL_IsTokenPresent())
+            {
+                // We found a card in this reader
+                Application::_slotCache[i]->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+            }
+            else
+            {
+                // No card in reader
+                Application::_slotCache[i]->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+            }
+
+            // Slots with Token Present
+            if((tokenPresent == TRUE) &&
+               (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+            {
+                slotNb++;
+            }
+            // All slots
+            else if (tokenPresent == FALSE)
+            {
+                slotNb++;
+            }
+        }
+    }
+
+    // If pSlotList is not NULL then *pulCount contains the buffer size of pSlotList
+    // so we need to check if size passed is valid or not.
+    if((pSlotList != NULL_PTR)&&(*pulCount < slotNb))
+    {
+        *pulCount = slotNb;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+
+    *pulCount = slotNb;
+
+    // Fill slot list if not NULL
+    if (pSlotList != NULL_PTR)
+    {
+        for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+        {
+            // Existing Slots only are scanned
+            if (Application::_slotCache[i] != NULL_PTR)
+            {
+                CK_BBOOL IsFound = FALSE;
+
+                // Slots with Token Present
+                if((tokenPresent == TRUE) &&
+                   (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+                {
+                    IsFound = TRUE;
+                }
+
+                // All slots
+                else if (tokenPresent == FALSE)
+                {
+                    IsFound = TRUE;
+                }
+
+                // Fill Slot List
+                if(IsFound == TRUE)
+                {
+                    pSlotList[sid++] = Application::_slotCache[i]->_slotId;
+                }
+            }
+        }
+    }
+
+    return CKR_OK;
+}
+
+#endif // _XCL_
+
+/*
+*/
+CK_RV Application::GetSlotFromSlotId( CK_SLOT_ID slotId, Slot** slot )
+{
+   if(((int)slotId < 0) || (slotId >= CONFIG_MAX_SLOT))
+   {
+      return CKR_SLOT_ID_INVALID;
+   }
+
+   if (Application::_slotCache[slotId] != NULL_PTR)
+   {
+      *slot = Application::_slotCache[slotId];
+      return CKR_OK;
+   }
+
+   return CKR_SLOT_ID_INVALID;
+}
+
+
+/*
+*/
+void Application::ClearCache(void)
+{
+   // initialize the slot cache
+   CK_SLOT_ID sid = 0;
+   for(;sid<CONFIG_MAX_SLOT;sid++)
+   {
+      if(Application::_slotCache[sid] != NULL_PTR)
+      {
+         Slot* slot = Application::_slotCache[sid];
+#ifdef INCLUDE_EVENTING
+         if(slot->_tracker != NULL_PTR)
+         {
+            slot->_tracker->stop();
+         }
+#endif
+
+         delete slot;
+         Application::_slotCache[sid] = NULL_PTR;
+      }
+   }
+
+   // set the number of actual slots present to zero
+   Application::_numSlots = 0;
+
+#ifdef INCLUDE_EVENTING
+   // we should just signal all the events
+   CryptokiEvent.Signal();
+#endif
+}
+
+
+/*
+*/
+void Application::Release( void )
+{
+   if( 0 != Application::_hContext )
+   {
+#ifndef _XCL_
+      SCardReleaseContext( Application::_hContext );
+#endif // _XCL_
+      Application::_hContext = 0;
+   }
+}
+
+
+/*
+*/
+void Application::End( void )
+{
+   Application::ClearCache( );
+   Application::Release( );
+}
+
+
+/*
+*/
+void Application::deleteSlot( int i )
+{
+   if( NULL_PTR != Application::_slotCache[ i ] )
+   {
+#ifdef INCLUDE_EVENTING
+      if( NULL_PTR != (Application::_slotCache[ i ]->_tracker) )
+      {
+         (Application::_slotCache[ i ])->_tracker->stop( );
+      }
+#endif
+      delete (Application::_slotCache[ i ]);
+      Application::_slotCache[ i ] = NULL_PTR;
+
+#ifdef INCLUDE_EVENTING
+      // we should just signal all the events
+      CryptokiEvent.Signal( );
+#endif
+
+   }
+}
+
+
+/*
+*/
+
+#ifndef _XCL_
+
+CK_RV Application::addSlot( std::string& a_readerName )
+{
+   int iSlotID = -1;
+   for( int j = 0 ; j < CONFIG_MAX_SLOT ; j++ )
+   {
+      if( NULL_PTR == Application::_slotCache[ j ] )
+      {
+         iSlotID = j;
+         break;
+      }
+   }
+   if( -1 == iSlotID )
+   {
+      return CKR_HOST_MEMORY;
+   }
+
+   Slot* slot = new Slot( );
+   slot->_readerName  = new std::string( a_readerName );
+
+   // Fill in the slot description
+   size_t l = ( a_readerName.length( ) > sizeof( slot->_slotInfo.slotDescription ) ) ? sizeof( slot->_slotInfo.slotDescription ) : a_readerName.length( );
+   for( size_t i = 0 ; i < l ; i++ )
+   {
+      slot->_slotInfo.slotDescription[ i ] = a_readerName[ i ];
+   }
+
+   // Add Slot in Cache
+   slot->_slotId = iSlotID;
+   Application::_slotCache[ iSlotID ] = slot;
+
+#ifdef INCLUDE_EVENTING
+   SCARD_READERSTATE readerStates;
+
+   readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+   readerStates.szReader = slot->_readerName->c_str();
+
+   if (SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+   {
+      if ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)
+      {
+         // we not found a card in this reader
+         slot->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+      }
+      else
+      {
+         // we found a card in this reader
+         slot->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+      }
+   }
+
+   // Start the monitoring also
+   slot->_tracker = new CardMonitoringThread(slot->_readerName->c_str());
+   slot->_tracker->SetSlot(slot);
+   slot->_tracker->start();
+
+#endif
+
+   return CKR_OK;
+}
+
+#else // _XCL_
+
+void Application::addSlot( Slot* slot )
+{
+    PRINT_MSG("IN Application::AddslotToCache");
+
+    // Add Slot in Cache
+    Application::_slotCache[slot->_slotId] = slot;
+
+#ifdef INCLUDE_EVENTING
+    SCARD_READERSTATE readerStates;
+
+    readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+    readerStates.szReader = slot->_readerName->c_str();
+
+    // asadali
+    if (xCL_IsTokenPresent())
+    {
+        // we found a card in this reader
+        slot->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+    }
+    else
+    {
+        // No card in reader
+        slot->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+    }
+
+    // Start the monitoring also
+    slot->_tracker = new CardMonitoringThread(slot->_readerName->c_str());
+    slot->_tracker->SetSlot(slot);
+    slot->_tracker->start();
+#endif
+}
+
+#endif // _XCL_

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,66 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_application_h
+#define _include_application_h
+
+#include <vector>
+#include <list>
+
+#ifdef _XCL_
+#include <xcl_utils.h>
+#endif // _XCL_
+
+using namespace std;
+
+class Application {
+
+public:
+   static CK_ULONG _numSlots;
+   static Slot* _slotCache[CONFIG_MAX_SLOT];
+   static SCARDCONTEXT _hContext;
+
+#ifdef _XCL_
+    static xCL_DeviceHandle _deviceHandle;
+#endif // _XCL_
+
+public:
+   static CK_RV InitApplication(void);
+
+   static CK_RV Enumerate(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+
+   static CK_RV GetSlotFromSlotId(CK_SLOT_ID slotId, Slot** slot);
+
+//   static void AddSlotToCache(Slot* slot);
+	static void addSlot( Slot* slot );
+
+   static void ClearCache();
+
+   static void Release( void );
+   static void End( void );
+   //static void ReleaseThreads( void );
+
+   static void deleteSlot( int i );
+   static CK_RV addSlot( std::string& a_readerName );
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,221 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+//#pragma warning(disable : 4251)
+
+#include "stdafx.h"
+#include "platconfig.h"
+//#include "config.h"
+//#include "dbg.h"
+
+
+
+#include <numeric>
+#include <functional>
+#include "attrcert.h"
+#include "digest.h"
+#include "sha1.h"
+
+using namespace std;
+
+namespace
+{
+
+    class JoinWith
+        : public binary_function<string, string, string>
+    {
+    public:
+
+        explicit
+        JoinWith(second_argument_type const &rGlue)
+            : m_Glue(rGlue)
+        {}
+
+
+        result_type
+        operator()(string const &rFirst,
+                   string const &rSecond) const
+        {
+            return rFirst + m_Glue + rSecond;
+        }
+
+    private:
+
+        second_argument_type const m_Glue;
+    };
+
+    string
+    Combine(vector<string> const &rvsNames)
+    {
+        static string::value_type const cBlank = ' ';
+        static string const sBlank(1, cBlank);
+
+        if(!rvsNames.empty())
+            return accumulate(rvsNames.begin() + 1, rvsNames.end(),
+                              *rvsNames.begin(), JoinWith(sBlank));
+        else
+            return string();
+    }
+
+} // namespace
+
+CAttributedCertificate::CAttributedCertificate(BEROctet::Blob const &cert) : m_x509cert(cert)
+{
+}
+
+CAttributedCertificate::CAttributedCertificate(const unsigned char * cert, size_t length)
+                                            : m_x509cert(cert, static_cast<unsigned long>(length))
+{
+}
+
+CAttributedCertificate::~CAttributedCertificate()
+{
+}
+
+BEROctet::Blob
+CAttributedCertificate::Modulus() const
+{
+    return m_x509cert.Modulus();
+}
+
+BEROctet::Blob
+CAttributedCertificate::PublicExponent() const
+{
+    return m_x509cert.PublicExponent();
+}
+
+BEROctet::Blob
+CAttributedCertificate::Subject() const
+{
+    return m_x509cert.Subject();
+}
+
+BEROctet::Blob
+CAttributedCertificate::Issuer() const
+{
+    return m_x509cert.Issuer();
+}
+
+BEROctet::Blob
+CAttributedCertificate::SerialNumber() const
+{
+    return m_x509cert.SerialNumber();
+}
+
+string
+CAttributedCertificate::DerivedName() const
+{
+    string sDerivedName(Combine(m_x509cert.UTF8SubjectCommonName()));
+    if(sDerivedName.empty())
+        sDerivedName.assign("Smart Card User");
+    return sDerivedName;
+}
+
+string
+CAttributedCertificate::DerivedLabel() const
+{
+    return Combine(m_x509cert.SubjectCommonName());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId() const
+{
+    return DerivedId(m_x509cert.Modulus());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId(BEROctet::Blob const & data)
+{
+    return DerivedId(data.c_str(), data.size());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId(unsigned char const * data, size_t length)
+{
+    CSHA1 sha1;
+    u1 hash[20];
+    sha1.HashCore(const_cast<CK_BYTE_PTR>(data), 0, static_cast<CK_LONG>(length));
+    sha1.HashFinal(hash);
+
+    return BEROctet::Blob(hash, 20);
+}
+
+string
+CAttributedCertificate::DerivedUniqueName() const
+{
+    return DerivedUniqueName(m_x509cert.Modulus());
+}
+
+string
+CAttributedCertificate::DerivedUniqueName(BEROctet::Blob const & data)
+{
+    return DerivedUniqueName(data.c_str(), data.size());
+}
+
+string
+CAttributedCertificate::DerivedUniqueName(unsigned char const * data, size_t length)
+{
+    CSHA1 sha1;
+    u1 hash[20];
+    sha1.HashCore(const_cast<CK_BYTE_PTR>(data), 0, static_cast<CK_LONG>(length));
+    sha1.HashFinal(hash);
+
+    // Format as a GUID
+
+    char name[40];
+
+    u1 *id = hash;
+
+    int i, n = 0;
+    char *c = name;
+
+    for(i=0; i<4; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<2; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<2; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<2; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+    sprintf(c,"-");
+    c++;
+    for(i=0; i<6; i++) {
+        sprintf(c,"%02x",id[n]);
+        n++; c+=2;
+    }
+
+    return string(name);
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,84 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_attrcert_h
+#define _include_attrcert_h
+
+#include "x509cert.h"
+
+
+class CAttributedCertificate
+{
+
+public:
+    explicit CAttributedCertificate(BEROctet::Blob const &cert);
+    CAttributedCertificate(const unsigned char * cert, size_t length);
+
+    virtual ~CAttributedCertificate();
+
+    BEROctet::Blob
+    Modulus() const;
+
+    BEROctet::Blob
+    PublicExponent() const;
+
+    BEROctet::Blob
+    Subject() const;
+
+    BEROctet::Blob
+    Issuer() const;
+
+    BEROctet::Blob
+    SerialNumber() const;
+
+    std::string
+    DerivedName() const;
+
+    std::string
+    DerivedLabel() const;
+
+    BEROctet::Blob
+    DerivedId() const;
+
+    static BEROctet::Blob
+    DerivedId(BEROctet::Blob const & data);
+
+    static BEROctet::Blob
+    DerivedId(unsigned char const * data, size_t length);
+
+    std::string
+    DerivedUniqueName() const;
+
+    static std::string
+    DerivedUniqueName(BEROctet::Blob const & data);
+
+    static std::string
+    DerivedUniqueName(unsigned char const * data, size_t length);
+
+private:
+    X509Cert m_x509cert;
+
+};
+
+
+#endif // _include_attrcert_h
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,739 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This implementation is based on X.690 specification. Access to this
+// specification is a pre-requisite to understand the logic. The spec
+// can be purchased from International Telecommunication Union (ITU)
+// at http://www.itu.int
+
+// This code is based on class in ACS baseline.
+
+#include <string.h>
+#include <stdlib.h>
+#include "beroctet.h"
+
+using namespace std;
+
+BEROctet::BEROctet() : m_tcClass(tcUniversal),
+                       m_fConstructed(fBerPcPrimitive),
+                       m_dwTag(dwBerUnivZero),
+                       m_fDefinite(true),
+                       m_fModified(true)
+{
+}
+
+BEROctet::BEROctet(BEROctet const &oct)
+{
+    *this = oct;
+}
+
+BEROctet::BEROctet(Blob const &blb)
+{
+    Decode(blb);
+}
+
+BEROctet::BEROctet(TagClass tcClass, bool fConstructed, unsigned int dwTag, bool fDefinite) :
+                                                                       m_tcClass(tcClass),
+                                                                       m_fConstructed(fConstructed),
+                                                                       m_dwTag(dwTag),
+                                                                       m_fDefinite(fDefinite),
+                                                                       m_fModified(true)
+{
+    if(!m_fDefinite && !m_fConstructed)
+        throw runtime_error("BERPrimitiveIndefiniteLength");
+}
+
+BEROctet::~BEROctet(void)
+{
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+        delete m_SubOctetList[i];
+}
+
+BEROctet& BEROctet::operator=(BEROctet const &Oct)
+{
+
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+        delete m_SubOctetList[i];
+
+    m_SubOctetList.resize(0);
+    m_blbData.resize(0);
+
+    m_fModified    = Oct.m_fModified;
+    m_blbOrigOctet = Oct.m_blbOrigOctet;
+
+    m_fConstructed = Oct.m_fConstructed;
+    m_tcClass      = Oct.m_tcClass;
+    m_dwTag        = Oct.m_dwTag;
+    m_fDefinite    = Oct.m_fDefinite;
+
+
+    if(m_fConstructed)
+    {
+        for(std::vector<BEROctet const*>::size_type i=0; i<Oct.m_SubOctetList.size(); i++)
+            m_SubOctetList.push_back(new BEROctet(*Oct.m_SubOctetList[i]));
+    }
+    else
+        m_blbData = Oct.m_blbData;
+
+    return *this;
+}
+
+// Returns a the data part of the octet
+
+BEROctet::Blob BEROctet::Data() const
+{
+
+    if(m_fConstructed)
+    {
+
+        // Traverse the tree
+
+        Blob data;
+
+        for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+            data += m_SubOctetList[i]->Octet();
+
+        return data;
+    }
+    else
+        return m_blbData;
+
+}
+
+// Sets the data part of the octet
+
+void BEROctet::Data(Blob const &blb)
+{
+
+    if(m_fConstructed)
+        throw runtime_error("BERInconsistentOperation");
+
+    m_blbData = blb;
+    m_fModified = true;
+
+}
+
+// If the octet is a constructed type, this returns list of sub-octets
+
+vector<BEROctet*> BEROctet::SubOctetList() const
+{
+    if(!m_fConstructed)
+        throw runtime_error("BERInconsistentOperation");
+
+    return m_SubOctetList;
+}
+
+// Insert an octet as a sub-octet of a constructed octet
+
+void BEROctet::Insert(BEROctet const &oct)
+{
+    if(!m_fConstructed)
+        throw runtime_error("BERInconsistentOperation");
+
+    BEROctet *pOct = new BEROctet(oct);
+    m_SubOctetList.push_back(pOct);
+    m_fModified = true;
+
+}
+
+// Returns the whole octet
+
+BEROctet::Blob BEROctet::Octet() const
+{
+    if(Modified())
+    {
+
+        Blob blbOct = IdentOctets(m_tcClass, m_fConstructed, m_dwTag);
+        Blob blbData = Data();
+
+        if(m_fDefinite)
+            blbOct += LengthOctets(static_cast<unsigned int>(blbData.size()));
+        else
+            blbOct += 0x80;    // Indefinite length octet
+
+        blbOct += blbData;
+
+        if(!m_fDefinite)
+        {
+
+            // Terminate with end-of-contents octet
+
+            BEROctet blbZero;
+            blbOct += blbZero.Octet();
+        }
+
+        return blbOct;
+    }
+    else
+        return m_blbOrigOctet;
+
+}
+
+// Returns the class of the octet
+
+TagClass BEROctet::Class() const
+{
+    return m_tcClass;
+}
+
+// Returns true if the octet is constructet, false otherwise
+
+bool BEROctet::Constructed() const
+{
+    return m_fConstructed;
+}
+
+// Returns the tag of the octet
+
+unsigned int BEROctet::Tag() const
+{
+    return m_dwTag;
+}
+
+// Decode the contents of an OID
+
+string BEROctet::ObjectID() const
+{
+
+    if(m_tcClass!=tcUniversal || m_dwTag!=dwBerUnivObjectIdent)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(!m_blbData.size())
+        throw runtime_error("BEREmptyOctet");
+
+    string OID;
+
+    // The scratch buffer "text" below needs to be large enough to hold
+    // the decimal encoding of two 32 bit integers, including a space
+    // and the terminating zero.
+
+    char text[40];
+
+    unsigned int subid;
+    const unsigned char *c = m_blbData.data();
+    const unsigned char *Last = c + m_blbData.size();
+    bool First = true;
+
+    while(c<Last)
+    {
+        subid = (*c)&0x7F;
+        while((*c)&0x80)
+        {
+            c++;
+            if(c>=Last)
+                throw runtime_error("BERUnexpectedEndOfOctet");
+            if(subid>0x01FFFFFF)
+                throw runtime_error("BEROIDSubIdentifierOverflow");
+            subid = (subid<<7) | ((*c)&0x7F);
+        }
+        if(First)
+        {
+            unsigned int X,Y;
+            if(subid<40)
+                X=0;
+            else if(subid<80)
+                X=1;
+            else
+                X=2;
+            Y = subid-X*40;
+            sprintf(text,"%d %d",X,Y);
+            OID = text;
+            First = false;
+        }
+        else
+        {
+            sprintf(text," %d",subid);
+            OID += text;
+        }
+        c++;
+    }
+
+    return OID;
+}
+
+// Encode an OID
+
+void BEROctet::ObjectID(string const &str)
+{
+
+    if(m_tcClass!=tcUniversal)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(m_dwTag==dwBerUnivZero)
+        m_dwTag = dwBerUnivObjectIdent;
+
+    if(m_dwTag!=dwBerUnivObjectIdent)
+        throw runtime_error("BERInconsistentOperation");
+
+    char *oid = 0;
+
+    try
+    {
+#if defined(_WIN32)
+        oid = _strdup(str.c_str());
+#else
+        oid = strdup(str.c_str());
+#endif
+        char *s;
+
+        if(0==(s = strtok(oid," ")))
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        unsigned int X,Y,dwSubOID;
+
+        if(sscanf(s,"%u",&X)!=1)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(X>2)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(0==(s = strtok(0," ")))
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(sscanf(s,"%u",&Y)!=1)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        if(X<2 && Y>39)
+            throw runtime_error("BERIllegalObjectIdentifier");
+
+        dwSubOID = X*40;
+        if(Y>0xFFFFFFFF-dwSubOID)
+            throw runtime_error("BERDataOverflow");
+
+        dwSubOID += Y;
+
+        Blob blbData;
+
+        while(true)
+        {
+
+            unsigned char buf[2*sizeof(dwSubOID)];
+            int n=0;
+            while(dwSubOID>0x7F)
+            {
+                buf[n] = static_cast<unsigned char>(dwSubOID & 0x7F);
+                dwSubOID >>=7;
+                n++;
+            }
+            buf[n] = static_cast<unsigned char>(dwSubOID & 0x7F);
+            n++;
+
+            for(int i=0; i<n; i++)
+            {
+                unsigned char b = buf[n-i-1];
+                if((i+1)<n) b |= 0x80;
+                blbData += b;
+            }
+
+            if(0==(s = strtok(0," ")))
+                break;
+            if(sscanf(s,"%u",&dwSubOID)!=1)
+                break;
+        }
+
+        Data(blbData);
+
+    }
+    catch(...)
+    {
+        if(oid)
+            free(oid);
+        throw;
+    }
+
+    if(oid)
+        free(oid);
+
+}
+
+// Decode a Time octet. Output format: "YYYYMMDDHHMMSS"
+
+// We here apply the convention from RFC 2459 that the 2 digit year
+// encoded in UTCTime is in the range 1950-2049.
+
+string BEROctet::Time() const
+{
+
+    static const Blob::size_type UnivUTCTimeSize = 13;
+    static const Blob::size_type UnivGenTimeSize = 15;
+
+    if(m_tcClass!=tcUniversal)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(m_dwTag==dwBerUnivUTCTime)
+    {
+        // UTCTime
+
+        if(m_blbData.size()!=UnivUTCTimeSize)
+            throw runtime_error("BERInconsistentDataLength");
+
+        string strCentury, strYear((char*)m_blbData.data(),2);
+        int iYear;
+        if(sscanf(strYear.c_str(),"%d",&iYear)!=1)
+            throw runtime_error("FormatDecodingError");
+
+        if(iYear>=50) strCentury = "19";
+        else strCentury = "20";
+
+        // Add century and strip off the 'Z'
+
+        return strCentury + string((char*)m_blbData.data(),UnivUTCTimeSize-1);
+    }
+    else if(m_dwTag==dwBerUnivGenTime)
+    {
+        // GeneralizedTime
+
+        if(m_blbData.size()!=UnivGenTimeSize)
+            throw runtime_error("BERInconsistentDataLength");
+
+        // Return the string as is, stripping off the 'Z'
+
+        return string((char*)m_blbData.data(),UnivGenTimeSize-1);
+    }
+    else
+        throw runtime_error("BERInconsistentOperation");
+
+}
+
+// Encode a Time. Input format: "YYYYMMDDHHMMSS"
+
+// If the Tag is not set to be either UTC Time or Generalized Time,
+// we apply the convention from RFC 2459 where years in the range
+// 1950-2049 are encoded as UTC Time and years later are encoded as
+// Generalized time. In this case, years < 1950 are not allowed.
+
+void BEROctet::Time(string const &str)
+{
+    static const Blob::size_type ExpectedSize = 14;
+
+    if(m_tcClass!=tcUniversal)
+        throw runtime_error("BERInconsistentOperation");
+
+    if(str.size()!=ExpectedSize)
+        throw runtime_error("IllegalParameter");
+
+    // If m_dwTag is zero, chose appropriate tag according to year
+
+    int iYear;
+    if(sscanf(str.substr(0,4).c_str(),"%d",&iYear)!=1)
+        throw runtime_error("IllegalParameter");
+
+    if(m_dwTag==dwBerUnivZero)
+    {
+        if(iYear<1950)
+            throw runtime_error("IllegalParameter");
+        else if(iYear<2050)
+            m_dwTag = dwBerUnivUTCTime;
+        else
+            m_dwTag = dwBerUnivGenTime;
+    }
+
+    Blob blbData;
+
+    if(m_dwTag==dwBerUnivUTCTime)
+        blbData.assign(((unsigned char*)str.data()+2),str.size()-2);
+
+    else if(m_dwTag==dwBerUnivGenTime)
+        blbData.assign((unsigned char*)str.data(),str.size());
+
+    else
+        throw runtime_error("BERInconsistentOperation");
+
+    blbData += 'Z';
+
+    Data(blbData);
+
+}
+
+// SearchOID returns all the constructed octets that contain a particular OID
+
+void BEROctet::SearchOID(string const &OID, vector<BEROctet const*> &result) const
+{
+
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+    {
+
+        if(m_SubOctetList[i]->Class()==tcUniversal &&
+           m_SubOctetList[i]->Tag()==dwBerUnivObjectIdent)
+        {
+            if(OID==m_SubOctetList[i]->ObjectID())
+                result.push_back(this);
+        }
+        else if(m_SubOctetList[i]->Constructed())
+            m_SubOctetList[i]->SearchOID(OID,result);
+    }
+
+    return;
+
+}
+
+// SearchOIDNext returns all the octets following a particular OID
+
+void BEROctet::SearchOIDNext(string const &OID, vector<BEROctet const*> &result) const
+{
+    for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+    {
+        if(m_SubOctetList[i]->Class()==tcUniversal &&
+           m_SubOctetList[i]->Tag()==dwBerUnivObjectIdent)
+        {
+            if(OID==m_SubOctetList[i]->ObjectID())
+            {
+                if((i+1) < m_SubOctetList.size())
+                    result.push_back(m_SubOctetList[i+1]);
+            }
+        }
+        else if(m_SubOctetList[i]->Constructed())
+            m_SubOctetList[i]->SearchOIDNext(OID,result);
+    }
+
+    return;
+
+}
+
+// Construct the Identifier octets
+
+BEROctet::Blob BEROctet::IdentOctets(TagClass tcClass, bool fConstructed, unsigned int dwTag)
+{
+
+    unsigned char bLeadingOct;
+    switch(tcClass)
+    {
+
+    case tcUniversal:
+        bLeadingOct = 0x00;
+        break;
+
+    case tcApplication:
+        bLeadingOct = 0x40;
+        break;
+
+    case tcContext:
+        bLeadingOct = 0x80;
+        break;
+
+    case tcPrivate:
+        bLeadingOct = 0xC0;
+        break;
+
+    default:
+        throw runtime_error("BERIllegalClass");
+    }
+
+    if(fConstructed)
+        bLeadingOct |= 0x20;
+
+    int n = 0;
+    unsigned char buf[sizeof(dwTag)];
+
+    if(dwTag<=30)
+        bLeadingOct |= dwTag;
+
+    else
+    {
+        bLeadingOct |= 0x1F;
+        while(dwTag>0)
+        {
+            buf[n] = static_cast<unsigned char>(dwTag & 0x000000FF);
+            dwTag >>= 8;
+            n++;
+        }
+    }
+
+    Blob IdentOcts(&bLeadingOct,1);
+
+    for(int i=0; i<n; i++)
+        IdentOcts +=buf[n-i-1];
+
+    return IdentOcts;
+
+}
+
+// Construct the Length octets
+
+BEROctet::Blob BEROctet::LengthOctets(unsigned int dwLength)
+{
+
+    int n = 0;
+    unsigned char buf[sizeof(dwLength)];
+    unsigned char bLeadingOct;
+
+    if(dwLength<=0x7F)
+        bLeadingOct = static_cast<unsigned char>(dwLength);
+    else
+    {
+        bLeadingOct = 0x80;
+        while(dwLength>0)
+        {
+            buf[n] = static_cast<unsigned char>(dwLength & 0x000000FF);
+            dwLength >>= 8;
+            n++;
+        }
+        bLeadingOct |= n;
+    }
+
+    Blob LengthOcts(&bLeadingOct,1);
+    for(int i=0; i<n; i++)
+        LengthOcts +=buf[n-i-1];
+
+    return LengthOcts;
+
+}
+
+// Decodes recursively a BER octet.
+
+void BEROctet::Decode(Blob const &blb)
+{
+
+    if(!blb.size())
+        throw runtime_error("BEREmptyOctet");
+
+    size_t BufferSize = blb.size();
+
+    m_fConstructed = (blb[0]&0x20) ? true : false;
+
+    switch(blb[0]&0xC0)
+    {
+
+    case 0x00:
+        m_tcClass = tcUniversal;
+        break;
+
+    case 0x40:
+        m_tcClass = tcApplication;
+        break;
+
+    case 0x80:
+        m_tcClass = tcContext;
+        break;
+
+    case 0xC0:
+        m_tcClass = tcPrivate;
+        break;
+
+    default:
+        throw runtime_error("BERIllegalClass");
+    }
+
+    const unsigned char *c = blb.data();
+    const unsigned char *Last = c + blb.size() - 1;
+    m_dwTag = *c & 0x1F;
+
+    if(m_dwTag>30)
+    {
+        m_dwTag = 0;
+
+        c++;
+        if(c>Last)
+            throw runtime_error("BERUnexpectedEndOfOctet");
+
+        while (*c & 0x80)
+        {
+            m_dwTag = (m_dwTag << 7) | ((*c) & 0x7F);
+            c++;
+            if(c>Last)
+                throw runtime_error("BERUnexpectedEndOfOctet");
+        }
+
+        if(m_dwTag > 0x01FFFFFF)
+            throw runtime_error("BERTagValueOverflow");
+
+        m_dwTag = (m_dwTag << 7) | ((*c) & 0x7F);
+
+    }
+
+    c++;
+    if(c>Last)
+        throw runtime_error("BERUnexpectedEndOfOctet");
+
+    size_t DataSize;
+
+    if((*c)&0x80)
+    {
+        int n = (*c) & 0x7F;
+        if(n)
+        {
+            DataSize = 0;
+            for(int i=0; i<n; i++)
+            {
+                c++; if(c>Last)
+                    throw runtime_error("BERUnexpectedEndOfOctet");
+                if(DataSize>0x007FFFFF)
+                    throw runtime_error("BERDataOverflow");
+                DataSize = (DataSize<<8) | (*c);
+            }
+        }
+        else
+            throw runtime_error("BERUnexpectedIndefiniteLength");
+    }
+    else DataSize = *c;
+
+    c++;
+
+    const unsigned char *bpData = c;
+
+    size_t OctetSize = DataSize + (bpData-blb.data());
+
+    m_blbOrigOctet = blb.substr(0,OctetSize);
+    m_fModified = false;
+
+    if(OctetSize>static_cast<unsigned int>(BufferSize))
+        throw runtime_error("BERInconsistentDataLength");
+
+    for(std::vector<BEROctet const*>::size_type  i=0; i<m_SubOctetList.size(); i++)
+        delete m_SubOctetList[i];
+
+    m_SubOctetList.resize(0);
+    m_blbData = Blob();
+
+    if(m_fConstructed)
+    {
+
+        // Constructed type
+
+        while(DataSize)
+        {
+
+            BEROctet *suboct = new BEROctet(Blob(bpData,DataSize));
+
+            m_SubOctetList.push_back(suboct);
+
+            Blob blbSubOct = suboct->Octet();
+
+            bpData += blbSubOct.size();
+            DataSize -= blbSubOct.size();
+        }
+    }
+    else
+        m_blbData = Blob(bpData,DataSize);
+
+}
+
+bool BEROctet::Modified() const
+{
+    if(m_fModified)
+        return true;
+
+    if(m_fConstructed)
+        for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+            if(m_SubOctetList[i]->Modified()) return true;
+
+    return false;
+
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,221 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_beroctet_h
+#define _include_beroctet_h
+
+#include <string>
+#include <vector>
+#include <stdexcept>
+
+enum TagClass {tcAny = -1, tcUniversal = 0, tcApplication = 1, tcContext = 2, tcPrivate = 3};
+
+// Defined tags
+
+const unsigned int dwBerUnivZero          = 0;
+const unsigned int dwBerUnivBool          = 1;
+const unsigned int dwBerUnivInteger       = 2;
+const unsigned int dwBerUnivBitString     = 3;
+const unsigned int dwBerUnivOctetString   = 4;
+const unsigned int dwBerUnivNull          = 5;
+const unsigned int dwBerUnivObjectIdent   = 6;
+const unsigned int dwBerUnivObjectDesc    = 7;
+const unsigned int dwBerUnivReal          = 9;
+const unsigned int dwBerUnivEnum          = 10;
+const unsigned int dwBerUnivUTF8String    = 12;
+const unsigned int dwBerUnivSequence      = 16;
+const unsigned int dwBerUnivSet           = 17;
+const unsigned int dwBerUnivPrintString   = 19;
+const unsigned int dwBerUnivIA5String     = 22;
+const unsigned int dwBerUnivUTCTime       = 23;
+const unsigned int dwBerUnivGenTime       = 24;
+const unsigned int dwBerGraphicString     = 25;
+const unsigned int dwBerISO646String      = 26;
+const unsigned int dwBerGeneralString     = 27;
+const unsigned int dwBerUniversalString   = 28;
+const unsigned int dwBerCharacterString   = 29;
+const unsigned int dwBerBMPString         = 30;
+const unsigned int dwBerDate              = 31;
+const unsigned int dwBerTimeOfDay         = 32;
+const unsigned int dwBerDateTime          = 33;
+const unsigned int dwBerDuration          = 34;
+
+const char OID_pkcs1[]                            = "1 2 840 113549 1 1";
+const char OID_pkcs1_rsaEncryption[]              = "1 2 840 113549 1 1 1";
+const char OID_pkcs1_md2WithRSAEncryption[]       = "1 2 840 113549 1 1 2";
+const char OID_pkcs1_md4WithRSAEncryption[]       = "1 2 840 113549 1 1 3";
+const char OID_pkcs1_md5WithRSAEncryption[]       = "1 2 840 113549 1 1 4";
+const char OID_pkcs1_sha1WithRSAEncryption[]      = "1 2 840 113549 1 1 5";
+const char OID_pkcs1_sha256WithRSAEncryption[]    = "1 2 840 113549 1 1 11";
+
+const char OID_pkcs7_data[]                       = "1 2 840 113549 1 7 1";
+const char OID_pkcs7_signedData[]                 = "1 2 840 113549 1 7 2";
+const char OID_pkcs7_envelopedData[]              = "1 2 840 113549 1 7 3";
+const char OID_pkcs7_signedAndEnvelopedData[]     = "1 2 840 113549 1 7 4";
+const char OID_pkcs7_digestedData[]               = "1 2 840 113549 1 7 5";
+const char OID_pkcs7_encryptedData[]              = "1 2 840 113549 1 7 6";
+
+const char OID_pkcs9_emailAddress[]               = "1 2 840 113549 1 9 1";
+const char OID_pkcs9_unstructuredName[]           = "1 2 840 113549 1 9 2";
+const char OID_pkcs9_contentType[]                = "1 2 840 113549 1 9 3";
+const char OID_pkcs9_messageDigest[]              = "1 2 840 113549 1 9 4";
+const char OID_pkcs9_signingTime[]                = "1 2 840 113549 1 9 5";
+const char OID_pkcs9_countersignature[]           = "1 2 840 113549 1 9 6";
+const char OID_pkcs9_challengePassword[]          = "1 2 840 113549 1 9 7";
+const char OID_pkcs9_unstructuredAddress[]        = "1 2 840 113549 1 9 8";
+const char OID_pkcs9_extendedCertificateAttr[]    = "1 2 840 113549 1 9 9";
+const char OID_pkcs9_sMIMECapabilities[]          = "1 2 840 113549 1 9 15";
+const char OID_pkcs9_id_smime[]                   = "1 2 840 113549 1 9 16";
+
+const char OID_digestAlogrithm_md2[]              = "1 2 840 113549 2 2";
+const char OID_digestAlogrithm_md4[]              = "1 2 840 113549 2 4";
+const char OID_digestAlogrithm_md5[]              = "1 2 840 113549 2 5";
+
+const char OID_RC2_CBC[]                          = "1 2 840 113549 3 2";
+const char OID_dES_EDE3_CBC[]                     = "1 2 840 113549 3 7";
+
+const char OID_ms_enrollmentAgent[]               = "1 3 6 1 4 1 311 20 2 1";
+const char OID_ms_smartCardLogin[]                = "1 3 6 1 4 1 311 20 2 2";
+
+const char OID_id_kp_serverAuth[]                 = "1 3 6 1 5 5 7 3 1";
+const char OID_id_kp_clientAuth[]                 = "1 3 6 1 5 5 7 3 2";
+const char OID_id_kp_codeSigning[]                = "1 3 6 1 5 5 7 3 3";
+const char OID_id_kp_emailProtection[]            = "1 3 6 1 5 5 7 3 4";
+const char OID_id_kp_ipsecEndSystem[]             = "1 3 6 1 5 5 7 3 5";
+const char OID_id_kp_ipsecTunnel[]                = "1 3 6 1 5 5 7 3 6";
+const char OID_id_kp_ipsecUser[]                  = "1 3 6 1 5 5 7 3 7";
+const char OID_id_kp_timeStamping[]               = "1 3 6 1 5 5 7 3 8";
+
+const char OID_md4WithRSA[]                       = "1 3 14 3 2 2";
+const char OID_md5WithRSA[]                       = "1 3 14 3 2 3";
+const char OID_md4WithRSAEncryption[]             = "1 3 14 3 2 4";
+const char OID_desECB[]                           = "1 3 14 3 2 6";
+const char OID_desCBC[]                           = "1 3 14 3 2 7";
+const char OID_desOFB[]                           = "1 3 14 3 2 8";
+const char OID_desCFB[]                           = "1 3 14 3 2 9";
+const char OID_desMAC[]                           = "1 3 14 3 2 10";
+const char OID_rsaSignature[]                     = "1 3 14 3 2 11";
+const char OID_mdc2WithRSASignature[]             = "1 3 14 3 2 14";
+const char OID_shaWithRSASignature[]              = "1 3 14 3 2 15";
+const char OID_desEDE[]                           = "1 3 14 3 2 17";
+const char OID_sha[]                              = "1 3 14 3 2 18";
+const char OID_rsaKeyTransport[]                  = "1 3 14 3 2 22";
+const char OID_md2WithRSASignature[]              = "1 3 14 3 2 24";
+const char OID_md5WithRSASignature[]              = "1 3 14 3 2 25";
+const char OID_sha1[]                             = "1 3 14 3 2 26";
+const char OID_sha1WithRSASignature[]             = "1 3 14 3 2 29";
+
+const char OID_id_at_organizationName[]           = "2 5 4 10";
+const char OID_id_at_organizationalUnitName[]     = "2 5 4 11";
+const char OID_id_at_commonName[]                 = "2 5 4 3";
+const char OID_id_at_countryName[]                = "2 5 4 6";
+const char OID_id_at_localityName[]               = "2 5 4 7";
+const char OID_id_at_stateOrProvinceName[]        = "2 5 4 8";
+const char OID_id_ce_subjectDirectoryAttributes[] = "2 5 29 9";
+const char OID_id_ce_subjectKeyIdentifier[]       = "2 5 29 14";
+const char OID_id_ce_keyUsage[]                   = "2 5 29 15";
+const char OID_id_ce_privateKeyUsagePeriod[]      = "2 5 29 16";
+const char OID_id_ce_subjectAltName[]             = "2 5 29 17";
+const char OID_id_ce_issuerAltName[]              = "2 5 29 18";
+const char OID_id_ce_basicConstraints[]           = "2 5 29 19";
+const char OID_id_ce_cRLNumber[]                  = "2 5 29 20";
+const char OID_id_ce_reasonCode[]                 = "2 5 29 21";
+const char OID_id_ce_instructionCode[]            = "2 5 29 23";
+const char OID_id_ce_invalidityDate[]             = "2 5 29 24";
+const char OID_id_ce_deltaCRLIndicator[]          = "2 5 29 27";
+const char OID_id_ce_issuingDistributionPoint[]   = "2 5 29 28";
+const char OID_id_ce_certificateIssuer[]          = "2 5 29 29";
+const char OID_id_ce_nameConstraints[]            = "2 5 29 30";
+const char OID_id_ce_cRLDistributionPoints[]      = "2 5 29 31";
+const char OID_id_ce_certificatePolicies[]        = "2 5 29 32";
+const char OID_id_ce_policyMappings[]             = "2 5 29 33";
+const char OID_id_ce_policyConstraints[]          = "2 5 29 36";
+const char OID_id_ce_authorityKeyIdentifier[]     = "2 5 29 35";
+const char OID_id_ce_extKeyUsage[]                = "2 5 29 37";
+
+const char OID_sha256[]                           = "2 16 840 1 101 3 4 2 1";
+const char OID_Netscape_certificate_type[]        = "2 16 840 1 113730 1 1";
+//
+////
+
+const bool fBerPcPrimitive = false;
+const bool fBerPcConstructed = true;
+
+class BEROctet
+{
+
+public:
+    typedef std::basic_string<unsigned char> Blob;
+
+    BEROctet();
+    BEROctet(BEROctet const &oct);
+    BEROctet(Blob const &blb);
+    BEROctet(TagClass tcClass, bool fConstructed, unsigned int dwTag, bool fDefinite=true);
+    ~BEROctet();
+
+    BEROctet& operator=(BEROctet const &oct);
+
+    Blob Data() const;
+    void Data(Blob const &data);
+    std::vector<BEROctet*> SubOctetList() const;
+    void Insert(BEROctet const &oct);
+
+    Blob Octet() const;
+
+    TagClass Class() const;
+    bool Constructed() const;
+    unsigned int Tag() const;
+
+    std::string ObjectID() const;
+    void ObjectID(std::string const &str);
+
+    std::string Time() const;
+    void Time(std::string const &str);
+
+    void SearchOID(std::string const &OID, std::vector<BEROctet const*> &result) const;
+    void SearchOIDNext(std::string const &OID, std::vector<BEROctet const*> &result) const;
+
+private:
+    static Blob IdentOctets(TagClass tcClass, bool fConstructed, unsigned int dwTag);
+    static Blob LengthOctets(unsigned int dwLength);
+
+    void Decode(Blob const &blb);
+    bool Modified() const;               // =true if octet or sub-octets are modified since decoding
+
+    Blob m_blbOrigOctet;            // Original octet that was decoded
+
+    TagClass m_tcClass;                  // Tag class
+    bool m_fConstructed;                 // =true if a constructed octed, false if primitive
+    unsigned int m_dwTag;                       // Tag
+    bool m_fDefinite;                    // =true for definite form of length octet, false if indefinite
+    bool m_fModified;                    // =true if octet is modified since decoded, false otherwise
+
+    Blob m_blbData;                 // Data octets (When primitive)
+    std::vector<BEROctet*> m_SubOctetList;  // List of sub-octets (when constructed)
+
+};
+
+
+#endif // _include_beroctet_h
+
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,304 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <memory>
+#include "stdafx.h"
+#include "cardcache.h"
+#include "error.h"
+#include "log.h"
+
+
+#define KEYSPEC_KEYEXCHANGE  0x01
+#define KEYSPEC_SIGNATURE    0x02
+#define MAX_RETRY 2
+#define LOW_MEMORY_LIMIT 5000
+
+
+/* Constructor
+*/
+CardCache::CardCache( CardModuleService * mscm ) : _mscm( mscm )
+{
+   if( !mscm )
+   {
+      throw CkError( CKR_FUNCTION_FAILED );
+   }
+}
+
+/*
+*/
+void CardCache::ManageGC( void )
+{
+   try
+   {
+      s4 freeMemory = _mscm->GetMemory( );
+
+      if ( freeMemory < LOW_MEMORY_LIMIT )
+      {
+          Log::error( "CardCache::ManageGC", "ForceGarbageCollector" );
+         _mscm->ForceGarbageCollector( );
+      }
+   }
+   catch( ... )
+   {
+   }
+}
+
+
+/* WriteFile
+Write the incoming data into the incoming pointed path into the smartcard
+and then into the cache
+*/
+void CardCache::WriteFile( std::string const & path, u1Array const & data )
+{
+   int ntry = 0;
+   while( ntry < MAX_RETRY )
+   {
+      try
+      {
+         ManageGC( );
+         ntry++;
+         _mscm->WriteFile( const_cast< std::string* >( &path ), const_cast< u1Array* >( &data ) );
+         _fileCache[ path ] = data;
+         break;
+      }
+      catch( Marshaller::Exception & x )
+      {
+         CK_RV rv = CkError::CheckMarshallerException( x );
+         if( CKR_DEVICE_MEMORY == rv )
+         {
+            Log::error( "CardCache::WriteFile", "ForceGarbageCollector" );
+           _mscm->ForceGarbageCollector( );
+            if( ntry >= MAX_RETRY )
+            {
+               _fileCache.erase( path );
+               throw CkError( rv );
+            }
+         }
+         else
+         {
+            _fileCache.erase( path );
+            throw CkError( rv );
+         }
+      }
+      catch( ... )
+      {
+         _fileCache.erase( path );
+         throw CkError( CKR_FUNCTION_FAILED );
+      }
+   }
+}
+
+
+/* ReadFile
+*/
+const u1Array & CardCache::ReadFile( std::string const & path )
+{
+   // V2+ cards may throw OutOfMemoryException from ReadFile, however
+   // it may recover from this by forcing the garbage collection to
+   // occur. In fact as a result of a ReadFile command that throws
+   // OutOfMemoryException, GC has already occured, so the command may
+   // be re-tried with high chance of success.
+
+   map<string, u1Array>::const_iterator ifile = _fileCache.find( path );
+   if( ifile == _fileCache.end( ) )
+   {
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ManageGC( );
+            ntry++;
+            auto_ptr< u1Array > data( _mscm->ReadFile( const_cast< std::string* >( &path ), 0 ) );
+            _fileCache[ path ] = *data;
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "CardCache::ReadFile", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+         catch( ... )
+         {
+            throw CkError( CKR_FUNCTION_FAILED );
+         }
+      }
+   }
+
+   return _fileCache[ path ];
+}
+
+
+/* ClearFile
+Erase a file from the cache
+*/
+void CardCache::ClearFile( std::string const &path )
+{
+   _fileCache.erase( path );
+}
+
+
+/* ReadContainer
+Read the contained pointed by the incoming index from the smartcard
+and compute an instance into the cache
+*/
+const CardCache::Container& CardCache::ReadContainer( int const &ctrIndex ) const
+{
+   map< int, Container >::const_iterator icont = _contCache.find( ctrIndex );
+   if( icont == _contCache.end( ) )
+   {
+      try
+      {
+         Container cont;
+         auto_ptr< u1Array > cInfo( _mscm->GetCAPIContainer( ctrIndex ) );
+         u4 offset = 2;
+         for( int ikeySpec = 0; ikeySpec < 2 ; ++ikeySpec )
+         {
+            if( offset < cInfo->GetLength( ) )
+            {
+               u1 keySpec = cInfo->ReadU1At( offset );
+               offset += 2;
+               u1 expontLen = cInfo->ReadU1At( offset );
+               offset++;
+               u1Array publicExponent( expontLen );
+               memcpy( publicExponent.GetBuffer( ), cInfo->GetBuffer( ) + offset, expontLen );
+               offset += ( expontLen + 1 );
+               u4 modulusLen = cInfo->ReadU1At( offset ) << 4; // Modulus Len
+               offset++;
+               u1Array modulus( modulusLen );
+               memcpy( modulus.GetBuffer( ), cInfo->GetBuffer( ) + offset, modulusLen );
+
+               if( keySpec == KEYSPEC_KEYEXCHANGE )
+               {
+                  cont.exchModulus = modulus;
+                  cont.exchPublicExponent = publicExponent;
+               }
+               else if( keySpec == KEYSPEC_SIGNATURE )
+               {
+                  cont.signModulus = modulus;
+                  cont.signPublicExponent = publicExponent;
+               }
+               offset += modulusLen;
+               offset += 2;
+            }
+         }
+         _contCache[ ctrIndex ] = cont;
+      }
+      catch( ... )
+      {
+         _contCache[ ctrIndex ] = Container( ); // Empty
+      }
+   }
+   return _contCache[ ctrIndex ];
+}
+
+
+/* ClearContainer
+Erase the container pointed by the incoming index from the cache
+*/
+void CardCache::ClearContainer( int const &ctrIndex )
+{
+   _contCache.erase( ctrIndex );
+}
+
+
+/* FileList
+Retreive the list of the files contained into the incoming directory path
+and returns a string vectors
+*/
+const vector< std::string > & CardCache::FileList( std::string const &dir )
+{
+   map< std::string, vector< std::string > >::const_iterator idir = _fileList.find( dir );
+   if( idir == _fileList.end( ) )
+   {
+      vector< std::string > vfile;
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ManageGC( );
+            ntry++;
+            auto_ptr<StringArray> files( _mscm->GetFiles( const_cast<string*>( &dir ) ) );
+            for( u4 i = 0; i < files->GetLength( ) ; i++ )
+            {
+               vfile.push_back( *files->GetStringAt( i ) );
+            }
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "CardCache::FileList", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+         catch( ... )
+         {
+            throw CkError( CKR_FUNCTION_FAILED );
+         }
+      }
+      _fileList[ dir ] = vfile;
+   }
+
+   return _fileList[ dir ];
+}
+
+
+/* ClearFileList
+Erase the dir from the cache
+*/
+void CardCache::ClearFileList( std::string const & dir )
+{
+   _fileList.erase( dir );
+}
+
+
+/* ClearAll
+Erase all cache
+*/
+void CardCache::ClearAll( )
+{
+   _fileCache.clear( );
+   _contCache.clear( );
+   _fileList.clear( );
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,65 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_cardcache_h
+#define _include_cardcache_h
+
+
+#include "cardmoduleservice.h"
+
+
+#include <map>
+#include <string>
+#include <vector>
+
+class CardCache
+{
+public:
+   struct Container
+   {
+      u1Array exchPublicExponent;
+      u1Array exchModulus;
+      u1Array signPublicExponent;
+      u1Array signModulus;
+   };
+
+   CardCache(CardModuleService *  mscm);
+   void WriteFile(std::string const & path, u1Array const & data);
+   const u1Array & ReadFile(std::string const & path);
+   void ClearFile(std::string const & path);
+
+   const Container & ReadContainer( int const &ctrIndex ) const;
+   void ClearContainer(int const &ctrIndex);
+
+   const std::vector<std::string> & FileList(std::string const & dir);
+   void ClearFileList(std::string const & dir);
+
+   void ClearAll();
+
+private:
+   void ManageGC( void );
+   CardModuleService * _mscm;
+   mutable std::map<std::string, u1Array> _fileCache;
+   mutable std::map<int, Container> _contCache;
+   mutable std::map<std::string, vector<string> > _fileList;
+
+};
+
+#endif // _include_cardcache_h

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,346 @@
+// Machine generated C++ stub file (.cpp) for remote object CardModuleService
+// Created on : 06/05/2008 12:22:51
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <winscard.h>
+#include "cardmoduleservice.h"
+
+using namespace std;
+using namespace Marshaller;
+
+
+// Constructors
+CardModuleService::CardModuleService(string* uri) : SmartCardMarshaller(NULL, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(string* uri, u4 index) : SmartCardMarshaller(NULL, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, index) { return; }
+CardModuleService::CardModuleService(u2 portNumber, string* uri) : SmartCardMarshaller(NULL, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(u2 portNumber, string* uri, u4 index) : SmartCardMarshaller(NULL, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, index) { return; }
+CardModuleService::CardModuleService(string* readerName, string* uri) : SmartCardMarshaller(readerName, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(string* readerName, u2 portNumber, string* uri) : SmartCardMarshaller(readerName, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(SCARDHANDLE cardHandle, string* uri) : SmartCardMarshaller(cardHandle, 0, uri, (u4)0xC04B4E, (u2)0x7FBD) { return; }
+CardModuleService::CardModuleService(SCARDHANDLE cardHandle, u2 portNumber, string* uri) : SmartCardMarshaller(cardHandle, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD) { return; }
+
+// Extra method (Microsoft CardModule only)
+void CardModuleService::UpdateCardHandle(SCARDHANDLE cardHandle)
+{
+    UpdatePCSCCardHandle(cardHandle);
+}
+
+// Pre-defined methods
+std::string* CardModuleService::GetReader(void){return GetReaderName();}
+SCARDHANDLE CardModuleService::GetPcscCardHandle(void){return GetCardHandle();}
+void CardModuleService::DoSCardTransact(bool flag){DoTransact(flag);}
+
+// Exposed methods
+
+void CardModuleService::ChangeReferenceData(u1 mode,u1 role,u1Array* oldPin,u1Array* newPin,s4 maxTries){
+	Invoke(5, 0xE08A, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, oldPin, MARSHALLER_TYPE_IN_U1ARRAY, newPin, MARSHALLER_TYPE_IN_S4, maxTries, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+s4 CardModuleService::GetTriesRemaining(u1 role){
+	s4 _s4 = 0;
+	Invoke(1, 0x6D08, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_S4, &_s4);
+	return _s4;
+}
+
+
+void CardModuleService::CreateCAPIContainer(u1 ctrIndex,u1 keyImport,u1 keySpec,s4 keySize,u1Array* keyValue){
+	Invoke(5, 0x0234, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_BOOL, keyImport, MARSHALLER_TYPE_IN_U1, keySpec, MARSHALLER_TYPE_IN_S4, keySize, MARSHALLER_TYPE_IN_U1ARRAY, keyValue, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeleteCAPIContainer(u1 ctrIndex){
+	Invoke(1, 0xF152, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetCAPIContainer(u1 ctrIndex){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0x9B2E, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1Array* CardModuleService::PrivateKeyDecrypt(u1 ctrIndex,u1 keyType,u1Array* encryptedData){
+	u1Array* _u1Array = NULL;
+	Invoke(3, 0x6144, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, keyType, MARSHALLER_TYPE_IN_U1ARRAY, encryptedData, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::CreateFile(string* path,u1Array* acls,s4 initialSize){
+	Invoke(3, 0xBEF1, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, acls, MARSHALLER_TYPE_IN_S4, initialSize, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::CreateDirectory(string* path,u1Array* acls){
+	Invoke(2, 0xACE9, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, acls, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::WriteFile(string* path,u1Array* data){
+	Invoke(2, 0xF20E, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::ReadFile(string* path,s4 maxBytesToRead){
+	u1Array* _u1Array = NULL;
+	Invoke(2, 0x744C, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_S4, maxBytesToRead, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::DeleteFile(string* path){
+	Invoke(1, 0x6E2B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeleteDirectory(string* path){
+	Invoke(1, 0x9135, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+StringArray* CardModuleService::GetFiles(string* path){
+	StringArray* _StringArray = NULL;
+	Invoke(1, 0xE72B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_STRINGARRAY, &_StringArray);
+	return _StringArray;
+}
+
+
+u1Array* CardModuleService::GetFileProperties(string* path){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0xA01B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::ChangeAuthenticatorEx(u1 mode,u1 oldRole,u1Array* oldPin,u1 newRole,u1Array* newPin,s4 maxTries){
+	Invoke(6, 0x9967, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, oldRole, MARSHALLER_TYPE_IN_U1ARRAY, oldPin, MARSHALLER_TYPE_IN_U1, newRole, MARSHALLER_TYPE_IN_U1ARRAY, newPin, MARSHALLER_TYPE_IN_S4, maxTries, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetContainerProperty(u1 ctrIndex,u1 property,u1 flags){
+	u1Array* _u1Array = NULL;
+	Invoke(3, 0x279C, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::SetContainerProperty(u1 ctrIndex,u1 property,u1Array* data,u1 flags){
+	Invoke(4, 0x98D1, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::SetCardProperty(u1 property,u1Array* data,u1 flags){
+	Invoke(3, 0xB0E4, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+s4 CardModuleService::GetMemory(){
+	s4 _s4 = 0;
+	Invoke(0, 0x1DB4, MARSHALLER_TYPE_RET_S4, &_s4);
+	return _s4;
+}
+
+
+void CardModuleService::ForceGarbageCollector(){
+	Invoke(0, 0x3D38, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::RecursiveDelete(string* path){
+	Invoke(1, 0xEDD5, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::Select(MemoryStream* AID){
+	Invoke(1, 0x32E1, MARSHALLER_TYPE_IN_MEMORYSTREAM, AID, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::Verify(u1 P1,u1 P2,u1Array* pin){
+	Invoke(3, 0xD845, MARSHALLER_TYPE_IN_U1, P1, MARSHALLER_TYPE_IN_U1, P2, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+u1 CardModuleService::get_AdminPersonalized(){
+	u1 _u1 = 0;
+	Invoke(0, 0xCFBE, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+
+u1 CardModuleService::get_UserPersonalized(){
+	u1 _u1 = 0;
+	Invoke(0, 0xE710, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+
+u1Array* CardModuleService::GetChallenge(){
+	u1Array* _u1Array = NULL;
+	Invoke(0, 0xFA3B, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+s8 CardModuleService::get_AuthenticationDelay(){
+	s8 _s8 = 0;
+	Invoke(0, 0x5321, MARSHALLER_TYPE_RET_S8, &_s8);
+	return _s8;
+}
+
+void CardModuleService::ExternalAuthenticate(u1Array* response){
+	Invoke(1, 0x24FE, MARSHALLER_TYPE_IN_U1ARRAY, response, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::VerifyPin(u1 role,u1Array* pin){
+	Invoke(2, 0x506B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1 CardModuleService::IsAuthenticated(u1 role){
+	u1 _u1 = 0;
+	Invoke(1, 0x9B0B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+
+s4Array* CardModuleService::QueryFreeSpace(){
+	s4Array* _s4Array = NULL;
+	Invoke(0, 0x00E5, MARSHALLER_TYPE_RET_S4ARRAY, &_s4Array);
+	return _s4Array;
+}
+
+
+s4Array* CardModuleService::QueryKeySizes(){
+	s4Array* _s4Array = NULL;
+	Invoke(0, 0x5EE4, MARSHALLER_TYPE_RET_S4ARRAY, &_s4Array);
+	return _s4Array;
+}
+
+
+void CardModuleService::LogOut(u1 role){
+	Invoke(1, 0xC4E4, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+
+
+void CardModuleService::SerializeData(string* filename){
+	Invoke(1, 0x9AEA, MARSHALLER_TYPE_IN_STRING, filename, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeSerializeData(string* filename){
+	Invoke(1, 0xA373, MARSHALLER_TYPE_IN_STRING, filename, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::get_SerialNumber(){
+	u1Array* _u1Array = NULL;
+	Invoke(0, 0xD017, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+string* CardModuleService::get_Version(){
+	string* _string = NULL;
+	Invoke(0, 0xDEEC, MARSHALLER_TYPE_RET_STRING, &_string);
+	return _string;
+}
+
+
+void CardModuleService::SetHostVersion(u4 hostVersion){
+	Invoke(1, 0xD9B1, MARSHALLER_TYPE_IN_U4, hostVersion, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetChallengeEx(u1 role){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0x8F0B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1Array* CardModuleService::AuthenticateEx(u1 mode,u1 role,u1Array* pin){
+	u1Array* _u1Array = NULL;
+	Invoke(3, 0x5177, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+void CardModuleService::DeauthenticateEx(u1 roles){
+	Invoke(1, 0xBD7B, MARSHALLER_TYPE_IN_U1, roles, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetCardProperty(u1 property,u1 flags){
+	u1Array* _u1Array = NULL;
+	Invoke(2, 0x8187, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1Array* CardModuleService::BM_GetBioHeader(u1 role){
+	u1Array* _u1Array = NULL;
+	Invoke(1, 0x4838, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+
+u1 CardModuleService::BM_BioMatch(u1 role,u1Array* verificationData){
+	u1 _u1 = 0;
+	Invoke(2, 0x2D3D, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, verificationData, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+u1Array* CardModuleService::BM_GetRoles(){
+	u1Array* _u1Array = NULL;
+	Invoke(0, 0xA77A, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+	return _u1Array;
+}
+
+u1 CardModuleService::get_BM_DefaultRole(){
+	u1 _u1 = 0;
+	Invoke(0, 0x17FD, MARSHALLER_TYPE_RET_U1, &_u1);
+	return _u1;
+}
+
+
+void CardModuleService::set_BM_DefaultRole(u1 value){
+	Invoke(1, 0x4F1E, MARSHALLER_TYPE_IN_U1, value, MARSHALLER_TYPE_RET_VOID);
+}
+
+u1 CardModuleService::get_BM_AuthPinAllowed(){
+	u1 _u1 = 0;
+	Invoke(0, 0x9063, MARSHALLER_TYPE_RET_BOOL, &_u1);
+	return _u1;
+}
+
+string* CardModuleService::BM_GetVerifUIName(){
+	string* _string = NULL;
+	Invoke(0, 0x7BB7, MARSHALLER_TYPE_RET_STRING, &_string);
+	return _string;
+}
+
+
+string* CardModuleService::BM_GetEnrollUIName(){
+	string* _string = NULL;
+	Invoke(0, 0x0D17, MARSHALLER_TYPE_RET_STRING, &_string);
+	return _string;
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,98 @@
+// Machine generated C++ stub file (.h) for remote object CardModuleService
+// Created on : 06/05/2008 12:22:51
+
+
+#ifndef _include_CardModuleService_h
+#define _include_CardModuleService_h
+
+#include <string>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#include "PCSC.h"
+#include "Marshaller.h"
+
+#ifdef CardModuleService_EXPORTS
+#define CardModuleService_API __declspec(dllexport)
+#else
+#define CardModuleService_API
+#endif
+
+using namespace std;
+using namespace Marshaller;
+
+class CardModuleService_API CardModuleService : private SmartCardMarshaller {
+public:
+	// Constructors
+	CardModuleService(string* uri);
+	CardModuleService(string* uri, u4 index);
+	CardModuleService(u2 portNumber, string* uri);
+	CardModuleService(u2 portNumber, string* uri, u4 index);
+	CardModuleService(string* readerName, string* uri);
+	CardModuleService(string* readerName, u2 portNumber, string* uri);
+	CardModuleService(SCARDHANDLE cardHandle, string* uri);
+	CardModuleService(SCARDHANDLE cardHandle, u2 portNumber, string* uri);
+
+    // Extra method (Microsoft CardModule only)
+    void UpdateCardHandle(SCARDHANDLE cardHandle);
+
+	// Pre-defined methods
+	string* GetReader(void);
+	SCARDHANDLE GetPcscCardHandle(void);
+    void DoSCardTransact(bool flag);
+
+	// Exposed methods
+	void ChangeReferenceData(u1 mode,u1 role,u1Array* oldPin,u1Array* newPin,s4 maxTries);
+	s4 GetTriesRemaining(u1 role);
+	void CreateCAPIContainer(u1 ctrIndex,u1 keyImport,u1 keySpec,s4 keySize,u1Array* keyValue);
+	void DeleteCAPIContainer(u1 ctrIndex);
+	u1Array* GetCAPIContainer(u1 ctrIndex);
+	u1Array* PrivateKeyDecrypt(u1 ctrIndex,u1 keyType,u1Array* encryptedData);
+	void CreateFile(string* path,u1Array* acls,s4 initialSize);
+	void CreateDirectory(string* path,u1Array* acls);
+	void WriteFile(string* path,u1Array* data);
+	u1Array* ReadFile(string* path,s4 maxBytesToRead);
+	void DeleteFile(string* path);
+	void DeleteDirectory(string* path);
+	StringArray* GetFiles(string* path);
+	u1Array* GetFileProperties(string* path);
+	void ChangeAuthenticatorEx(u1 mode,u1 oldRole,u1Array* oldPin,u1 newRole,u1Array* newPin,s4 maxTries);
+	u1Array* GetContainerProperty(u1 ctrIndex,u1 property,u1 flags);
+	void SetContainerProperty(u1 ctrIndex,u1 property,u1Array* data,u1 flags);
+	void SetCardProperty(u1 property,u1Array* data,u1 flags);
+	s4 GetMemory();
+	void ForceGarbageCollector();
+	void RecursiveDelete(string* path);
+	void Select(MemoryStream* AID);
+	void Verify(u1 P1,u1 P2,u1Array* pin);
+	u1 get_AdminPersonalized();
+	u1 get_UserPersonalized();
+	u1Array* GetChallenge();
+	s8 get_AuthenticationDelay();
+	void ExternalAuthenticate(u1Array* response);
+	void VerifyPin(u1 role,u1Array* pin);
+	u1 IsAuthenticated(u1 role);
+	s4Array* QueryFreeSpace();
+	s4Array* QueryKeySizes();
+	void LogOut(u1 role);
+	void SerializeData(string* filename);
+	void DeSerializeData(string* filename);
+	u1Array* get_SerialNumber();
+	string* get_Version();
+	void SetHostVersion(u4 hostVersion);
+	u1Array* GetChallengeEx(u1 role);
+	u1Array* AuthenticateEx(u1 mode,u1 role,u1Array* pin);
+	void DeauthenticateEx(u1 roles);
+	u1Array* GetCardProperty(u1 property,u1 flags);
+
+	u1Array* BM_GetBioHeader(u1 role);
+	u1 BM_BioMatch(u1 role,u1Array* verificationData);
+	u1Array* BM_GetRoles();
+	u1 get_BM_DefaultRole();
+	void set_BM_DefaultRole(u1 value);
+	u1 get_BM_AuthPinAllowed();
+	string* BM_GetVerifUIName();
+	string* BM_GetEnrollUIName();
+};
+
+
+#endif

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,879 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cert_utils.h"
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+CCertUtils::CCertUtils(void)
+{
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+CCertUtils::~CCertUtils(void)
+{
+}
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::IsSequence(BYTE *content)
+{
+   return (content[0] == 0x30);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::IsInteger(BYTE *content)
+{
+   return (content[0] == 0x02);
+}
+
+
+//------------------------------------------------------------------------------
+// int ExtractContent(ASN1 *pAsn1)
+//
+// Description : Extract contents of a Asn1 block 'pAsn1->Asn1' and place it
+//              in 'pAsn1->Content'.
+//
+// Remarks     : Field Asn1.pData is allocated by calling function.
+//
+// In          : pAsn1->Asn1.pData
+//
+// Out         : This fileds are filled (if RV_SUCCESS) :
+//                - Tag
+//                - Asn1.usLen
+//                - Content.usLen
+//                - Content.pData
+//
+// Responses   : RV_SUCCESS : All is OK.
+//               RV_INVALID_DATA : Asn1 block format not supported.
+//
+//------------------------------------------------------------------------------
+int CCertUtils::ExtractContent(ASN1 *pAsn1)
+
+{
+   BYTE
+      *pData;
+   int
+      NbBytes,
+      i;
+
+   pData = pAsn1->Asn1.pData;
+
+   if ((pData[0] & 0x1F) == 0x1F)
+   {
+      // High-tag-number : not supported
+      return(RV_INVALID_DATA);
+   }
+   else
+   {
+      pAsn1->Tag = pData[0];
+   }
+
+   if (pData[1] == 0x80)
+   {
+      // Constructed, indefinite-length method : not supported
+      return(RV_INVALID_DATA);
+   }
+   else if (pData[1] > 0x82)
+   {
+      // Constructed, definite-length method : too long
+      return(RV_INVALID_DATA);
+   }
+   else if (pData[1] < 0x80)
+   {
+      // Primitive, definite-length method
+
+      pAsn1->Content.usLen = pData[1];
+      pAsn1->Content.pData = &pData[2];
+
+      pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2;
+   }
+   else
+   {
+      // Constructed, definite-length method
+
+      NbBytes = pData[1] & 0x7F;
+
+      pAsn1->Content.usLen = 0;
+      for (i = 0; i < NbBytes; i++)
+      {
+          pAsn1->Content.usLen = (pAsn1->Content.usLen << 8) + pData[2+i];
+      }
+      pAsn1->Content.pData = &pData[2+NbBytes];
+
+      pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2 + NbBytes;
+   }
+
+   return(RV_SUCCESS);
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::MemReverse(BYTE *pbOut, BYTE *pbIn, DWORD dwLen)
+{
+   DWORD i;
+
+   for (i = 0; i < dwLen; i++)
+   {
+      pbOut[i] = pbIn[dwLen - i -1];
+   }
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::ConvAscii (BYTE  *pIn,
+                          DWORD  dwLen,
+                          BYTE  *pOut
+                         )
+{
+#define tohex(x)  (((x) >= 0xA) ? ((x) - 0xA + 'A') : ((x) + '0'))
+   register DWORD i;
+
+   for(i=0; i < dwLen; i++)
+   {
+      pOut[i*2] = tohex((pIn[i] >> 4) & 0xF);
+      pOut[i*2+1] =  tohex(pIn[i] & 0xF);
+   }
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::ConvHex (BYTE  *pIn,
+                        DWORD  dwLen,
+                        BYTE  *pOut
+                       )
+{
+#define fromhex(x) (x-((x>='0')&&(x<='9')?'0':((x>='A')&&(x<='F')?'7':'W')))
+   register DWORD i;
+
+   for(i=0; i < dwLen; i+=2)
+   {
+      pOut[i/2] = (fromhex(pIn[i]) << 4) + fromhex(pIn[i+1]);
+   }
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+BYTE* CCertUtils::GetDERLength(BYTE *content, DWORD *len)
+{
+   DWORD NBBytesForLength = 0;
+   unsigned short usLen = 0,i=0;
+
+
+   if(content == NULL){
+      *len = 0;
+      return NULL;
+   }
+   if(content[1] < 0x80){
+      *len = content[1];
+      return &content[2];
+   }
+
+   NBBytesForLength = content[1] & 0x7F;
+
+   usLen = 0;
+   for (i = 0; i < NBBytesForLength; i++)
+   {
+       usLen = (usLen << 8) + content[2+i];
+   }
+
+   *len = usLen;
+   return &content[2+NBBytesForLength];
+
+}
+
+
+//------------------------------------------------------------------------------
+// bool ParseCertificateValue(BYTE *pCert,          DWORD  dwCertLen,
+//                            BYTE *pSerialNumber,  DWORD *pdwSerialNumberLen,
+//                            BYTE *pIssuer,        DWORD *pdwIssuerLen,
+//                            BYTE *pSubject,       DWORD *pdwSubjectLen
+//                           )
+//
+// In          : pCert : Value of a valid X509 certificate.
+//               dwCertLen : Length of value.
+//
+// Out         : pSerialNumber : Field 'SerialNumber'
+//               pusSerialNumberLen : Serial number length
+//               pIssuer : Field 'Issuer'
+//               pusIssuerLen : Issuer length
+//               pSubject : Field 'Subject'
+//               pusSubjectLen : Subject length
+//
+// Responses   : true: All is OK.
+//               false: Parsing fails.
+//
+//------------------------------------------------------------------------------
+bool CCertUtils::ParseCertificateValue(BYTE *pCert,         DWORD /*dwCertLen*/,
+                                       BYTE *pSerialNumber, DWORD *pdwSerialNumberLen,
+                                       BYTE *pIssuer,       DWORD *pdwIssuerLen,
+                                       BYTE *pSubject,      DWORD *pdwSubjectLen
+                                      )
+
+{
+   ASN1
+      Value,
+      tbsCert,
+      serialNumberPart,
+      signaturePart,
+      issuerPart,
+      validityPart,
+      subjectPart;
+   bool
+      bValuesToBeReturned;
+   BYTE
+      *pCurrent;
+   int
+      rv;
+   DWORD
+      SerialNumberLen,
+      IssuerLen,
+      SubjectLen;
+
+
+   bValuesToBeReturned =   (pSerialNumber != NULL)
+                        && (pIssuer != NULL)
+                        && (pSubject != NULL);
+
+
+   Value.Asn1.pData = pCert;
+   rv = ExtractContent(&Value);
+   if (rv != RV_SUCCESS) return false;
+
+   tbsCert.Asn1.pData = Value.Content.pData;
+   rv = ExtractContent(&tbsCert);
+   if (rv != RV_SUCCESS) return false;
+
+
+   pCurrent = tbsCert.Content.pData;
+   if (pCurrent[0] == TAG_OPTION_VERSION)
+   {
+      // We have A0 03 02 01 vv  where vv is the version
+      pCurrent += 5;
+   }
+
+   serialNumberPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&serialNumberPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+   signaturePart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&signaturePart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+   issuerPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&issuerPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+   validityPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&validityPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+   subjectPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&subjectPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+   SerialNumberLen = serialNumberPart.Content.usLen;
+   IssuerLen = issuerPart.Asn1.usLen;
+   SubjectLen = subjectPart.Asn1.usLen;
+
+   if (bValuesToBeReturned)
+   {
+      if (    (*pdwSerialNumberLen < SerialNumberLen)
+           || (*pdwIssuerLen < IssuerLen)
+           || (*pdwSubjectLen < SubjectLen)
+         )
+      {
+         return(false);
+      }
+      memcpy(pSerialNumber, serialNumberPart.Content.pData, SerialNumberLen);
+      memcpy(pIssuer, issuerPart.Asn1.pData, IssuerLen);
+      memcpy(pSubject, subjectPart.Asn1.pData, SubjectLen);
+      *pdwSerialNumberLen = SerialNumberLen;
+      *pdwIssuerLen = IssuerLen;
+      *pdwSubjectLen = SubjectLen;
+   }
+   else
+   {
+      *pdwSerialNumberLen = SerialNumberLen;
+      *pdwIssuerLen = IssuerLen;
+      *pdwSubjectLen = SubjectLen;
+   }
+
+   return(true);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::MakeCertificateLabel(BYTE  *pCert,
+                                      DWORD  /*dwCertLen*/,
+                                      BYTE  *pLabel,
+                                      DWORD *pdwLabelLen
+                                     )
+{
+   ASN1
+        AttributeTypePart,
+        AttributeValuePart,
+        AVA,
+        RDN,
+      Value,
+      tbsCert,
+      serialNumberPart,
+      signaturePart,
+      issuerPart,
+      validityPart,
+      subjectPart;
+    BLOC
+        OrganizationName,
+        CommonName;
+   bool
+      bValuesToBeReturned;
+   BYTE
+      *pCurrentRDN,
+      *pCurrent;
+   int
+      rv;
+
+    OrganizationName.pData = NULL;
+    OrganizationName.usLen = 0;
+    CommonName.pData = NULL;
+    CommonName.usLen = 0;
+
+    bValuesToBeReturned =   (pLabel != NULL);
+
+   Value.Asn1.pData = pCert;
+   rv = ExtractContent(&Value);
+   if (rv != RV_SUCCESS) return false;
+
+   tbsCert.Asn1.pData = Value.Content.pData;
+   rv = ExtractContent(&tbsCert);
+   if (rv != RV_SUCCESS) return false;
+
+
+   pCurrent = tbsCert.Content.pData;
+   if (pCurrent[0] == TAG_OPTION_VERSION)
+   {
+      /* We have A0 03 02 01 vv  where vv is the version                      */
+      pCurrent += 5;
+   }
+
+   serialNumberPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&serialNumberPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+   signaturePart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&signaturePart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+   issuerPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&issuerPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+   validityPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&validityPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+   subjectPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&subjectPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+    // Search field 'OrganizationName' in 'Issuer'
+   pCurrent = issuerPart.Content.pData;
+
+   while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'OrganisationName'
+            if (!memcmp("\x55\x04\x0A",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                OrganizationName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+   // If no 'OrganizationName' is 'Issuer' search for 'CommonName' in 'Subject'
+   if (OrganizationName.usLen == 0)
+   {
+      pCurrent = issuerPart.Content.pData;
+
+      while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+      {
+         RDN.Asn1.pData = pCurrent;
+         rv = ExtractContent(&RDN);
+         if (rv != RV_SUCCESS) return false;
+
+         pCurrentRDN = RDN.Content.pData;
+
+         while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+         {
+               AVA.Asn1.pData = pCurrentRDN;
+               rv = ExtractContent(&AVA);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeTypePart.Asn1.pData = AVA.Content.pData;
+               rv = ExtractContent(&AttributeTypePart);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                      + AttributeTypePart.Content.usLen;
+               rv = ExtractContent(&AttributeValuePart);
+               if (rv != RV_SUCCESS) return false;
+
+               // Search 'CommonName'
+               if (!memcmp("\x55\x04\x03",
+                              AttributeTypePart.Content.pData,
+                              AttributeTypePart.Content.usLen)
+                  )
+               {
+                  OrganizationName = AttributeValuePart.Content;
+               }
+
+               pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+         }
+
+         pCurrent = RDN.Content.pData + RDN.Content.usLen;
+      }
+   }
+
+   // Search 'CommonName' in 'Subject'
+   pCurrent = subjectPart.Content.pData;
+
+   while (pCurrent < subjectPart.Content.pData + subjectPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'CommonName'
+            if (!memcmp("\x55\x04\x03",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                CommonName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+    if (bValuesToBeReturned)
+    {
+        if (    (*pdwLabelLen < (DWORD)(OrganizationName.usLen + CommonName.usLen))
+           )
+        {
+            return(false);
+        }
+
+        if (CommonName.usLen > 0)
+        {
+           memcpy(pLabel,
+                CommonName.pData,
+                CommonName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen],
+                "'s ",
+                3
+               );
+           memcpy(&pLabel[CommonName.usLen+3],
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen],
+                " ID",
+                3
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
+        }
+        else
+        {
+           memcpy(pLabel,
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[OrganizationName.usLen],
+                " ID",
+                3
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + 3;
+        }
+    }
+    else
+    {
+        if (CommonName.usLen > 0)
+        {
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
+        }
+        else
+        {
+           *pdwLabelLen = OrganizationName.usLen + 3;
+        }
+    }
+
+    return(true);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::MakeCertificateLabelEx(BYTE  *pCert,
+                                        DWORD  /*dwCertLen*/,
+                                        BYTE  *pLabel,
+                                        DWORD *pdwLabelLen
+                                       )
+{
+   ASN1
+        AttributeTypePart,
+        AttributeValuePart,
+        AVA,
+        RDN,
+      Value,
+      tbsCert,
+      serialNumberPart,
+      signaturePart,
+      issuerPart,
+      validityPart,
+      subjectPart;
+    BLOC
+        OrganizationName,
+        CommonName;
+   bool
+      bValuesToBeReturned;
+   BYTE
+      *pCurrentRDN,
+      *pCurrent,
+      szSerialNumber[256] = "";
+   int
+      rv;
+
+    OrganizationName.pData = NULL;
+    OrganizationName.usLen = 0;
+    CommonName.pData = NULL;
+    CommonName.usLen = 0;
+
+    bValuesToBeReturned =   (pLabel != NULL);
+
+   Value.Asn1.pData = pCert;
+   rv = ExtractContent(&Value);
+   if (rv != RV_SUCCESS) return false;
+
+   tbsCert.Asn1.pData = Value.Content.pData;
+   rv = ExtractContent(&tbsCert);
+   if (rv != RV_SUCCESS) return false;
+
+
+   pCurrent = tbsCert.Content.pData;
+   if (pCurrent[0] == TAG_OPTION_VERSION)
+   {
+      /* We have A0 03 02 01 vv  where vv is the version                      */
+      pCurrent += 5;
+   }
+
+   serialNumberPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&serialNumberPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+   memset(szSerialNumber, 0x00, sizeof(szSerialNumber));
+
+   ConvAscii(serialNumberPart.Asn1.pData, serialNumberPart.Asn1.usLen, szSerialNumber);
+
+   signaturePart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&signaturePart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+   issuerPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&issuerPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+   validityPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&validityPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+   subjectPart.Asn1.pData = pCurrent;
+   rv = ExtractContent(&subjectPart);
+   if (rv != RV_SUCCESS) return false;
+   pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+    // Search field 'OrganizationName' in 'Issuer'
+   pCurrent = issuerPart.Content.pData;
+
+   while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'OrganisationName'
+            if (!memcmp("\x55\x04\x0A",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                OrganizationName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+   // If no 'OrganizationName' is 'Issuer' search for 'CommonName' in 'Subject'
+   if (OrganizationName.usLen == 0)
+   {
+      pCurrent = issuerPart.Content.pData;
+
+      while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+      {
+         RDN.Asn1.pData = pCurrent;
+         rv = ExtractContent(&RDN);
+         if (rv != RV_SUCCESS) return false;
+
+         pCurrentRDN = RDN.Content.pData;
+
+         while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+         {
+               AVA.Asn1.pData = pCurrentRDN;
+               rv = ExtractContent(&AVA);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeTypePart.Asn1.pData = AVA.Content.pData;
+               rv = ExtractContent(&AttributeTypePart);
+               if (rv != RV_SUCCESS) return false;
+
+               AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                      + AttributeTypePart.Content.usLen;
+               rv = ExtractContent(&AttributeValuePart);
+               if (rv != RV_SUCCESS) return false;
+
+               // Search 'CommonName'
+               if (!memcmp("\x55\x04\x03",
+                              AttributeTypePart.Content.pData,
+                              AttributeTypePart.Content.usLen)
+                  )
+               {
+                  OrganizationName = AttributeValuePart.Content;
+               }
+
+               pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+         }
+
+         pCurrent = RDN.Content.pData + RDN.Content.usLen;
+      }
+   }
+
+   // Search 'CommonName' in 'Subject'
+   pCurrent = subjectPart.Content.pData;
+
+   while (pCurrent < subjectPart.Content.pData + subjectPart.Content.usLen)
+   {
+      RDN.Asn1.pData = pCurrent;
+      rv = ExtractContent(&RDN);
+      if (rv != RV_SUCCESS) return false;
+
+        pCurrentRDN = RDN.Content.pData;
+
+        while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+        {
+            AVA.Asn1.pData = pCurrentRDN;
+            rv = ExtractContent(&AVA);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeTypePart.Asn1.pData = AVA.Content.pData;
+            rv = ExtractContent(&AttributeTypePart);
+            if (rv != RV_SUCCESS) return false;
+
+            AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+                                                    + AttributeTypePart.Content.usLen;
+            rv = ExtractContent(&AttributeValuePart);
+            if (rv != RV_SUCCESS) return false;
+
+            // Search 'CommonName'
+            if (!memcmp("\x55\x04\x03",
+                            AttributeTypePart.Content.pData,
+                            AttributeTypePart.Content.usLen)
+                )
+            {
+                CommonName = AttributeValuePart.Content;
+            }
+
+            pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+        }
+
+        pCurrent = RDN.Content.pData + RDN.Content.usLen;
+   }
+
+    if (bValuesToBeReturned)
+    {
+        if (    (*pdwLabelLen < (DWORD)(OrganizationName.usLen + CommonName.usLen))
+           )
+        {
+            return(false);
+        }
+
+        if (CommonName.usLen > 0)
+        {
+           memcpy(pLabel,
+                CommonName.pData,
+                CommonName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen],
+                "'s ",
+                3
+               );
+           memcpy(&pLabel[CommonName.usLen+3],
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen],
+                " ID - ",
+                6
+               );
+           memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen+6],
+                szSerialNumber,
+                strlen((char *)szSerialNumber)
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + (DWORD)strlen((char *)szSerialNumber) + 9;
+        }
+        else
+        {
+           memcpy(pLabel,
+                OrganizationName.pData,
+                OrganizationName.usLen
+               );
+           memcpy(&pLabel[OrganizationName.usLen],
+                " ID - ",
+                6
+               );
+           memcpy(&pLabel[OrganizationName.usLen+6],
+                szSerialNumber,
+                strlen((char *)szSerialNumber)
+               );
+
+           *pdwLabelLen = OrganizationName.usLen + (DWORD)strlen((char *)szSerialNumber) + 6;
+        }
+    }
+    else
+    {
+        if (CommonName.usLen > 0)
+        {
+           *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + (DWORD)strlen((char *)szSerialNumber) + 9;
+        }
+        else
+        {
+           *pdwLabelLen = OrganizationName.usLen + (DWORD)strlen((char *)szSerialNumber) + 6;
+        }
+    }
+
+    return(true);
+}
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,119 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#pragma once
+
+#define CERT_TYPE_UNKNOWN     (0)
+#define CERT_TYPE_USER        (1)
+#define CERT_TYPE_CA_ROOT     (2)
+
+#define CERT_USAGE_UNKNOWN    (0)
+#define CERT_USAGE_EXCHANGE   (AT_KEYEXCHANGE)
+#define CERT_USAGE_SIGNATURE  (AT_SIGNATURE)
+
+// Errors code
+#define RV_SUCCESS					0	// Info
+#define RV_COMPRESSION_FAILED		1	// Warning
+#define RV_MALLOC_FAILED			2	// Error
+#define RV_BAD_DICTIONARY			3	// Error
+#define RV_INVALID_DATA				4	// Error
+#define RV_BLOC_TOO_LONG			5	// Warning
+#define RV_FILE_OPEN_FAILED         6	// Error
+#define RV_BUFFER_TOO_SMALL         7	// Error
+
+#define TAG_OPTION_VERSION          0xA0
+
+/*------------------------------------------------------------------------------
+                          Types definitions
+------------------------------------------------------------------------------*/
+typedef unsigned char   TAG;
+typedef TAG*            TAG_PTR;
+typedef BYTE*           BYTE_PTR;
+
+typedef struct
+{
+   USHORT   usLen;
+   BYTE_PTR pData;
+} BLOC, * BLOC_PTR;
+
+typedef struct
+{
+   BLOC Asn1;
+   BLOC Content;
+   TAG  Tag;
+} ASN1, * ASN1_PTR;
+
+
+class CCertUtils
+{
+public:
+   CCertUtils(void);
+   ~CCertUtils(void);
+
+void MemReverse                 (BYTE *pbOut,
+                                 BYTE *pbIn,
+                                 DWORD dwLen
+                                );
+
+void ConvAscii                  (BYTE  *pIn,
+                                 DWORD  dwLen,
+                                 BYTE  *pOut
+                                );
+
+void ConvHex                    (BYTE  *pIn,
+                                 DWORD  dwLen,
+                                 BYTE  *pOut
+                                );
+
+BYTE *GetDERLength              (BYTE  *content,
+                                 DWORD *len
+                                );
+
+bool ParseCertificateValue      (BYTE                   *pCert,
+                                 DWORD                  dwCertLen,
+                                 BYTE                   *pSerialNumber,
+                                 DWORD                  *pdwSerialNumberLen,
+                                 BYTE                   *pIssuer,
+                                 DWORD                  *pdwIssuerLen,
+                                 BYTE                   *pSubject,
+                                 DWORD                  *pdwSubjectLen
+                                );
+
+bool MakeCertificateLabel       (BYTE                   *pCert,
+                                 DWORD                  dwCertLen,
+                                 BYTE                   *pLabel,
+                                 DWORD                  *pdwLabelLen
+                                );
+
+bool MakeCertificateLabelEx     (BYTE                   *pCert,
+                                 DWORD                  dwCertLen,
+                                 BYTE                   *pLabel,
+                                 DWORD                  *pdwLabelLen
+                                );
+
+
+private:
+int ExtractContent       (ASN1 *pAsn1);
+
+bool IsSequence          (BYTE *content);
+
+bool IsInteger           (BYTE *content);
+};
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,258 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+//#include "dbg.h"
+#include "util.h"
+
+#include "certificateobject.h"
+
+CertificateObject::CertificateObject() : StorageObject()
+{
+   this->_trusted   = CK_FALSE;
+   this->_checkSum  = NULL_PTR;
+   this->_startDate = NULL_PTR;
+   this->_endDate   = NULL_PTR;
+
+   this->_class = CKO_CERTIFICATE;
+
+   this->_ctrIndex = 0xFF;
+   this->_keySpec  = 0xFF;
+}
+
+CertificateObject::~CertificateObject()
+{
+   if(this->_checkSum != NULL_PTR)
+      delete this->_checkSum;
+
+   if(this->_startDate != NULL_PTR)
+      delete this->_startDate;
+
+   if(this->_endDate != NULL_PTR)
+      delete this->_endDate;
+
+}
+
+bool CertificateObject::IsEqual(const StorageObject * that) const
+{
+   if(_uniqueId != 0 && that->_uniqueId != 0)
+      return (_uniqueId == that->_uniqueId);
+
+   // Only objects that have been stored under p11 directory
+   // will have a non-zero _uniqueId. For other objects, do
+   // a deep comparison based on other attributes.
+   if(_class != that->_class)
+      return false;
+
+   const CertificateObject * thatCert = static_cast<const CertificateObject*>(that);
+   return ( (_ctrIndex == thatCert->_ctrIndex) &&
+      (_keySpec == thatCert->_keySpec) &&
+      (_checkValue == thatCert->_checkValue));
+}
+
+CK_BBOOL CertificateObject::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_CERTIFICATE_TYPE:
+           return (this->_certType == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_CERTIFICATE_CATEGORY:
+           return (this->_certCategory == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_TRUSTED:
+           return (this->_trusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_CHECK_VALUE:
+           return Util::CompareU1Arrays(this->_checkSum,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_START_DATE:
+           return Util::CompareU1Arrays(this->_startDate,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_END_DATE:
+           return Util::CompareU1Arrays(this->_endDate,attribute.pValue,attribute.ulValueLen);
+
+        default:
+           return StorageObject::Compare(attribute);
+   }
+}
+
+CK_RV CertificateObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   CK_RV rv = CKR_OK;
+
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   if(objCreation == CK_FALSE){
+      switch(attribute.type){
+            case CKA_CERTIFICATE_TYPE:
+            case CKA_CERTIFICATE_CATEGORY:
+               return CKR_ATTRIBUTE_READ_ONLY;
+      }
+   }
+
+   switch(attribute.type){
+
+        case CKA_CERTIFICATE_TYPE:
+           {
+              CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_certType = utemp;}
+           }
+           break;
+
+        case CKA_CERTIFICATE_CATEGORY:
+           {
+              CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_certCategory = utemp;}
+           }
+           break;
+
+        case CKA_TRUSTED:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_trusted = btemp; }
+           }
+           break;
+
+        case CKA_CHECK_VALUE:
+           if(this->_checkSum != NULL_PTR){
+              delete this->_checkSum;
+           }
+           this->_checkSum = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        case CKA_START_DATE:
+           {
+              u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){
+                 if(this->_startDate != NULL_PTR){
+                    delete this->_startDate;
+                 }
+                 this->_startDate = dtemp;
+              }
+           }
+           break;
+
+        case CKA_END_DATE:
+           {
+              u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){
+                 if(this->_endDate != NULL_PTR){
+                    delete this->_endDate;
+                 }
+                 this->_endDate = dtemp;
+              }
+           }
+           break;
+
+        default:
+           return StorageObject::SetAttribute(attribute,objCreation);
+   }
+
+   return rv;
+}
+
+CK_RV CertificateObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type){
+
+        case CKA_CERTIFICATE_TYPE:
+           return StorageObject::PutULongInAttribute(this->_certType,attribute);
+
+        case CKA_CERTIFICATE_CATEGORY:
+           return StorageObject::PutULongInAttribute(this->_certCategory,attribute);
+
+        case CKA_TRUSTED:
+           return StorageObject::PutBBoolInAttribute(this->_trusted,attribute);
+
+        case CKA_CHECK_VALUE:
+           return StorageObject::PutU1ArrayInAttribute(this->_checkSum,attribute);
+
+        case CKA_START_DATE:
+           return StorageObject::PutU1ArrayInAttribute(this->_startDate,attribute);
+
+        case CKA_END_DATE:
+           return StorageObject::PutU1ArrayInAttribute(this->_endDate,attribute);
+
+        default:
+           return StorageObject::GetAttribute(attribute);
+   }
+}
+
+void CertificateObject::Serialize(std::vector<u1> *to)
+{
+   StorageObject::Serialize(to);
+
+   Util::PushULongInVector(to,this->_certType);
+
+   Util::PushULongInVector(to,this->_certCategory);
+
+   Util::PushBBoolInVector(to,this->_trusted);
+
+   Util::PushByteArrayInVector(to,this->_startDate);
+
+   Util::PushByteArrayInVector(to,this->_endDate);
+
+   Util::PushByteArrayInVector(to,this->_checkSum);
+
+   // serialize the extra fields
+
+   PKCS11_ASSERT(_checkValue != 0);
+   PKCS11_ASSERT(_ctrIndex < 100);
+   PKCS11_ASSERT(_keySpec == 1 || _keySpec == 2 );
+
+   Util::PushULongLongInVector(to,this->_checkValue);
+
+   Util::PushBBoolInVector(to,this->_ctrIndex);
+
+   Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void CertificateObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   StorageObject::Deserialize(from,idx);
+
+   this->_certType = Util::ReadULongFromVector(from,idx);
+
+   this->_certCategory = Util::ReadULongFromVector(from,idx);
+
+   this->_trusted = Util::ReadBBoolFromVector(from,idx);
+
+   this->_startDate = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_endDate = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_checkSum = Util::ReadByteArrayFromVector(from,idx);
+
+   // serialize the extra fields
+
+   this->_checkValue = Util::ReadULongLongFromVector(from,idx);
+
+   this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+   this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,57 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_certificateobject_h
+#define _include_certificateobject_h
+
+#include "storageobject.h"
+
+class CertificateObject : public StorageObject{
+
+public:
+    CK_ULONG        _certType;
+    CK_BBOOL        _trusted;
+    CK_ULONG        _certCategory;
+    u1Array*        _checkSum;
+    u1Array*        _startDate;
+    u1Array*        _endDate;
+
+    // extra fields
+    std::string     _certName;
+    u8              _checkValue;
+    CK_BYTE         _ctrIndex;
+    CK_BYTE         _keySpec;
+
+public:
+    CertificateObject();
+    virtual ~CertificateObject();
+
+    virtual bool IsEqual(const StorageObject * that) const;
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,26 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_config_h
+#define _include_config_h
+
+#define CONFIG_MAX_SLOT                     16
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,112 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// Copied from ACS
+
+#include "stdafx.h"
+#include "critsect.h"
+
+#if !defined (_WIN32)
+#include <stdexcept>
+#endif
+
+CCriticalSection::CCriticalSection()
+{
+    Init();
+}
+
+/*
+CCriticalSection::CCriticalSection(bool)
+{
+    Init();
+}
+*/
+
+CCriticalSection::~CCriticalSection(void)
+{
+#if defined (_WIN32)
+
+    DeleteCriticalSection(&m_CriticalSection);
+
+#else
+
+    pthread_mutex_destroy(&m_Mutex);
+
+#endif
+}
+
+
+void CCriticalSection::Enter()
+{
+#if defined (_WIN32)
+
+    EnterCriticalSection(&m_CriticalSection);
+
+#else
+
+    if(pthread_equal(m_OwnerThread,pthread_self())) m_RefCount++;
+    else {
+        int Stat = pthread_mutex_lock(&m_Mutex);
+        if(Stat)
+            throw std::runtime_error("pthread_mutex_lock");
+
+        m_OwnerThread = pthread_self();
+        m_RefCount = 1;
+    }
+
+#endif
+}
+
+void CCriticalSection::Leave()
+{
+
+#if defined (_WIN32)
+
+    LeaveCriticalSection(&m_CriticalSection);
+
+#else
+
+    if(pthread_equal(m_OwnerThread,pthread_self())) {
+        m_RefCount--;
+        if(!m_RefCount) {
+            m_OwnerThread = 0;
+            pthread_mutex_unlock(&m_Mutex);
+        }
+    }
+
+#endif
+
+    return;
+}
+
+void CCriticalSection::Init()
+{
+#if defined (_WIN32)
+
+	InitializeCriticalSection(&m_CriticalSection);
+
+#else
+
+    pthread_mutex_init(&m_Mutex,0);
+    m_OwnerThread = 0;
+    m_RefCount = 0;
+
+#endif
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,95 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// Copied from ACS
+
+#ifndef _include_critsect_h
+#define _include_critsect_h
+
+#if defined(_WIN32)
+
+#include <windows.h>
+
+#else
+
+#include <pthread.h>
+
+#endif
+
+class CCriticalSection
+{
+
+public:
+
+    // A non-default constructor with a dummy parameter is added since
+    // it is needed when CCriticalSection is used as static member in
+    // template classes to instantiate properly with GCC. See for instance
+    // http://gcc.gnu.org/ml/gcc-bugs/2005-01/msg03798.html
+
+    CCriticalSection();
+    //explicit CCriticalSection(bool dummy);
+    ~CCriticalSection();
+    void Enter();
+    void Leave();
+
+private:
+    void Init();
+
+#if defined(_WIN32)
+
+	CRITICAL_SECTION m_CriticalSection;
+
+#else
+
+    pthread_mutex_t m_Mutex;
+    pthread_t m_OwnerThread;
+    unsigned long m_RefCount;
+
+#endif
+
+};
+
+// Convenience class to manage locking
+
+class CCriticalSectionLocker
+{
+public:
+    CCriticalSectionLocker(CCriticalSection & cs) : m_cs(&cs)
+    {
+        m_cs->Enter();
+    }
+    CCriticalSectionLocker(CCriticalSection * cs) : m_cs(cs)
+    {
+        if(m_cs)
+            m_cs->Enter();
+    }
+   ~CCriticalSectionLocker()
+    {
+        if(m_cs)
+            m_cs->Leave();
+    }
+
+private:
+    CCriticalSection * m_cs;
+};
+
+
+#endif // _include_critsect_h
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,175 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+#include "dataobject.h"
+
+DataObject::DataObject() : StorageObject()
+{
+   this->_class    = CKO_DATA;
+   this->_appName  = NULL_PTR;
+   this->_objId    = NULL_PTR;
+   this->_objValue = NULL_PTR;
+}
+
+DataObject::~DataObject(){
+
+   if(this->_appName != NULL_PTR){
+      delete this->_appName;
+   }
+
+   if(this->_objId != NULL_PTR){
+      delete this->_objId;
+   }
+
+   if(this->_objValue != NULL_PTR){
+      delete this->_objValue;
+   }
+}
+
+CK_BBOOL DataObject::Compare(CK_ATTRIBUTE attribute)
+{
+   CK_BBOOL bRet = CK_FALSE;
+
+   switch(attribute.type)
+   {
+   case CKA_APPLICATION:
+      bRet = Util::CompareU1Arrays(this->_appName,attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_OBJECT_ID:
+      bRet = Util::CompareU1Arrays(this->_objId,attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_VALUE:
+      bRet = Util::CompareU1Arrays(this->_objValue,attribute.pValue,attribute.ulValueLen);
+      break;
+
+   default:
+      bRet = StorageObject::Compare( attribute );
+      break;
+   }
+
+   return bRet;
+}
+
+CK_RV DataObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+   switch(attribute.type){
+
+        case CKA_APPLICATION:
+           {
+              u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){
+                 if(this->_appName != NULL_PTR){
+                    delete this->_appName;
+                 }
+                 this->_appName = stemp;
+              }
+           }
+           break;
+
+
+        case CKA_OBJECT_ID:
+           if(this->_objId != NULL_PTR){
+              delete this->_objId;
+           }
+           this->_objId = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        case CKA_VALUE:
+           if(this->_objValue != NULL_PTR){
+              delete this->_objValue;
+           }
+           this->_objValue = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        default:
+           return StorageObject::SetAttribute(attribute,objCreation);
+
+   }
+
+   return rv;
+}
+
+CK_RV DataObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   CK_RV ulRet = CKR_OK;
+   switch(attribute->type)
+   {
+   case CKA_APPLICATION:
+      ulRet = StorageObject::PutU1ArrayInAttribute(this->_appName,attribute);
+      break;
+
+   case CKA_OBJECT_ID:
+      ulRet = StorageObject::PutU1ArrayInAttribute(this->_objId,attribute);
+      break;
+
+   case CKA_VALUE:
+      ulRet = StorageObject::PutU1ArrayInAttribute(this->_objValue,attribute);
+      break;
+
+   default:
+      ulRet = StorageObject::GetAttribute(attribute);
+      break;
+   }
+
+   return ulRet;
+}
+
+
+void DataObject::Serialize(std::vector<u1>* to)
+{
+   // first go ahead and serialize the fields in base class
+   StorageObject::Serialize(to);
+
+   // serialize label attribute
+   Util::PushByteArrayInVector(to,this->_appName);
+
+   // serialize label attribute
+   Util::PushByteArrayInVector(to,this->_objId);
+
+   // serialize label attribute
+   Util::PushByteArrayInVector(to,this->_objValue);
+}
+
+void DataObject::Deserialize(std::vector<u1> from,CK_ULONG_PTR idx)
+{
+   // first go ahead and de-serialize the fields in base class
+   StorageObject::Deserialize(from,idx);
+
+   this->_appName = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_objId = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_objValue = Util::ReadByteArrayFromVector(from,idx);
+}
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,51 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_dataobject_h
+#define _include_dataobject_h
+
+#include "storageobject.h"
+
+class DataObject : public StorageObject
+{
+
+public:
+    u1Array* _appName;
+    u1Array* _objId;
+    u1Array* _objValue;
+
+public:
+
+    DataObject();
+    ~DataObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+
+};
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,54 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+#include "des.h"
+
+CDES::CDES(){
+    this->_blockSize = 8;
+}
+
+CDES::~CDES(){
+}
+
+void CDES::TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                  CK_BYTE_PTR input,CK_LONG input_offset,
+                                  CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    // encryprtMode == ENCRYPT then we need to XOR input with iv
+    if(iv != NULL_PTR && this->_encryptMode == ENCRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            input[input_offset+i] ^= iv[i];
+        }
+    }
+
+    algo_DES_DESProcess(key,&input[input_offset],&output[output_offset],(u1)encryptMode);
+
+    if(iv != NULL_PTR && this->_encryptMode == DECRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            output[output_offset+i] ^= iv[i];
+        }
+    }
+
+
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,42 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_des_h
+#define _include_des_h
+
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+class CDES : public CSymmAlgo
+{
+
+public:
+    CDES();
+    ~CDES();
+
+private:
+    void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                   CK_BYTE_PTR input,CK_LONG input_offset,
+                                   CK_BYTE_PTR output,CK_LONG output_offset);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+
+CDigest::CDigest(){
+    this->_counter       = 0;
+    this->_workingOffset = 0;
+    this->_workingLength = 0;
+}
+
+CDigest::~CDigest(){
+    free(this->_hashValue);
+    free(this->_workingBuffer);
+}
+
+void CDigest::HashCore(CK_BYTE_PTR data,CK_LONG offset,CK_LONG count)
+{
+    while (count > 0)
+    {
+        // prepare working buffer.
+        if ((_workingOffset + count) >= this->_blockLength){
+            _workingLength = this->_blockLength - _workingOffset;
+        }
+        else{
+            _workingLength = count;
+        }
+
+        memcpy(&_workingBuffer[_workingOffset],&data[offset],_workingLength);
+
+        _workingOffset += _workingLength;
+        count -= _workingLength;
+        offset += _workingLength;
+
+        if ((_workingOffset == this->_blockLength) && (count > 0)){
+
+            TransformBlock(_workingBuffer,_counter,_hashValue);
+
+            _counter += this->_blockLength;
+            _workingOffset = 0;
+        }
+    }
+}
+
+void CDigest::HashFinal(CK_BYTE_PTR hash)
+{
+    TransformFinalBlock(_workingBuffer,_workingOffset,_counter,_hashValue);
+    memcpy(hash,_hashValue,this->_hashLength);
+}
+
+CK_LONG CDigest::HashLength(void)
+{
+    return this->_hashLength;
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,49 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_digest_h
+#define _include_digest_h
+
+class CDigest
+{
+protected:
+    CK_BYTE_PTR  _workingBuffer;
+    CK_LONG      _workingOffset;
+    CK_LONG      _workingLength;
+    CK_LONG      _counter;
+    CK_BYTE_PTR  _hashValue;
+    CK_LONG      _hashLength;
+    CK_LONG      _blockLength;
+
+    virtual void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result) = 0;
+    virtual void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result) = 0;
+
+public:
+    CDigest();
+    virtual ~CDigest();
+
+    void HashCore(CK_BYTE_PTR data,CK_LONG offset,CK_LONG count);
+    void HashFinal(CK_BYTE_PTR hash);
+    CK_LONG HashLength(void);
+};
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,340 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "error.h"
+#include "log.h"
+
+
+#define ERROR_MEMORY "Persistent"
+
+
+/* CheckMarshallerException
+*/
+CK_RV CkError::CheckMarshallerException( Marshaller::Exception &x )
+{
+   UnauthorizedAccessException* uae = dynamic_cast< UnauthorizedAccessException* >( &x );
+   if( uae )
+   {
+      Log::log( "CheckMarshallerException", "## Error ## UnauthorizedAccessException <%s>", x.what( ) );
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   OutOfMemoryException* oome = dynamic_cast< OutOfMemoryException* >( &x );
+   if( oome )
+   {
+      Log::log( "CheckMarshallerException", "## Error ## OutOfMemoryException <%s>", x.what( ) );
+      return CKR_DEVICE_MEMORY;
+   }
+
+   if( NULL != x.what( ) )
+   {
+      if( 0 == strcmp( x.what( ), ERROR_MEMORY ) )
+      {
+         Log::log( "CheckMarshallerException", "## Error ## OutOfMemoryException %s <%s>", ERROR_MEMORY, x.what( ) );
+         return CKR_DEVICE_MEMORY;
+      }
+   }
+
+   {
+      DirectoryNotFoundException * e = dynamic_cast<DirectoryNotFoundException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## DirectoryNotFoundException <%s>", x.what( ) );
+         return CKR_TOKEN_NOT_RECOGNIZED;
+      }
+   }
+   {
+      FileNotFoundException * e = dynamic_cast<FileNotFoundException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## FileNotFoundException <%s>", x.what( ) );
+         return CKR_TOKEN_NOT_RECOGNIZED;
+      }
+   }
+   {
+      IOException * e = dynamic_cast<IOException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## IOException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      RemotingException * e = dynamic_cast<RemotingException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## RemotingException <%s>", x.what( ) );
+         return CKR_TOKEN_NOT_PRESENT;
+      }
+   }
+
+   {
+      CryptographicException * e = dynamic_cast<CryptographicException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## CryptographicException <%s>", x.what( ) );
+         return CKR_DEVICE_MEMORY;
+      }
+   }
+
+   {
+      SystemException * e = dynamic_cast<SystemException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## SystemException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArgumentException * e = dynamic_cast<ArgumentException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArgumentException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArgumentNullException * e = dynamic_cast<ArgumentNullException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArgumentNullException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArgumentOutOfRangeException * e = dynamic_cast<ArgumentOutOfRangeException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArgumentOutOfRangeException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      IndexOutOfRangeException * e = dynamic_cast<IndexOutOfRangeException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## IndexOutOfRangeException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      InvalidCastException * e = dynamic_cast<InvalidCastException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## InvalidCastException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      InvalidOperationException * e = dynamic_cast<InvalidOperationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## InvalidOperationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      NotImplementedException * e = dynamic_cast<NotImplementedException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## NotImplementedException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      NotSupportedException * e = dynamic_cast<NotSupportedException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## NotSupportedException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      NullReferenceException * e = dynamic_cast<NullReferenceException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## NullReferenceException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ObjectDisposedException * e = dynamic_cast<ObjectDisposedException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ObjectDisposedException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ApplicationException * e = dynamic_cast<ApplicationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ApplicationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArithmeticException * e = dynamic_cast<ArithmeticException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArithmeticException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      ArrayTypeMismatchException * e = dynamic_cast<ArrayTypeMismatchException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## ArrayTypeMismatchException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      BadImageFormatException * e = dynamic_cast<BadImageFormatException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## BadImageFormatException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      DirectoryNotFoundException * e = dynamic_cast<DirectoryNotFoundException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## DirectoryNotFoundException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      DivideByZeroException * e = dynamic_cast<DivideByZeroException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## DivideByZeroException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      FormatException * e = dynamic_cast<FormatException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## FormatException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      RankException * e = dynamic_cast<RankException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## RankException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      RemotingException * e = dynamic_cast<RemotingException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## RemotingException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      StackOverflowException * e = dynamic_cast<StackOverflowException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## StackOverflowException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      TypeLoadException * e = dynamic_cast<TypeLoadException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## TypeLoadException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MemberAccessException * e = dynamic_cast<MemberAccessException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MemberAccessException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MissingFieldException * e = dynamic_cast<MissingFieldException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MissingFieldException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MissingMemberException * e = dynamic_cast<MissingMemberException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MissingMemberException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      MissingMethodException * e = dynamic_cast<MissingMethodException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## MissingMethodException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      OverflowException * e = dynamic_cast<OverflowException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## OverflowException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      SecurityException * e = dynamic_cast<SecurityException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## SecurityException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      VerificationException * e = dynamic_cast<VerificationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## VerificationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+   {
+      SerializationException * e = dynamic_cast<SerializationException *>( &x );
+      if(e)
+      {
+         Log::log( "CheckMarshallerException", "## Error ## SerializationException <%s>", x.what( ) );
+         return CKR_DEVICE_ERROR;
+      }
+   }
+
+   return CKR_FUNCTION_FAILED;
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,62 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_error_h
+#define _include_error_h
+
+#include <string>
+#include <stdexcept>
+#include "cardmoduleservice.h"
+#include "platconfig.h"
+#include "Except.h"
+
+class PcscError : public std::runtime_error
+{
+public:
+    PcscError() : std::runtime_error(""), _err(0) {}
+    PcscError(unsigned long err) : std::runtime_error(""), _err(err) {}
+    PcscError(const std::string & message, unsigned long err = 0) : std::runtime_error(message), _err(err) {}
+
+    unsigned long Error() const {return _err;}
+
+private:
+    unsigned long _err;
+
+};
+
+
+class CkError : public std::runtime_error
+{
+public:
+    CkError() : std::runtime_error(""), _err(0) {}
+    CkError(CK_RV err) : std::runtime_error(""), _err(err) {}
+    CkError(const std::string & message, unsigned long err = 0) : std::runtime_error(message), _err(err) {}
+
+    CK_RV Error() const {return _err;}
+
+    static CK_RV CheckMarshallerException( Marshaller::Exception & x );
+
+private:
+    unsigned long _err;
+
+};
+
+#endif // _include_error_h
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,141 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+//#include "dbg.h"
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/time.h>
+#endif
+#include "event.h"
+
+CEvent::CEvent(CK_ULONG timeOut)
+{
+	#ifdef WIN32
+    m_eventHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
+    #else
+    pthread_mutex_init(&m_Mutex,0);
+    pthread_cond_init(&m_Condition,0);
+    #endif
+    m_timeOut     = timeOut;
+}
+
+CEvent::~CEvent(void)
+{
+	#ifdef WIN32
+    CloseHandle(m_eventHandle);
+    #else
+    pthread_mutex_destroy(&m_Mutex);
+    pthread_cond_destroy(&m_Condition);
+    #endif
+}
+
+void CEvent::Signal()
+{
+	#ifdef WIN32
+
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    PulseEvent(m_eventHandle);
+
+    #else
+
+    if(pthread_cond_broadcast(&m_Condition) == 0)
+    {
+    	//assert(FALSE);
+    }
+
+    #endif
+
+}
+
+void CEvent::Set()
+{
+	#ifdef WIN32
+
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    SetEvent(m_eventHandle);
+
+    #else
+
+    if(pthread_cond_signal( &m_Condition ) != 0)
+    {
+    	//assert(FALSE);
+    }
+
+
+    #endif
+}
+
+void CEvent::Reset()
+{
+	#ifdef WIN32
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    ResetEvent(m_eventHandle);
+    #endif
+}
+
+void CEvent::Wait()
+{
+	#ifdef WIN32
+    if(!m_eventHandle)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    DWORD rv = WaitForSingleObject(m_eventHandle,m_timeOut);
+
+    if(rv == WAIT_TIMEOUT)
+        assert(FALSE);  // throw CError(CKR_FUNCTION_FAILED);
+
+    #else
+
+    struct timeval CurrTime;
+
+    gettimeofday(&CurrTime, NULL);
+
+    timespec Abstime;
+
+    // Calculate absolute time to time out.
+
+    Abstime.tv_sec = CurrTime.tv_sec + m_timeOut/1000;
+    Abstime.tv_nsec = CurrTime.tv_usec*1000 + (m_timeOut % 1000)*1000000;
+
+    if(Abstime.tv_nsec>999999999) {
+        Abstime.tv_sec++;
+        Abstime.tv_nsec -= 1000000000;
+    }
+
+    if(pthread_cond_timedwait(&m_Condition,&m_Mutex,&Abstime) == 0)
+    {
+    	//assert(FALSE);
+    }
+
+    #endif
+}
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,57 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_event_h
+#define _include_event_h
+
+#ifdef INCLUDE_EVENTING
+
+class CEvent
+{
+
+private:
+    #ifdef WIN32
+    HANDLE      m_eventHandle;
+    #else
+    pthread_mutex_t m_Mutex;
+    pthread_cond_t  m_Condition;
+    #endif
+    CK_ULONG    m_timeOut;
+
+public:
+    CEvent(CK_ULONG timeOut);
+    ~CEvent(void);
+
+    void Signal(void);
+    void Set(void);
+    void Reset(void);
+    void Wait(void);  // Throws CK_RV exception on error
+
+    #ifdef WIN32
+    HANDLE GetHandle() { return m_eventHandle;}
+    #endif
+};
+
+extern CEvent CryptokiEvent;
+
+#endif
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,258 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "keyobject.h"
+
+KeyObject::KeyObject() : StorageObject()
+{
+    this->_keyType          = 0;
+    this->_id               = NULL_PTR;
+    this->_startDate        = NULL_PTR;
+    this->_endDate          = NULL_PTR;
+    this->_allowedMechanism = NULL_PTR;
+
+    this->_local         = CK_FALSE;
+    this->_mechanismType = CK_UNAVAILABLE_INFORMATION;//-1;
+}
+
+KeyObject::~KeyObject()
+{
+    if(this->_startDate != NULL_PTR){
+        delete this->_startDate;
+    }
+
+    if(this->_endDate != NULL_PTR){
+        delete this->_endDate;
+    }
+
+    if(this->_id != NULL_PTR){
+        delete this->_id;
+    }
+}
+
+CK_BBOOL KeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type)
+    {
+        case CKA_KEY_TYPE:
+            return (this->_keyType == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_ID:
+            return Util::CompareU1Arrays(this->_id,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_START_DATE:
+            return Util::CompareU1Arrays(this->_startDate,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_END_DATE:
+            return Util::CompareU1Arrays(this->_endDate,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_LOCAL:
+            return (this->_local == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_DERIVE:
+            return (this->_derive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_MECHANISM_TYPE:
+            return (this->_mechanismType == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_ALLOWED_MECHANISMS:
+            return Util::CompareU4Arrays(this->_allowedMechanism,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return StorageObject::Compare(attribute);
+
+    }
+}
+
+CK_RV KeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_KEY_TYPE:
+            case CKA_LOCAL:
+            case CKA_MECHANISM_TYPE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+
+        case CKA_KEY_TYPE:
+            {
+                CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_keyType = utemp;}
+            }
+            break;
+
+        case CKA_ID:
+            if(this->_id != NULL_PTR){
+                delete this->_id;
+            }
+            this->_id = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_START_DATE:
+            {
+                u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_startDate != NULL_PTR){
+                        delete this->_startDate;
+                    }
+                    this->_startDate = dtemp;
+                }
+            }
+            break;
+
+        case CKA_END_DATE:
+           {
+                u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_endDate != NULL_PTR){
+                        delete this->_endDate;
+                    }
+                    this->_endDate = dtemp;
+                }
+            }
+            break;
+
+        case CKA_LOCAL:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_local = btemp; }
+            }
+            break;
+
+        case CKA_DERIVE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_derive = btemp; }
+            }
+            break;
+
+        case CKA_MECHANISM_TYPE:
+            {
+                CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_mechanismType = utemp;}
+            }
+            break;
+
+        case CKA_ALLOWED_MECHANISMS:
+            if(this->_allowedMechanism != NULL_PTR){
+                delete this->_allowedMechanism;
+            }
+            this->_allowedMechanism = new u4Array(attribute.ulValueLen/4);
+            memcpy((u1*)this->_allowedMechanism->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+            break;
+
+        default:
+            return StorageObject::SetAttribute(attribute,objCreation);
+
+    }
+
+    return rv;
+}
+
+CK_RV KeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type)
+    {
+        case CKA_KEY_TYPE:
+            return StorageObject::PutULongInAttribute(this->_keyType,attribute);
+
+        case CKA_ID:
+            return StorageObject::PutU1ArrayInAttribute(this->_id,attribute);
+
+        case CKA_START_DATE:
+            return StorageObject::PutU1ArrayInAttribute(this->_startDate,attribute);
+
+        case CKA_END_DATE:
+            return StorageObject::PutU1ArrayInAttribute(this->_endDate,attribute);
+
+        case CKA_LOCAL:
+            return StorageObject::PutBBoolInAttribute(this->_local,attribute);
+
+        case CKA_DERIVE:
+            return StorageObject::PutBBoolInAttribute(this->_derive,attribute);
+
+        case CKA_MECHANISM_TYPE:
+            return StorageObject::PutULongInAttribute(this->_mechanismType,attribute);
+
+        case CKA_ALLOWED_MECHANISMS:
+            return StorageObject::PutU4ArrayInAttribute(this->_allowedMechanism,attribute);
+
+        default:
+            return StorageObject::GetAttribute(attribute);
+    }
+}
+
+void KeyObject::Serialize(std::vector<u1> *to)
+{
+    StorageObject::Serialize(to);
+
+    Util::PushULongInVector(to,this->_keyType);
+
+    Util::PushByteArrayInVector(to,this->_id);
+
+    Util::PushByteArrayInVector(to,this->_startDate);
+
+    Util::PushByteArrayInVector(to,this->_endDate);
+
+    Util::PushBBoolInVector(to,this->_local);
+
+    Util::PushBBoolInVector(to,this->_derive);
+
+    Util::PushULongInVector(to,this->_mechanismType);
+
+    Util::PushIntArrayInVector(to,this->_allowedMechanism);
+}
+
+void KeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    StorageObject::Deserialize(from,idx);
+
+    this->_keyType = Util::ReadULongFromVector(from,idx);
+
+    this->_id = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_startDate = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_endDate = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_local = Util::ReadBBoolFromVector(from,idx);
+
+    this->_derive = Util::ReadBBoolFromVector(from,idx);
+
+    this->_mechanismType = Util::ReadULongFromVector(from,idx);
+
+    this->_allowedMechanism = Util::ReadIntArrayFromVector(from,idx);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,52 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_keyobject_h
+#define _include_keyobject_h
+
+#include "storageobject.h"
+
+class KeyObject : public StorageObject
+{
+public:
+    CK_ULONG    _keyType;
+    u1Array*    _id;
+    u1Array*    _startDate;
+    u1Array*    _endDate;
+    CK_BBOOL    _derive;
+    CK_BBOOL    _local;
+    CK_ULONG    _mechanismType;
+    u4Array*    _allowedMechanism;
+
+public:
+    KeyObject();
+    virtual ~KeyObject();
+
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,2182 @@
+
+/* ---------------- Gemalto Debug -------------- */
+
+
+#include <string.h>
+#include "log.h"
+
+
+// Define to unable if you want to activate trace into the code or at compilation time
+//#define __DEBUG_GEMALTO__
+
+#ifdef WIN32
+#include <windows.h>
+#define LOG_FILE_NAME "c:\\Gemalto.NET.PKCS11.log"
+#else
+#define LOG_FILE_NAME "/tmp/Gemalto.NET.PKCS11.log"
+#endif
+
+
+#define T_BOOL 0
+#define T_BYTES 1
+#define T_LONG 2
+#define T_KEY_TYPE 3
+#define T_CERTIFICATE_TYPE 4
+#define T_CLASS 5
+#define T_DATE 6
+#define T_KEY_GEN_MECHANISM 7
+#define T_UNKNOWN 8
+
+
+/* Log a message into the log file
+*/
+void Log::log( const char * format, ... )
+{
+#ifdef __DEBUG_GEMALTO__
+   // Try to open the file
+   FILE* pLog = fopen( LOG_FILE_NAME, "a" );
+   if( NULL == pLog )
+   {
+      // The file does not exit. Nothing to log
+      return;
+   }
+
+   // Write the message to the log file
+   va_list args;
+   va_start( args, format );
+   vfprintf( pLog, format, args );
+   va_end( args );
+   fprintf(pLog, "\n");
+
+#ifndef WIN32
+   // Write the message to stderr stream
+   va_start( args, format );
+	vfprintf( stderr, format, args );
+   va_end( args );
+	fprintf( stderr, "\n");
+#else
+   // Get the size of the buffer necessary to write the message
+   // The size must be extended to include the '\n' and the '\0' characters.
+   va_start( args, format );
+   size_t len = _vscprintf( format, args );
+   va_end( args );
+
+   // Allocate the buffer for the message
+   char *buffer = new char[ len + 2 ];
+   memset( buffer, '\0', len + 2 );
+
+   // Write the message into the buffer.
+   va_start( args, format );
+   vsprintf_s( buffer, len + 1, format, args );
+   va_end( args );
+   buffer[ len ] = '\n';
+
+   // Write the message to the console
+   OutputDebugString( buffer );
+
+   // Release the buffer
+   delete[] buffer;
+#endif
+
+   va_end( args );
+
+   // Close the file
+   fclose( pLog );
+#endif
+}
+
+/*
+
+#ifdef __DEBUG_GEMALTO__
+void Log::log( const char * format, ... )
+{
+   // Try to open the file
+   FILE* pLog = fopen( LOG_FILE_NAME, "a" );
+   if( NULL == pLog )
+   {
+      // The file does not exit. Nothing to log
+      return;
+   }
+
+   // Get the size of the buffer necessary to write the message
+   // The size must be extended to include the '\n' and the '\0' characters.
+   va_list args;
+   va_start( args, format );
+#ifdef WIN32
+   size_t len = _vscprintf( format, args );
+#else
+   char tmp[1];
+   int len = vsnprintf( tmp, sizeof(tmp), format, args );
+#endif
+   va_end( args );
+
+   // Allocate the buffer for the message
+   char *buffer = new char[ len + 2 ];
+   memset( buffer, '\0', len + 2 );
+
+   // Write the message into the buffer.
+   va_start( args, format );
+#ifdef WIN32
+   vsprintf_s( buffer, len + 1, format, args );
+#else
+   vsprintf( buffer, format, args );
+#endif
+   va_end( args );
+   buffer[ len ] = '\n';
+
+   // Write the message to the console
+#ifdef WIN32
+   OutputDebugString( buffer );
+#else
+   printf( buffer );
+#endif
+
+   // Write the message to the log file
+   fputs( buffer, pLog );
+   fflush( pLog );
+
+   // Close the file
+   fclose( pLog );
+
+   // Release the buffer
+   delete[] buffer;
+}
+#else
+void Log::log( const char*, ... )
+{
+}
+#endif
+*/
+
+
+
+/*
+*/
+void Log::begin( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - <BEGIN>", a_pMethod );
+#else
+	(void)a_pMethod;
+#endif
+}
+
+
+/*
+*/
+void Log::end( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - <END>", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::in( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - [IN]", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::out( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - [OUT]", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::error( const char* a_pMethod, const char* a_pError )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - ## Error ## %s", a_pMethod, a_pError );
+#endif
+}
+
+
+
+void Log::logCK_UTF8CHAR_PTR( const char* a_pName, const unsigned char* a_pBuffer, const std::size_t& a_Size )
+{
+#ifdef __DEBUG_GEMALTO__
+   std::string s = "";
+   if( NULL_PTR != a_pBuffer )
+   {
+      toString( a_pBuffer, a_Size, s );
+   }
+   log( "%s - <%#02x> - size <%ld> - buffer <%s>", a_pName, a_pBuffer, a_Size, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_INFO_PTR( const char* a_pMethod, CK_MECHANISM_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR != pInfo )
+	{
+	   std::string flags = "";
+	   CK_FLAGS f = pInfo->flags;
+	   mechanismFlagsToString( f, flags );
+
+      log( "%s - CK_MECHANISM_INFO - ulMinKeySize <%#02x> - ulMaxKeySize <%#02x> - flags <%s>", a_pMethod, pInfo->ulMinKeySize, pInfo->ulMaxKeySize, flags.c_str( ) );
+   }
+   else
+   {
+      log( "%s - CK_MECHANISM_INFO - NULL_PTR", a_pMethod );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_INFO( const char* a_pMethod, const CK_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR != pInfo )
+   {
+	   std::string s = "";
+	   CK_INFOToString( pInfo, s );
+      log( "%s - CK_INFO <%s>", a_pMethod, s.c_str( ) );
+   }
+   else
+   {
+      log( "%s - CK_INFO <NULL_PTR>", a_pMethod );
+   }
+#endif
+}
+
+
+void Log::logCK_RV( const char* a_pMethod, const CK_RV& rv )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( CKR_OK == rv )
+   {
+      log( "%s - [RV] <0x00> (CKR_OK)", a_pMethod );
+   }
+   else
+  {
+      std::string s = "";
+      CK_RVToString( rv, s );
+      log( "%s - [RV] <%#02x> (%s)", a_pMethod, rv, s.c_str( ) );
+   }
+#endif
+}
+
+
+void Log::logCK_C_INITIALIZE_ARGS_PTR( const char* a_pMethod, CK_C_INITIALIZE_ARGS_PTR a_pArgs )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR != a_pArgs )
+   {
+		//log( a_pMethod, "pInitArgs->CreateMutex <%#02x>", a_pArgs.CreateMutex );
+		log( "%s - CK_C_INITIALIZE_ARGS - DestroyMutex <%#02x> - LockMutex <%#02x> - UnlockMutex <%#02x> - flags <%#02x> - pReserved <%#02x>",
+         a_pMethod, a_pArgs->DestroyMutex, a_pArgs->LockMutex, a_pArgs->UnlockMutex, a_pArgs->flags, a_pArgs->pReserved );
+   }
+   else
+   {
+		log( "%s - CK_C_INITIALIZE_ARGS - CreateMutex <NULL_PTR> - DestroyMutex <NULL_PTR> - LockMutex <NULL_PTR> - UnlockMutex <NULL_PTR> - flags <NULL_PTR> - pReserved <NULL_PTR>", a_pMethod );
+   }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_SLOT_ID_PTR( const char* a_pMethod, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR == pSlotList )
+   {
+      log( "%s - CK_SLOT_ID_PTR - pulCount <%#02x> (%ld) - pSlotList <NULL_PTR>", a_pMethod, pulCount, ( NULL_PTR != pulCount ) ? *pulCount : 0 );
+   }
+   else
+   {
+      std::string sList = "";
+      if( NULL_PTR != pulCount )
+      {
+	      for( size_t i = 0 ; i < (size_t)*pulCount ; i++ )
+	      {
+		      std::string s = "";
+		      toString( (unsigned long) pSlotList[ i ], s );
+		      sList += s;
+		      if( i != (size_t)( *pulCount - 1 ) )
+		      {
+			      sList += ", " ;
+		      }
+	      }
+      }
+      log( "%s - CK_SLOT_ID_PTR - pulCount <%#02x> (%ld) - pSlotList <%#02x> (%s)", a_pMethod, pulCount, ( NULL_PTR != pulCount ) ? *pulCount : 0, pSlotList, sList.c_str( ) );
+   }
+#endif
+}
+
+
+void Log::logCK_SLOT_INFO_PTR( const char* a_pMethod, CK_SLOT_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR != pInfo )
+	{
+	   std::string slotDescription = "";
+	   toString( pInfo->slotDescription, 64, slotDescription );
+
+	   std::string manufacturerID = "";
+	   toString( pInfo->manufacturerID, 32, manufacturerID );
+
+	   std::string flags = "";
+	   CK_FLAGS f = pInfo->flags;
+	   slotFlagsToString( f, flags );
+
+	   std::string hardwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->hardwareVersion), hardwareVersion );
+
+	   std::string firmwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->firmwareVersion), firmwareVersion );
+
+      log( "%s - CK_SLOT_INFO_PTR - slotDescription <%s> - manufacturerID <%s> - flags <%s> - hardwareVersion <%s> - firmwareVersion <%s>",
+		   a_pMethod, slotDescription.c_str( ), manufacturerID.c_str( ), flags.c_str( ), hardwareVersion.c_str( ), firmwareVersion.c_str( ) );
+   }
+   else
+   {
+      log( "%s - CK_SLOT_INFO_PTR - NULL_PTR", a_pMethod );
+   }
+#endif
+}
+
+
+void Log::logCK_TOKEN_INFO_PTR( const char* a_pMethod, CK_TOKEN_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+   if( NULL_PTR != pInfo )
+	{
+	   std::string label = "";
+	   toString( pInfo->label, 32, label );
+
+	   std::string manufacturerID = "";
+	   toString( pInfo->manufacturerID, 32, manufacturerID );
+
+	   std::string model = "";
+	   toString( pInfo->model, 16, model );
+
+	   std::string serialNumber = "";
+	   toString( pInfo->serialNumber, 16, serialNumber );
+
+	   std::string hardwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->hardwareVersion), hardwareVersion );
+
+	   std::string firmwareVersion = "";
+	   CK_VERSIONToString( &(pInfo->firmwareVersion), firmwareVersion );
+
+	   std::string utcTime = "";
+	   toString( pInfo->utcTime, 16, utcTime );
+
+	   log( "%s - CK_TOKEN_INFO_PTR - <%#02x> - label <%s> - manufacturerID <%s> - model <%s> - serialNumber <%s> - flags <%#02x> - ulMaxSessionCount <%#02x> - ulSessionCount <%#02x> - \
+		   ulMaxRwSessionCount <%#02x> - ulRwSessionCount <%#02x> - ulMaxPinLen <%#02x> - ulMinPinLen <%#02x> - ulTotalPublicMemory <%#02x> - \
+		   ulFreePublicMemory <%#02x> - ulTotalPrivateMemory <%#02x> - ulFreePrivateMemory <%#02x> - hardwareVersion <%s> - \
+		   firmwareVersion <%s> - utcTime <%s>",
+		   a_pMethod,
+         pInfo,
+         label.c_str( ),
+		   manufacturerID.c_str( ),
+		   model.c_str( ),
+		   serialNumber.c_str( ),
+		   pInfo->flags,
+		   pInfo->ulMaxSessionCount,
+		   pInfo->ulSessionCount,
+		   pInfo->ulMaxRwSessionCount,
+		   pInfo->ulRwSessionCount,
+		   pInfo->ulMaxPinLen,
+		   pInfo->ulMinPinLen,
+		   pInfo->ulTotalPublicMemory,
+		   pInfo->ulFreePublicMemory,
+		   pInfo->ulTotalPrivateMemory,
+		   pInfo->ulFreePrivateMemory,
+		   hardwareVersion.c_str( ),
+		   firmwareVersion.c_str( ),
+		   utcTime.c_str( ) );
+	}
+   else
+   {
+      log( "%s - CK_TOKEN_INFO_PTR - <NULL_PTR>", a_pMethod );
+   }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_TYPE( const char* a_pMethod, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+   std::string s = "";
+   if( ( NULL_PTR != pMechanismList ) && ( NULL_PTR != pulCount ) )
+   {
+		CK_MECHANISM_TYPEToString( pMechanismList, *pulCount, s );
+	}
+   log( "%s - CK_MECHANISM_TYPE_PTR - pulCount <%#02x> (%ld) - pMechanismList <%#02x> (%s)", a_pMethod, pulCount, ( ( NULL_PTR != pulCount ) ? *pulCount : 0 ), pMechanismList, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_TYPE( const char* a_pMethod, CK_MECHANISM_TYPE & ulMechanism )
+{
+#ifdef __DEBUG_GEMALTO__
+   std::string s = "";
+	CK_MECHANISM_TYPEToString( ulMechanism, s );
+   log( "%s - CK_MECHANISM_TYPE <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logSessionFlags( const char* a_pMethod, CK_FLAGS & flags )
+{
+#ifdef __DEBUG_GEMALTO__
+	std::string s = "";
+	sessionFlagsToString( flags, s );
+	log( "%s - CK_FLAGS <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_SESSION_INFO_PTR( const char* a_pMethod, CK_SESSION_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR != pInfo )
+   {
+      std::string s = "";
+	   CK_SESSION_INFOToString( pInfo, s );
+	   log( "%s - CK_SESSION_INFO <%#02x> (%s)", a_pMethod, pInfo, s.c_str( ) );
+   }
+   else
+	{
+	   log( "%s - CK_SESSION_INFO <NULL_PTR>", a_pMethod );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_USER_TYPE( const char* a_pMethod, CK_USER_TYPE &userType )
+{
+#ifdef __DEBUG_GEMALTO__
+	std::string s = "";
+	CK_USER_TYPEToString( userType, s );
+	log( "%s - CK_USER_TYPE <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_PTR( const char* a_pMethod, CK_MECHANISM_PTR pMechanism )
+{
+#ifdef __DEBUG_GEMALTO__
+	std::string s = "";
+   CK_MECHANISMToString( pMechanism, s );
+	log( "%s - CK_MECHANISM_PTR <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_ATTRIBUTE_PTR( const char* a_pMethod, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG& ulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+   log( "%s - pTemplate <%#02x> - ulCount <%ld>", a_pMethod, pTemplate, ulCount );
+	if( NULL_PTR != pTemplate )
+	{
+	   for( size_t i = 0; i < (size_t)ulCount; i++ )
+	   {
+		   CK_ATTRIBUTE a = pTemplate[ i ];
+		   std::string attribute = "";
+		   CK_ATTRIBUTEToString( &a, attribute );
+
+         log( "%s	- Attribute #%d - %s", a_pMethod, i, attribute.c_str( ) );
+	   }
+   }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISMToString( CK_MECHANISM_PTR m, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == m )
+	{
+		return;
+	}
+
+	std::string mechanismType = "";
+	CK_MECHANISM_TYPE t = m->mechanism;
+	CK_MECHANISM_TYPEToString( t, mechanismType );
+
+	std::string mechanismParam = "";
+	toString( (const unsigned char*)m->pParameter, m->ulParameterLen, mechanismParam );
+
+	toString( result,
+		"Type <%s> - Parameter <%s> - ParameterLen <%#02x>",
+		mechanismType.c_str( ),
+		mechanismParam.c_str( ),
+		m->ulParameterLen );
+#endif
+}
+
+
+void Log::CK_ATTRIBUTEToString( const CK_ATTRIBUTE_PTR a, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == a )
+	{
+		return;
+	}
+
+	std::string t = "";
+	int type = T_UNKNOWN;
+	CK_ATTRIBUTE_TYPEToString( a->type, t, type );
+
+	if( ( (CK_ULONG)(-1) ) == a->ulValueLen )
+	{
+		toString( result, "Type <%s> - Length <-1> - Value <UNKNOWN>", t.c_str( ) );
+		return;
+	}
+
+	std::string v = "";
+	if( NULL_PTR == a->pValue )
+	{
+		v = "null";
+	}
+	else
+	{
+		switch( type )
+		{
+		case T_BOOL:
+			toString( ((bool*)a->pValue)[0], v );
+			break;
+
+		case T_BYTES:
+			toString( (CK_BYTE_PTR) a->pValue, a->ulValueLen, v );
+			break;
+
+		case T_LONG:
+			toString( ((CK_ULONG*)a->pValue)[0], v );
+			break;
+
+		case T_KEY_TYPE:
+			CK_KEY_TYPEToString( ((CK_KEY_TYPE *)a->pValue)[0], v );
+			break;
+
+		case T_CERTIFICATE_TYPE:
+			CK_CERTIFICATE_TYPEToString( ((CK_CERTIFICATE_TYPE *)a->pValue)[0], v );
+			break;
+
+		case T_CLASS:
+			CK_OBJECT_CLASSToString( ((CK_OBJECT_CLASS *)a->pValue)[0], v );
+			break;
+
+		case T_DATE:
+			CK_DATEToString( (CK_DATE*) a->pValue, v );
+			break;
+
+		case T_KEY_GEN_MECHANISM:
+			CK_MECHANISM_TYPEToString( ((CK_MECHANISM_TYPE *)a->pValue)[0], v );
+			break;
+
+		default:
+			v = "UNPREDICTABLE VALUE";
+		}
+	}
+
+	toString( result, "Type <%s> - Length <%#02x> - Value <%s>", t.c_str( ), a->ulValueLen, v.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::CK_ATTRIBUTE_TYPEToString( const CK_ATTRIBUTE_TYPE& a, std::string &t, int& type )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( a )
+	{
+	case CKA_CLASS:
+		t = "CKA_CLASS";
+		type = T_CLASS;
+		break;
+
+	case CKA_TOKEN:
+		t = "CKA_TOKEN";
+		type = T_BOOL;
+		break;
+
+	case CKA_PRIVATE:
+		t = "CKA_PRIVATE";
+		type = T_BOOL;
+		break;
+
+	case CKA_LABEL:
+		t = "CKA_LABEL";
+		type = T_BYTES;
+		break;
+
+	case CKA_APPLICATION:
+		t = "CKA_APPLICATION";
+		type = T_BYTES;
+		break;
+
+	case CKA_VALUE:
+		t = "CKA_VALUE";
+		type = T_BYTES;
+		break;
+
+	case CKA_CERTIFICATE_TYPE:
+		t = "CKA_CERTIFICATE_TYPE";
+		type = T_CERTIFICATE_TYPE;
+		break;
+
+	case CKA_ISSUER:
+		t = "CKA_ISSUER";
+		type = T_BYTES;
+		break;
+
+	case CKA_SERIAL_NUMBER:
+		t = "CKA_SERIAL_NUMBER";
+		type = T_BYTES;
+		break;
+
+	case CKA_KEY_TYPE:
+		t = "CKA_KEY_TYPE";
+		type = T_KEY_TYPE;
+		break;
+
+	case CKA_SUBJECT:
+		t = "CKA_SUBJECT";
+		type = T_BYTES;
+		break;
+
+	case CKA_ID:
+		t = "CKA_ID";
+		type = T_BYTES;
+		break;
+
+	case CKA_SENSITIVE:
+		t = "CKA_SENSITIVE";
+		type = T_BOOL;
+		break;
+
+	case CKA_ENCRYPT:
+		t = "CKA_ENCRYPT";
+		type = T_BOOL;
+		break;
+
+	case CKA_DECRYPT:
+		t = "CKA_DECRYPT";
+		type = T_BOOL;
+		break;
+
+	case CKA_WRAP:
+		t = "CKA_WRAP";
+		type = T_BOOL;
+		break;
+
+	case CKA_UNWRAP:
+		t = "CKA_UNWRAP";
+		type = T_BOOL;
+		break;
+
+	case CKA_SIGN:
+		t = "CKA_SIGN";
+		type = T_BOOL;
+		break;
+
+	case CKA_SIGN_RECOVER:
+		t = "CKA_SIGN_RECOVER";
+		type = T_BOOL;
+		break;
+
+	case CKA_VERIFY:
+		t = "CKA_VERIFY";
+		type = T_BOOL;
+		break;
+
+	case CKA_VERIFY_RECOVER:
+		t = "CKA_VERIFY_RECOVER";
+		type = T_BOOL;
+		break;
+
+	case CKA_DERIVE:
+		t = "CKA_DERIVE";
+		type = T_BOOL;
+		break;
+
+	case CKA_START_DATE:
+		t = "CKA_START_DATE";
+		type = T_DATE;
+		break;
+
+	case CKA_END_DATE:
+		t = "CKA_END_DATE";
+		type = T_DATE;
+		break;
+
+	case CKA_MODULUS:
+		t = "CKA_MODULUS";
+		type = T_BYTES;
+		break;
+
+	case CKA_MODULUS_BITS:
+		t = "CKA_MODULUS_BITS";
+		type = T_LONG;
+		break;
+
+	case CKA_PUBLIC_EXPONENT:
+		t = "CKA_PUBLIC_EXPONENT";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIVATE_EXPONENT:
+		t = "CKA_PRIVATE_EXPONENT";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIME_1:
+		t = "CKA_PRIME_1";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIME_2:
+		t = "CKA_PRIME_2";
+		type = T_BYTES;
+		break;
+
+	case CKA_EXPONENT_1:
+		t = "CKA_EXPONENT_1";
+		type = T_BYTES;
+		break;
+
+	case CKA_EXPONENT_2:
+		t = "CKA_EXPONENT_2";
+		type = T_BYTES;
+		break;
+
+	case CKA_COEFFICIENT:
+		t = "CKA_COEFFICIENT";
+		type = T_BYTES;
+		break;
+
+	case CKA_PRIME:
+		t = "CKA_PRIME";
+		type = T_BYTES;
+		break;
+
+	case CKA_SUBPRIME:
+		t = "CKA_SUBPRIME";
+		type = T_BYTES;
+		break;
+
+	case CKA_BASE:
+		t = "CKA_BASE";
+		type = T_BYTES;
+		break;
+
+	case CKA_VALUE_BITS:
+		t = "CKA_VALUE_BITS";
+		type = T_BYTES;
+		break;
+
+	case CKA_VALUE_LEN:
+		t = "CKA_VALUE_LEN";
+		type = T_LONG;
+		break;
+
+	case CKA_EXTRACTABLE:
+		t = "CKA_EXTRACTABLE";
+		type = T_BOOL;
+		break;
+
+	case CKA_LOCAL:
+		t = "CKA_LOCAL";
+		type = T_BOOL;
+		break;
+
+	case CKA_NEVER_EXTRACTABLE:
+		t = "CKA_NEVER_EXTRACTABLE";
+		type = T_BOOL;
+		break;
+
+	case CKA_ALWAYS_SENSITIVE:
+		t = "CKA_ALWAYS_SENSITIVE";
+		type = T_BOOL;
+		break;
+
+	case CKA_MODIFIABLE:
+		t = "CKA_MODIFIABLE";
+		type = T_BOOL;
+		break;
+
+	case CKA_ECDSA_PARAMS:
+		t = "CKA_ECDSA_PARAMS";
+		type = T_BYTES;
+		break;
+
+	case CKA_EC_POINT:
+		t = "CKA_EC_POINT";
+		type = T_BYTES;
+		break;
+
+	case CKA_VENDOR_DEFINED:
+		t = "CKA_VENDOR_DEFINED";
+		type = T_BYTES;
+		break;
+
+		//case CKA_KEY_GEN_MECHANISM:
+		//	t = "CKA_KEY_GEN_MECHANISM";
+		//	type = T_KEY_GEN_MECHANISM;
+		//	break;
+
+	default:
+		toString( t, "UNKNOWN TYPE <%#02x>", a );
+		type = T_UNKNOWN;
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_DATEToString( const CK_DATE* t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == t )
+	{
+		return;
+	}
+
+	std::string year = "";
+	toString( t->year, 4, year );
+
+	std::string month = "";
+	toString( t->month, 2, month );
+
+	std::string day = "";
+	toString( t->day, 2, day );
+
+	result = "Year <" + year + "> - Month <" + month + "> - Day <" + day + ">";
+#endif
+}
+
+
+/*
+*/
+void Log::CK_OBJECT_CLASSToString( const CK_OBJECT_CLASS& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKO_DATA:
+		result = "CKO_DATA";
+		break;
+
+	case CKO_CERTIFICATE:
+		result = "CKO_CERTIFICATE";
+		break;
+
+	case CKO_PUBLIC_KEY:
+		result = "CKO_PUBLIC_KEY";
+		break;
+
+	case CKO_PRIVATE_KEY:
+		result = "CKO_PRIVATE_KEY";
+		break;
+
+	case CKO_SECRET_KEY:
+		result = "CKO_SECRET_KEY";
+		break;
+
+	case CKO_VENDOR_DEFINED:
+		result = "CKO_VENDOR_DEFINED";
+		break;
+
+	default:
+		toString( result, "UNKNOWN OBJECT CLASS <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_KEY_TYPEToString( const CK_KEY_TYPE& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKK_RSA:
+		result = "CKK_RSA";
+		break;
+
+	case CKK_DSA:
+		result = "CKK_DSA";
+		break;
+
+	case CKK_ECDSA:
+		result = "CKK_ECDSA";
+		break;
+
+	case CKK_DH:
+		result = "CKK_DH";
+		break;
+
+	case CKK_KEA:
+		result = "CKK_KEA";
+		break;
+
+	case CKK_GENERIC_SECRET:
+		result = "CKK_GENERIC_SECRET";
+		break;
+
+	case CKK_RC2:
+		result = "CKK_RC2";
+		break;
+
+	case CKK_RC4:
+		result = "CKK_RC4";
+		break;
+
+	case CKK_DES:
+		result = "CKK_DES";
+		break;
+
+	case CKK_DES2:
+		result = "CKK_DES2";
+		break;
+
+	case CKK_DES3:
+		result = "CKK_DES3";
+		break;
+
+	case CKK_CAST:
+		result = "CKK_CAST";
+		break;
+
+	case CKK_CAST3:
+		result = "CKK_CAST3";
+		break;
+
+	case CKK_CAST5:
+		result = "CKK_CAST5/128";
+		break;
+
+	case CKK_RC5:
+		result = "CKK_RC5";
+		break;
+
+	case CKK_IDEA:
+		result = "CKK_IDEA";
+		break;
+
+	case CKK_SKIPJACK:
+		result = "CKK_SKIPJACK";
+		break;
+
+	case CKK_BATON:
+		result = "CKK_BATON";
+		break;
+
+	case CKK_JUNIPER:
+		result = "CKK_JUNIPER";
+		break;
+
+	case CKK_CDMF:
+		result = "CKK_CDMF";
+		break;
+
+	case CKK_VENDOR_DEFINED:
+		result = "CKK_VENDOR_DEFINED";
+		break;
+
+	default:
+		toString( result, "UNKNOWN KEY TYPE <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_CERTIFICATE_TYPEToString( const CK_CERTIFICATE_TYPE &t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKC_X_509:
+		result = "CKC_X_509";
+		break;
+
+	case CKC_VENDOR_DEFINED:
+		result = "CKC_VENDOR_DEFINED";
+		break;
+
+	default:
+		toString( result, "UNKNOWN CERTIFICATE TYPE <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_INFOToString( CK_INFO_PTR pInfo, std::string& result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pInfo )
+	{
+		return;
+	}
+
+	std::string cryptokiVersion = "";
+	CK_VERSIONToString( &(pInfo->cryptokiVersion), cryptokiVersion );
+
+	std::string manufacturerID = "";
+	toString( pInfo->manufacturerID, 32, manufacturerID );
+
+	std::string flags = "";
+	CK_FLAGS f = pInfo->flags;
+	toString( f, flags );
+
+	std::string libraryDescription = "";
+	toString( pInfo->libraryDescription, 32, libraryDescription );
+
+	std::string libraryVersion = "";
+	CK_VERSIONToString( &(pInfo->libraryVersion), libraryVersion );
+
+	result = "cryptokiVersion <" + cryptokiVersion
+		+ "> - manufacturerID <" + manufacturerID
+		+ "> - flags <" + flags
+		+ "> - libraryDescription <" + libraryDescription
+		+ "> - libraryVersion <" + libraryVersion
+		+ ">";
+#endif
+}
+
+
+/*
+*/
+void Log::CK_RVToString( const CK_RV& rv, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( rv )
+	{
+	case CKR_OK:
+		result = "CKR_OK";
+		break;
+	case CKR_CANCEL:
+		result = "CKR_CANCEL";
+		break;
+	case CKR_HOST_MEMORY:
+		result = "CKR_HOST_MEMORY";
+		break;
+	case CKR_SLOT_ID_INVALID:
+		result = "CKR_SLOT_ID_INVALID";
+		break;
+	case CKR_GENERAL_ERROR:
+		result = "CKR_GENERAL_ERROR";
+		break;
+	case CKR_FUNCTION_FAILED:
+		result = "CKR_FUNCTION_FAILED";
+		break;
+	case CKR_ARGUMENTS_BAD:
+		result = "CKR_ARGUMENTS_BAD";
+		break;
+	case CKR_NO_EVENT:
+		result = "CKR_NO_EVENT";
+		break;
+	case CKR_NEED_TO_CREATE_THREADS:
+		result = "CKR_NEED_TO_CREATE_THREADS";
+		break;
+	case CKR_CANT_LOCK:
+		result = "CKR_CANT_LOCK";
+		break;
+	case CKR_ATTRIBUTE_READ_ONLY:
+		result = "CKR_ATTRIBUTE_READ_ONLY";
+		break;
+	case CKR_ATTRIBUTE_SENSITIVE:
+		result = "CKR_ATTRIBUTE_SENSITIVE";
+		break;
+	case CKR_ATTRIBUTE_TYPE_INVALID:
+		result = "CKR_ATTRIBUTE_TYPE_INVALID";
+		break;
+	case CKR_ATTRIBUTE_VALUE_INVALID:
+		result = "CKR_ATTRIBUTE_VALUE_INVALID";
+		break;
+	case CKR_DATA_INVALID:
+		result = "CKR_DATA_INVALID";
+		break;
+	case CKR_DATA_LEN_RANGE:
+		result = "CKR_DATA_LEN_RANGE";
+		break;
+	case CKR_DEVICE_ERROR:
+		result = "CKR_DEVICE_ERROR";
+		break;
+	case CKR_DEVICE_MEMORY:
+		result = "CKR_DEVICE_MEMORY";
+		break;
+	case CKR_DEVICE_REMOVED:
+		result = "CKR_DEVICE_REMOVED";
+		break;
+	case CKR_ENCRYPTED_DATA_INVALID:
+		result = "CKR_ENCRYPTED_DATA_INVALID";
+		break;
+	case CKR_ENCRYPTED_DATA_LEN_RANGE:
+		result = "CKR_ENCRYPTED_DATA_LEN_RANGE";
+		break;
+	case CKR_FUNCTION_CANCELED:
+		result = "CKR_FUNCTION_CANCELED";
+		break;
+	case CKR_FUNCTION_NOT_PARALLEL:
+		result = "CKR_FUNCTION_NOT_PARALLEL";
+		break;
+	case CKR_FUNCTION_NOT_SUPPORTED:
+		result = "CKR_FUNCTION_NOT_SUPPORTED";
+		break;
+	case CKR_KEY_HANDLE_INVALID:
+		result = "CKR_KEY_HANDLE_INVALID";
+		break;
+	case CKR_KEY_SIZE_RANGE:
+		result = "CKR_KEY_SIZE_RANGE";
+		break;
+	case CKR_KEY_TYPE_INCONSISTENT:
+		result = "CKR_KEY_TYPE_INCONSISTENT";
+		break;
+	case CKR_KEY_NOT_NEEDED:
+		result = "CKR_KEY_NOT_NEEDED";
+		break;
+	case CKR_KEY_CHANGED:
+		result = "CKR_KEY_CHANGED";
+		break;
+	case CKR_KEY_NEEDED:
+		result = "CKR_KEY_NEEDED";
+		break;
+	case CKR_KEY_INDIGESTIBLE:
+		result = "CKR_KEY_INDIGESTIBLE";
+		break;
+	case CKR_KEY_FUNCTION_NOT_PERMITTED:
+		result = "CKR_KEY_FUNCTION_NOT_PERMITTED";
+		break;
+	case CKR_KEY_NOT_WRAPPABLE:
+		result = "CKR_KEY_NOT_WRAPPABLE";
+		break;
+	case CKR_KEY_UNEXTRACTABLE:
+		result = "CKR_KEY_UNEXTRACTABLE";
+		break;
+	case CKR_MECHANISM_INVALID:
+		result = "CKR_MECHANISM_INVALID";
+		break;
+	case CKR_MECHANISM_PARAM_INVALID:
+		result = "CKR_MECHANISM_PARAM_INVALID";
+		break;
+	case CKR_OBJECT_HANDLE_INVALID:
+		result = "CKR_OBJECT_HANDLE_INVALID";
+		break;
+	case CKR_OPERATION_ACTIVE:
+		result = "CKR_OPERATION_ACTIVE";
+		break;
+	case CKR_OPERATION_NOT_INITIALIZED:
+		result = "CKR_OPERATION_NOT_INITIALIZED";
+		break;
+	case CKR_PIN_INCORRECT:
+		result = "CKR_PIN_INCORRECT";
+		break;
+	case CKR_PIN_INVALID:
+		result = "CKR_PIN_INVALID";
+		break;
+	case CKR_PIN_LEN_RANGE:
+		result = "CKR_PIN_LEN_RANGE";
+		break;
+	case CKR_PIN_EXPIRED:
+		result = "CKR_PIN_EXPIRED";
+		break;
+	case CKR_PIN_LOCKED:
+		result = "CKR_PIN_LOCKED";
+		break;
+	case CKR_SESSION_CLOSED:
+		result = "CKR_SESSION_CLOSED";
+		break;
+	case CKR_SESSION_COUNT:
+		result = "CKR_SESSION_COUNT";
+		break;
+	case CKR_SESSION_HANDLE_INVALID:
+		result = "CKR_SESSION_HANDLE_INVALID";
+		break;
+	case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
+		result = "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
+		break;
+	case CKR_SESSION_READ_ONLY:
+		result = "CKR_SESSION_READ_ONLY";
+		break;
+	case CKR_SESSION_EXISTS:
+		result = "CKR_SESSION_EXISTS";
+		break;
+	case CKR_SESSION_READ_ONLY_EXISTS:
+		result = "CKR_SESSION_READ_ONLY_EXISTS";
+		break;
+	case CKR_SESSION_READ_WRITE_SO_EXISTS:
+		result = "CKR_SESSION_READ_WRITE_SO_EXISTS";
+		break;
+	case CKR_SIGNATURE_INVALID:
+		result = "CKR_SIGNATURE_INVALID";
+		break;
+	case CKR_SIGNATURE_LEN_RANGE:
+		result = "CKR_SIGNATURE_LEN_RANGE";
+		break;
+	case CKR_TEMPLATE_INCOMPLETE:
+		result = "CKR_TEMPLATE_INCOMPLETE";
+		break;
+	case CKR_TEMPLATE_INCONSISTENT:
+		result = "CKR_TEMPLATE_INCONSISTENT";
+		break;
+	case CKR_TOKEN_NOT_PRESENT:
+		result = "CKR_TOKEN_NOT_PRESENT";
+		break;
+	case CKR_TOKEN_NOT_RECOGNIZED:
+		result = "CKR_TOKEN_NOT_RECOGNIZED";
+		break;
+	case CKR_TOKEN_WRITE_PROTECTED:
+		result = "CKR_TOKEN_WRITE_PROTECTED";
+		break;
+	case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
+		result = "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
+		break;
+	case CKR_UNWRAPPING_KEY_SIZE_RANGE:
+		result = "CKR_UNWRAPPING_KEY_SIZE_RANGE";
+		break;
+	case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
+		result = "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
+		break;
+	case CKR_USER_ALREADY_LOGGED_IN:
+		result = "CKR_USER_ALREADY_LOGGED_IN";
+		break;
+	case CKR_USER_NOT_LOGGED_IN:
+		result = "CKR_USER_NOT_LOGGED_IN";
+		break;
+	case CKR_USER_PIN_NOT_INITIALIZED:
+		result = "CKR_USER_PIN_NOT_INITIALIZED";
+		break;
+	case CKR_USER_TYPE_INVALID:
+		result = "CKR_USER_TYPE_INVALID";
+		break;
+	case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
+		result = "CKR_USER_ANOTHER_ALREADY_LOGGED_IN";
+		break;
+	case CKR_USER_TOO_MANY_TYPES:
+		result = "CKR_USER_TOO_MANY_TYPES";
+		break;
+	case CKR_WRAPPED_KEY_INVALID:
+		result = "CKR_WRAPPED_KEY_INVALID";
+		break;
+	case CKR_WRAPPED_KEY_LEN_RANGE:
+		result = "CKR_WRAPPED_KEY_LEN_RANGE";
+		break;
+	case CKR_WRAPPING_KEY_HANDLE_INVALID:
+		result = "CKR_WRAPPING_KEY_HANDLE_INVALID";
+		break;
+	case CKR_WRAPPING_KEY_SIZE_RANGE:
+		result = "CKR_WRAPPING_KEY_SIZE_RANGE";
+		break;
+	case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
+		result = "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
+		break;
+	case CKR_RANDOM_SEED_NOT_SUPPORTED:
+		result = "CKR_RANDOM_SEED_NOT_SUPPORTED";
+		break;
+	case CKR_RANDOM_NO_RNG:
+		result = "CKR_RANDOM_NO_RNG";
+		break;
+	case CKR_BUFFER_TOO_SMALL:
+		result = "CKR_BUFFER_TOO_SMALL";
+		break;
+	case CKR_SAVED_STATE_INVALID:
+		result = "CKR_SAVED_STATE_INVALID";
+		break;
+	case CKR_INFORMATION_SENSITIVE:
+		result = "CKR_INFORMATION_SENSITIVE";
+		break;
+	case CKR_STATE_UNSAVEABLE:
+		result = "CKR_STATE_UNSAVEABLE";
+		break;
+	case CKR_CRYPTOKI_NOT_INITIALIZED:
+		result = "CKR_CRYPTOKI_NOT_INITIALIZED";
+		break;
+	case CKR_CRYPTOKI_ALREADY_INITIALIZED:
+		result = "CKR_CRYPTOKI_ALREADY_INITIALIZED";
+		break;
+	case CKR_MUTEX_BAD:
+		result = "CKR_MUTEX_BAD";
+		break;
+	case CKR_MUTEX_NOT_LOCKED:
+		result = "CKR_MUTEX_NOT_LOCKED";
+		break;
+	case CKR_VENDOR_DEFINED:
+		result = "CKR_VENDOR_DEFINED";
+		break;
+	default:
+		toString( result, "UNKNOWN ERROR <%#02x>", rv );
+	}
+#endif
+}
+
+/*
+*/
+void Log::toString( std::string &result, const char * format, ... )
+{
+#ifdef __DEBUG_GEMALTO__
+	result = "";
+
+   // Get the size of the buffer necessary to write the message
+   // The size must be extended to include the '\n' and the '\0' characters.
+   va_list args;
+   va_start( args, format );
+#ifdef WIN32
+   size_t len = _vscprintf( format, args );
+#else
+   char tmp[1];
+   int len = vsnprintf( tmp, sizeof(tmp), format, args );
+#endif
+   va_end( args );
+
+   // Allocate the buffer for the message
+   char *buffer = new char[ len + 2 ];
+   memset( buffer, '\0', len + 2 );
+
+   // Write the message into the buffer.
+   va_start( args, format );
+#ifdef WIN32
+   vsprintf_s( buffer, len + 1, format, args );
+#else
+   vsprintf( buffer, format, args );
+#endif
+   va_end( args );
+
+   // Write the message to the string
+   result = buffer;
+
+   // Release the buffer
+   delete[] buffer;
+#endif
+}
+
+
+/*
+*/
+void Log::toString( const unsigned char* buffer, std::size_t size, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( ( NULL == buffer ) || ( 1 > size ) )
+	{
+		//result.assign( "null" );
+		return;
+	}
+
+    std::ostringstream oss;
+	oss.rdbuf( )->str( "" );
+
+    // Afficher en héxadécimal et en majuscule
+    oss << std::hex << std::uppercase;
+
+    // Remplir les blancs avec des zéros
+    oss << std::setfill('0');
+
+    for( std::size_t i = 0; i < size; ++i )
+    {
+        // Séparer chaque octet par un espace
+        if (i != 0)
+            oss << ' ';
+
+        // Afficher sa valeur hexadécimale précédée de "0x"
+        // setw(2) permet de forcer l'affichage à 2 caractères
+        oss << /*"0x" <<*/ std::setw(2) << static_cast<int>( buffer[i] );
+    }
+
+    result.assign( oss.str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::toString( const unsigned long &l, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	classtoString<unsigned long>( l, result );
+#endif
+}
+
+
+template<typename T> void Log::classtoString( const T & value, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL == &value )
+	{
+		return;
+	}
+	std::ostringstream str;
+	str << value;
+	result.assign( str.str( ) );
+#endif
+}
+
+
+void Log::slotFlagsToString( const CK_FLAGS& f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	result = "";
+
+	// Slot Information Flags
+	if( f & CKF_TOKEN_PRESENT )
+	{
+		result += "CKF_TOKEN_PRESENT";
+	}
+
+	if( f & CKF_REMOVABLE_DEVICE )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_REMOVABLE_DEVICE";
+	}
+
+	if( f & CKF_HW_SLOT )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_HW_SLOT";
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_VERSIONToString( CK_VERSION_PTR pVersion, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pVersion )
+	{
+		return;
+	}
+
+	toString( result, "%#02x - %#02x", pVersion->major, pVersion->minor );
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_TYPEToString( CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG mechanismListLen, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pMechanismList )
+	{
+		return;
+	}
+
+	result = "";
+
+	for( size_t i = 0 ; i < (size_t)mechanismListLen; i++ )
+	{
+		std::string m = "";
+		CK_MECHANISM_TYPEToString( pMechanismList[ i ], m );
+		result += m;
+		if( i != (size_t)( mechanismListLen - 1 ) )
+		{
+			result +=", ";
+		}
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_TYPEToString( const CK_MECHANISM_TYPE &t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKM_RSA_PKCS_KEY_PAIR_GEN:
+		result = "CKM_RSA_PKCS_KEY_PAIR_GEN";
+		break;
+	case CKM_RSA_PKCS:
+		result = "CKM_RSA_PKCS";
+		break;
+	case CKM_RSA_9796:
+		result = "CKM_RSA_9796";
+		break;
+	case CKM_RSA_X_509:
+		result = "CKM_RSA_X_509";
+		break;
+	case CKM_MD2_RSA_PKCS:
+		result = "CKM_MD2_RSA_PKCS";
+		break;
+	case CKM_MD5_RSA_PKCS:
+		result = "CKM_MD5_RSA_PKCS";
+		break;
+	case CKM_SHA1_RSA_PKCS:
+		result = "CKM_SHA1_RSA_PKCS";
+		break;
+	case CKM_DSA_KEY_PAIR_GEN:
+		result = "CKM_DSA_KEY_PAIR_GEN";
+		break;
+	case CKM_DSA:
+		result = "CKM_DSA";
+		break;
+	case CKM_DSA_SHA1:
+		result = "CKM_DSA_SHA1";
+		break;
+	case CKM_DH_PKCS_KEY_PAIR_GEN:
+		result = "CKM_DH_PKCS_KEY_PAIR_GEN";
+		break;
+	case CKM_DH_PKCS_DERIVE:
+		result = "CKM_DH_PKCS_DERIVE";
+		break;
+	case CKM_RC2_KEY_GEN:
+		result = "CKM_RC2_KEY_GEN";
+		break;
+	case CKM_RC2_ECB:
+		result = "CKM_RC2_ECB";
+		break;
+	case CKM_RC2_CBC:
+		result = "CKM_RC2_CBC";
+		break;
+	case CKM_RC2_MAC:
+		result = "CKM_RC2_MAC";
+		break;
+	case CKM_RC2_MAC_GENERAL:
+		result = "CKM_RC2_MAC_GENERAL";
+		break;
+	case CKM_RC2_CBC_PAD:
+		result = "CKM_RC2_CBC_PAD";
+		break;
+	case CKM_RC4_KEY_GEN:
+		result = "CKM_RC4_KEY_GEN";
+		break;
+	case CKM_RC4:
+		result = "CKM_RC4";
+		break;
+	case CKM_DES_KEY_GEN:
+		result = "CKM_DES_KEY_GEN";
+		break;
+	case CKM_DES_ECB:
+		result = "CKM_DES_ECB";
+		break;
+	case CKM_DES_CBC:
+		result = "CKM_DES_CBC";
+		break;
+	case CKM_DES_MAC:
+		result = "CKM_DES_MAC";
+		break;
+	case CKM_DES_MAC_GENERAL:
+		result = "CKM_DES_MAC_GENERAL";
+		break;
+	case CKM_DES_CBC_PAD:
+		result = "CKM_DES_CBC_PAD";
+		break;
+	case CKM_DES2_KEY_GEN:
+		result = "CKM_DES2_KEY_GEN";
+		break;
+	case CKM_DES3_KEY_GEN:
+		result = "CKM_DES3_KEY_GEN";
+		break;
+	case CKM_DES3_ECB:
+		result = "CKM_DES3_ECB";
+		break;
+	case CKM_DES3_CBC:
+		result = "CKM_DES3_CBC";
+		break;
+	case CKM_DES3_MAC:
+		result = "CKM_DES3_MAC";
+		break;
+	case CKM_DES3_MAC_GENERAL:
+		result = "CKM_DES3_MAC_GENERAL";
+		break;
+	case CKM_DES3_CBC_PAD:
+		result = "CKM_DES3_CBC_PAD";
+		break;
+	case CKM_CDMF_KEY_GEN:
+		result = "CKM_CDMF_KEY_GEN";
+		break;
+	case CKM_CDMF_ECB:
+		result = "CKM_CDMF_ECB";
+		break;
+	case CKM_CDMF_CBC:
+		result = "CKM_CDMF_CBC";
+		break;
+	case CKM_CDMF_MAC:
+		result = "CKM_CDMF_MAC";
+		break;
+	case CKM_CDMF_MAC_GENERAL:
+		result = "CKM_CDMF_MAC_GENERAL";
+		break;
+	case CKM_CDMF_CBC_PAD:
+		result = "CKM_CDMF_CBC_PAD";
+		break;
+	case CKM_MD2:
+		result = "CKM_MD2";
+		break;
+	case CKM_MD2_HMAC:
+		result = "CKM_MD2_HMAC";
+		break;
+	case CKM_MD2_HMAC_GENERAL:
+		result = "CKM_MD2_HMAC_GENERAL";
+		break;
+	case CKM_MD5:
+		result = "CKM_MD5";
+		break;
+	case CKM_MD5_HMAC:
+		result = "CKM_MD5_HMAC";
+		break;
+	case CKM_MD5_HMAC_GENERAL:
+		result = "CKM_MD5_HMAC_GENERAL";
+		break;
+	case CKM_SHA_1:
+		result = "CKM_SHA_1";
+		break;
+	case CKM_SHA_1_HMAC:
+		result = "CKM_SHA_1_HMAC";
+		break;
+	case CKM_SHA_1_HMAC_GENERAL:
+		result = "CKM_SHA_1_HMAC_GENERAL";
+		break;
+	case CKM_CAST_KEY_GEN:
+		result = "CKM_CAST_KEY_GEN";
+		break;
+	case CKM_CAST_ECB:
+		result = "CKM_CAST_ECB";
+		break;
+	case CKM_CAST_CBC:
+		result = "CKM_CAST_CBC";
+		break;
+	case CKM_CAST_MAC:
+		result = "CKM_CAST_MAC";
+		break;
+	case CKM_CAST_MAC_GENERAL:
+		result = "CKM_CAST_MAC_GENERAL";
+		break;
+	case CKM_CAST_CBC_PAD:
+		result = "CKM_CAST_CBC_PAD";
+		break;
+	case CKM_CAST3_KEY_GEN:
+		result = "CKM_CAST3_KEY_GEN";
+		break;
+	case CKM_CAST3_ECB:
+		result = "CKM_CAST3_ECB";
+		break;
+	case CKM_CAST3_CBC:
+		result = "CKM_CAST3_CBC";
+		break;
+	case CKM_CAST3_MAC:
+		result = "CKM_CAST3_MAC";
+		break;
+	case CKM_CAST3_MAC_GENERAL:
+		result = "CKM_CAST3_MAC_GENERAL";
+		break;
+	case CKM_CAST3_CBC_PAD:
+		result = "CKM_CAST3_CBC_PAD";
+		break;
+		/*case CKM_CAST5_KEY_GEN:
+		result = "CKM_CAST5_KEY_GEN";
+		break;*/
+	case CKM_CAST128_KEY_GEN:
+		result = "CKM_CAST128_KEY_GEN/CKM_CAST5_KEY_GEN";
+		break;
+		/*case CKM_CAST5_ECB:
+		result = "CKM_CAST5_ECB";
+		break;*/
+	case CKM_CAST128_ECB:
+		result = "CKM_CAST128_ECB/CKM_CAST5_ECB";
+		break;
+		/*case CKM_CAST5_CBC:
+		result = "CKM_CAST5_CBC";
+		break;*/
+	case CKM_CAST128_CBC:
+		result = "CKM_CAST128_CBC/CKM_CAST5_CBC";
+		break;
+		/*case CKM_CAST5_MAC:
+		result = "CKM_CAST5_MAC";
+		break;*/
+	case CKM_CAST128_MAC:
+		result = "CKM_CAST128_MAC/CKM_CAST5_MAC";
+		break;
+		/*case CKM_CAST5_MAC_GENERAL:
+		result = "CKM_CAST5_MAC_GENERAL";
+		break;*/
+	case CKM_CAST128_MAC_GENERAL:
+		result = "CKM_CAST128_MAC_GENERAL/CKM_CAST5_MAC_GENERAL";
+		break;
+		/*case CKM_CAST5_CBC_PAD:
+		result = "CKM_CAST5_CBC_PAD";
+		break;*/
+	case CKM_CAST128_CBC_PAD:
+		result = "CKM_CAST128_CBC_PAD/CKM_CAST5_CBC_PAD";
+		break;
+	case CKM_RC5_KEY_GEN:
+		result = "CKM_RC5_KEY_GEN";
+		break;
+	case CKM_RC5_ECB:
+		result = "CKM_RC5_ECB";
+		break;
+	case CKM_RC5_CBC:
+		result = "CKM_RC5_CBC";
+		break;
+	case CKM_RC5_MAC:
+		result = "CKM_RC5_MAC";
+		break;
+	case CKM_RC5_MAC_GENERAL:
+		result = "CKM_RC5_MAC_GENERAL";
+		break;
+	case CKM_RC5_CBC_PAD:
+		result = "CKM_RC5_CBC_PAD";
+		break;
+	case CKM_IDEA_KEY_GEN:
+		result = "CKM_IDEA_KEY_GEN";
+		break;
+	case CKM_IDEA_ECB:
+		result = "CKM_IDEA_ECB";
+		break;
+	case CKM_IDEA_CBC:
+		result = "CKM_IDEA_CBC";
+		break;
+	case CKM_IDEA_MAC:
+		result = "CKM_IDEA_MAC";
+		break;
+	case CKM_IDEA_MAC_GENERAL:
+		result = "CKM_IDEA_MAC_GENERAL";
+		break;
+	case CKM_IDEA_CBC_PAD:
+		result = "CKM_IDEA_CBC_PAD";
+		break;
+	case CKM_GENERIC_SECRET_KEY_GEN:
+		result = "CKM_GENERIC_SECRET_KEY_GEN";
+		break;
+	case CKM_CONCATENATE_BASE_AND_KEY:
+		result = "CKM_CONCATENATE_BASE_AND_KEY";
+		break;
+	case CKM_CONCATENATE_BASE_AND_DATA:
+		result = "CKM_CONCATENATE_BASE_AND_DATA";
+		break;
+	case CKM_CONCATENATE_DATA_AND_BASE:
+		result = "CKM_CONCATENATE_DATA_AND_BASE";
+		break;
+	case CKM_XOR_BASE_AND_DATA:
+		result = "CKM_XOR_BASE_AND_DATA";
+		break;
+	case CKM_EXTRACT_KEY_FROM_KEY:
+		result = "CKM_EXTRACT_KEY_FROM_KEY";
+		break;
+	case CKM_SSL3_PRE_MASTER_KEY_GEN:
+		result = "CKM_SSL3_PRE_MASTER_KEY_GEN";
+		break;
+	case CKM_SSL3_MASTER_KEY_DERIVE:
+		result = "CKM_SSL3_MASTER_KEY_DERIVE";
+		break;
+	case CKM_SSL3_KEY_AND_MAC_DERIVE:
+		result = "CKM_SSL3_KEY_AND_MAC_DERIVE";
+		break;
+	case CKM_SSL3_MD5_MAC:
+		result = "CKM_SSL3_MD5_MAC";
+		break;
+	case CKM_SSL3_SHA1_MAC:
+		result = "CKM_SSL3_SHA1_MAC";
+		break;
+	case CKM_MD5_KEY_DERIVATION:
+		result = "CKM_MD5_KEY_DERIVATION";
+		break;
+	case CKM_MD2_KEY_DERIVATION:
+		result = "CKM_MD2_KEY_DERIVATION";
+		break;
+	case CKM_SHA1_KEY_DERIVATION:
+		result = "CKM_SHA1_KEY_DERIVATION";
+		break;
+	case CKM_PBE_MD2_DES_CBC:
+		result = "CKM_PBE_MD2_DES_CBC";
+		break;
+	case CKM_PBE_MD5_DES_CBC:
+		result = "CKM_PBE_MD5_DES_CBC";
+		break;
+	case CKM_PBE_MD5_CAST_CBC:
+		result = "CKM_PBE_MD5_CAST_CBC";
+		break;
+	case CKM_PBE_MD5_CAST3_CBC:
+		result = "CKM_PBE_MD5_CAST3_CBC";
+		break;
+		/*case CKM_PBE_MD5_CAST5_CBC:
+		result = "CKM_PBE_MD5_CAST5_CBC";
+		break;*/
+	case CKM_PBE_MD5_CAST128_CBC:
+		result = "CKM_PBE_MD5_CAST128_CBC/CKM_PBE_MD5_CAST5_CBC";
+		break;
+		/*case CKM_PBE_SHA1_CAST5_CBC:
+		result = "CKM_PBE_SHA1_CAST5_CBC";
+		break;*/
+	case CKM_PBE_SHA1_CAST128_CBC:
+		result = "CKM_PBE_SHA1_CAST128_CBC/CKM_PBE_SHA1_CAST5_CBC";
+		break;
+	case CKM_PBE_SHA1_RC4_128:
+		result = "CKM_PBE_SHA1_RC4_128";
+		break;
+	case CKM_PBE_SHA1_RC4_40:
+		result = "CKM_PBE_SHA1_RC4_40";
+		break;
+	case CKM_PBE_SHA1_DES3_EDE_CBC:
+		result = "CKM_PBE_SHA1_DES3_EDE_CBC";
+		break;
+	case CKM_PBE_SHA1_DES2_EDE_CBC:
+		result = "CKM_PBE_SHA1_DES2_EDE_CBC";
+		break;
+	case CKM_PBE_SHA1_RC2_128_CBC:
+		result = "CKM_PBE_SHA1_RC2_128_CBC";
+		break;
+	case CKM_PBE_SHA1_RC2_40_CBC:
+		result = "CKM_PBE_SHA1_RC2_40_CBC";
+		break;
+	case CKM_PBA_SHA1_WITH_SHA1_HMAC:
+		result = "CKM_PBA_SHA1_WITH_SHA1_HMAC";
+		break;
+	case CKM_KEY_WRAP_LYNKS:
+		result = "CKM_KEY_WRAP_LYNKS";
+		break;
+	case CKM_KEY_WRAP_SET_OAEP:
+		result = "CKM_KEY_WRAP_SET_OAEP";
+		break;
+	case CKM_SKIPJACK_KEY_GEN:
+		result = "CKM_SKIPJACK_KEY_GEN";
+		break;
+	case CKM_SKIPJACK_ECB64:
+		result = "CKM_SKIPJACK_ECB64";
+		break;
+	case CKM_SKIPJACK_CBC64:
+		result = "CKM_SKIPJACK_CBC64";
+		break;
+	case CKM_SKIPJACK_OFB64:
+		result = "CKM_SKIPJACK_OFB64";
+		break;
+	case CKM_SKIPJACK_CFB64:
+		result = "CKM_SKIPJACK_CFB64";
+		break;
+	case CKM_SKIPJACK_CFB32:
+		result = "CKM_SKIPJACK_CFB32";
+		break;
+	case CKM_SKIPJACK_CFB16:
+		result = "CKM_SKIPJACK_CFB16";
+		break;
+	case CKM_SKIPJACK_CFB8:
+		result = "CKM_SKIPJACK_CFB8";
+		break;
+	case CKM_SKIPJACK_WRAP:
+		result = "CKM_SKIPJACK_WRAP";
+		break;
+	case CKM_SKIPJACK_PRIVATE_WRAP:
+		result = "CKM_SKIPJACK_PRIVATE_WRAP";
+		break;
+	case CKM_SKIPJACK_RELAYX:
+		result = "CKM_SKIPJACK_RELAYX";
+		break;
+	case CKM_KEA_KEY_PAIR_GEN:
+		result = "CKM_KEA_KEY_PAIR_GEN";
+		break;
+	case CKM_KEA_KEY_DERIVE:
+		result = "CKM_KEA_KEY_DERIVE";
+		break;
+	case CKM_FORTEZZA_TIMESTAMP:
+		result = "CKM_FORTEZZA_TIMESTAMP";
+		break;
+	case CKM_BATON_KEY_GEN:
+		result = "CKM_BATON_KEY_GEN";
+		break;
+	case CKM_BATON_ECB128:
+		result = "CKM_BATON_ECB128";
+		break;
+	case CKM_BATON_ECB96:
+		result = "CKM_BATON_ECB96";
+		break;
+	case CKM_BATON_CBC128:
+		result = "CKM_BATON_CBC128";
+		break;
+	case CKM_BATON_COUNTER:
+		result = "CKM_BATON_COUNTER";
+		break;
+	case CKM_BATON_SHUFFLE:
+		result = "CKM_BATON_SHUFFLE";
+		break;
+	case CKM_BATON_WRAP:
+		result = "CKM_RSA_9796";
+		break;
+	case CKM_ECDSA:
+		result = "CKM_ECDSA";
+		break;
+	case CKM_ECDSA_SHA1:
+		result = "CKM_ECDSA_SHA1";
+		break;
+	case CKM_JUNIPER_KEY_GEN:
+		result = "CKM_JUNIPER_KEY_GEN";
+		break;
+	case CKM_JUNIPER_ECB128:
+		result = "CKM_JUNIPER_ECB128";
+		break;
+	case CKM_JUNIPER_CBC128:
+		result = "CKM_JUNIPER_CBC128";
+		break;
+	case CKM_JUNIPER_COUNTER:
+		result = "CKM_JUNIPER_COUNTER";
+		break;
+	case CKM_JUNIPER_SHUFFLE:
+		result = "CKM_JUNIPER_SHUFFLE";
+		break;
+	case CKM_JUNIPER_WRAP:
+		result = "CKM_JUNIPER_WRAP";
+		break;
+	case CKM_FASTHASH:
+		result = "CKM_FASTHASH";
+		break;
+	case CKM_VENDOR_DEFINED:
+		result = "CKM_VENDOR_DEFINED";
+		break;
+	case CKM_SHA256:
+		result = "CKM_SHA256";
+		break;
+	case CKM_SHA256_RSA_PKCS:
+		result = "CKM_SHA256_RSA_PKCS";
+		break;
+	default:
+		toString( result, "UNKNOWN MECHANISM <%#02x>", t );
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_INFOToString( CK_MECHANISM_INFO_PTR pInfo, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pInfo )
+	{
+		 return;
+	}
+
+	std::string flags = "";
+	CK_FLAGS f = pInfo->flags;
+	mechanismFlagsToString( f, flags );
+
+	toString( result, "ulMinKeySize <%#02x> - ulMaxKeySize <%#02x> - flags <%s>", pInfo->ulMinKeySize, pInfo->ulMaxKeySize, flags.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::mechanismFlagsToString( const CK_FLAGS& f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( f & CKF_EXTENSION )
+	{
+		result += "CKF_EXTENSION";
+	}
+	if( f & CKF_DERIVE )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_DERIVE";
+	}
+	if( f & CKF_UNWRAP )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_UNWRAP";
+	}
+	if( f & CKF_WRAP )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_WRAP";
+	}
+	if( f & CKF_GENERATE_KEY_PAIR )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_GENERATE_KEY_PAIR";
+	}
+	if( f & CKF_GENERATE )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_GENERATE";
+	}
+	if( f & CKF_VERIFY_RECOVER )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_VERIFY_RECOVER";
+	}
+	if( f & CKF_VERIFY )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_VERIFY";
+	}
+	if( f & CKF_SIGN_RECOVER )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_SIGN_RECOVER";
+	}
+	if( f & CKF_HW )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_HW";
+	}
+	if( f & CKF_ENCRYPT )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_ENCRYPT";
+	}
+	if( f & CKF_DECRYPT )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_DECRYPT";
+	}
+	if( f & CKF_DIGEST )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_DIGEST";
+	}
+	if( f & CKF_SIGN )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_SIGN";
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::sessionFlagsToString( const CK_FLAGS &f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	result = "";
+
+	// Session information flags
+	if( f & CKF_SERIAL_SESSION )
+	{
+		result += "CKF_SERIAL_SESSION";
+	}
+
+	if( f & CKF_RW_SESSION )
+	{
+		if( !result.empty( ) )
+		{
+			result += " | ";
+		}
+		result += "CKF_RW_SESSION";
+	}
+#endif
+}
+
+
+/*
+*/
+void Log::CK_SESSION_INFOToString( CK_SESSION_INFO_PTR pInfo, std::string& result )
+{
+#ifdef __DEBUG_GEMALTO__
+	if( NULL_PTR == pInfo )
+	{
+		return;
+	}
+
+	std::string flags = "";
+	CK_FLAGS f = pInfo->flags;
+	sessionFlagsToString( f, flags );
+
+	toString( result, "slotID <%#02x> - state <%#02x> - flags <%#02x> (%s) - ulDeviceError <%#02x>",
+				pInfo->slotID,
+				pInfo->state,
+				pInfo->flags,
+				flags.c_str( ),
+				pInfo->ulDeviceError );
+#endif
+}
+
+/*
+*/
+void Log::CK_USER_TYPEToString( const CK_USER_TYPE& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+	switch( t )
+	{
+	case CKU_USER:
+		result = "CKU_USER";
+		break;
+
+	case CKU_SO:
+		result  = "CKU_SO";
+		break;
+
+	default:
+		toString( result, "UNKNOWN USER TYPE <%#02x>", t );
+	}
+#endif
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,90 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_log_h
+#define _include_log_h
+
+#include <string>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include "platconfig.h"
+
+
+class Log
+{
+public:
+
+   static void log( const char * format, ... );
+
+   static void error( const char*, const char* );
+   static void in( const char* a_pMethod );
+   static void out( const char* a_pMethod );
+   static void begin( const char* a_pMethod );
+   static void end( const char* a_pMethod );
+
+   static void logCK_SLOT_ID_PTR( const char*, CK_SLOT_ID_PTR, CK_ULONG_PTR );
+   static void logCK_SLOT_INFO_PTR( const char*, CK_SLOT_INFO_PTR );
+   static void logCK_C_INITIALIZE_ARGS_PTR( const char*, CK_C_INITIALIZE_ARGS_PTR );
+   static void logCK_INFO( const char*, const CK_INFO_PTR );
+   static void logCK_RV( const char*, const CK_RV & );
+   static void logCK_UTF8CHAR_PTR( const char*, const unsigned char*, const std::size_t& );
+   static void logCK_TOKEN_INFO_PTR( const char*, CK_TOKEN_INFO_PTR );
+   static void logCK_MECHANISM_TYPE( const char*, CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR );
+   static void logCK_MECHANISM_TYPE( const char*, CK_MECHANISM_TYPE & );
+   static void logCK_SESSION_INFO_PTR( const char*, CK_SESSION_INFO_PTR );
+   static void logCK_USER_TYPE( const char*, CK_USER_TYPE & );
+   static void logCK_ATTRIBUTE_PTR( const char*, CK_ATTRIBUTE_PTR, CK_ULONG & );
+   static void logSessionFlags( const char*, CK_FLAGS & );
+   static void logCK_MECHANISM_INFO_PTR( const char*, CK_MECHANISM_INFO_PTR );
+   static void logCK_MECHANISM_PTR( const char*, CK_MECHANISM_PTR );
+
+   static void CK_MECHANISMToString( CK_MECHANISM_PTR, std::string & );
+   static void CK_CERTIFICATE_TYPEToString( const CK_CERTIFICATE_TYPE &, std::string & );
+   static void CK_KEY_TYPEToString( const CK_KEY_TYPE&, std::string & );
+   static void CK_OBJECT_CLASSToString( const CK_OBJECT_CLASS&, std::string & );
+   static void CK_DATEToString( const CK_DATE*, std::string & );
+   static void CK_INFOToString( CK_INFO_PTR pInfo, std::string &result );
+   static void slotFlagsToString( const CK_FLAGS& f, std::string &result );
+   static void mechanismFlagsToString( const CK_FLAGS &, std::string & );
+   static void sessionFlagsToString( const CK_FLAGS & , std::string & );
+   static void CK_VERSIONToString( CK_VERSION_PTR pVersion, std::string& result );
+   static void CK_RVToString( const CK_RV& rv, std::string &result );
+   static void CK_MECHANISM_TYPEToString( CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG mechanismListLen, std::string &result );
+   static void CK_MECHANISM_TYPEToString( const CK_MECHANISM_TYPE &, std::string & );
+   static void CK_MECHANISM_INFOToString( CK_MECHANISM_INFO_PTR pInfo, std::string &result );
+   static void CK_SESSION_INFOToString( CK_SESSION_INFO_PTR, std::string& );
+   static void CK_USER_TYPEToString( const CK_USER_TYPE&, std::string & );
+   static void CK_ATTRIBUTEToString( const CK_ATTRIBUTE_PTR, std::string & );
+   static void CK_ATTRIBUTE_TYPEToString( const CK_ATTRIBUTE_TYPE& , std::string &, int& );
+
+   static void toStringHex( const unsigned char* buffer, const std::size_t& size, std::string &result );
+   static void toString( std::string &result, const char * format, ... );
+   static void toString( const unsigned char* buffer, std::size_t size, std::string &result );
+   static void toString( const unsigned long &l, std::string &result );
+
+   template<typename T> static void classtoString( const T & value, std::string &result );
+
+};
+
+
+#endif

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "md5.h"
+
+CMD5::CMD5(){
+    this->_hashValue     = (CK_BYTE_PTR)malloc(MD5_HASH_LENGTH);
+    this->_workingBuffer = (CK_BYTE_PTR)malloc(MD5_BLOCK_LENGTH);
+    this->_hashLength    = MD5_HASH_LENGTH;
+    this->_blockLength   = MD5_BLOCK_LENGTH;
+}
+
+CMD5::~CMD5(){
+}
+
+void CMD5::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_md5_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_md5_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    algo_md5_update(&ctx, data, MD5_BLOCK_LENGTH);
+}
+
+void CMD5::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_md5_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_md5_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    // allocate tempory working buffer
+    ctx.input = (u1*)malloc(MD5_BLOCK_LENGTH);
+    memset(ctx.input,0,MD5_BLOCK_LENGTH);
+
+    algo_md5_update(&ctx,data,length);
+    algo_md5_finish(&ctx);
+
+    free(ctx.input);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_md5_h
+#define _include_md5_h
+
+#include "MarshallerCfg.h"
+#include "algo_md5.h"
+
+class CMD5 : public CDigest
+{
+private:
+    void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+    void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+    CMD5();
+    ~CMD5();
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,144 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include <string>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include "mutex.h"
+
+CMutex::CMutex()
+{
+#ifdef WIN32
+    m_hMutex = NULL;
+#endif
+    m_strName = "";
+}
+
+CMutex::CMutex(const char* nm)
+{
+    m_strName = nm;
+
+#ifdef WIN32
+    m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
+
+    if(m_hMutex == NULL)
+    {
+        assert(FALSE); //throw ThreadException("Failed to create mutex");
+    }
+#else
+    pthread_mutex_init(&m_hMutex,0);
+    m_ownerThread = 0;
+    m_refCount = 0;
+#endif
+}
+
+#ifdef WIN32
+void CMutex::create(const char* nm)
+#else
+void CMutex::create(const char*)
+#endif
+{
+
+#ifdef WIN32
+    if(m_hMutex != NULL)
+    {
+        CloseHandle(m_hMutex);
+        m_hMutex = NULL;
+    }
+
+    m_strName = nm;
+    m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
+
+    if(m_hMutex == NULL)
+    {
+        assert(FALSE); //throw ThreadException("Failed to create mutex");
+    }
+#else
+    if(pthread_equal(m_ownerThread,pthread_self()))
+    {
+        m_refCount++;
+    }
+    else
+    {
+        if(pthread_mutex_lock(&m_hMutex) == 0)
+        {
+            //assert(FALSE);
+        }
+        m_ownerThread = pthread_self();
+        m_refCount = 1;
+    }
+
+
+#endif
+}
+
+#ifdef WIN32
+unsigned long* CMutex::getMutexHandle()
+{
+    return m_hMutex;
+}
+#endif
+
+std::string CMutex::getName()
+{
+    return m_strName;
+}
+
+void CMutex::release()
+{
+#ifdef WIN32
+    if(m_hMutex != NULL)
+    {
+        CloseHandle(m_hMutex);
+        m_hMutex = NULL;
+    }
+#else
+    if(pthread_equal(m_ownerThread,pthread_self()))
+    {
+        m_refCount--;
+
+        if(!m_refCount)
+        {
+            m_ownerThread = 0;
+            pthread_mutex_unlock(&m_hMutex);
+        }
+    }
+#endif
+}
+
+CMutex::~CMutex()
+{
+#ifdef WIN32
+    if(m_hMutex != NULL)
+    {
+        CloseHandle(m_hMutex);
+    }
+#else
+    pthread_mutex_destroy(&m_hMutex);
+#endif
+}
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,54 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_mutex_h
+#define _include_mutex_h
+
+#ifdef INCLUDE_EVENTING
+
+class CMutex
+{
+private:
+    // unsigned long* to the low-level mutex object
+#ifdef WIN32
+    unsigned long* m_hMutex;
+#else
+    pthread_mutex_t m_hMutex;
+    pthread_t 		m_ownerThread;
+    unsigned long 	m_refCount;
+#endif
+    // name to identify the mutex
+    std::string m_strName;
+
+public:
+    CMutex();
+    CMutex(const char* nm);
+    ~CMutex();
+
+    void create(const char* nm);
+    unsigned long* getMutexHandle();
+    std::string getName();
+    void release();
+};
+
+#endif
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,2189 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define CRYPTOKIVERSION_INTERFACE_MAJOR  0x02
+#define CRYPTOKIVERSION_INTERFACE_MINOR  0x14
+
+#define CRYPTOKIVERSION_LIBRARY_MAJOR    0x02
+#define CRYPTOKIVERSION_LIBRARY_MINOR    0x00
+
+#define LIBRARY_DESCRIPTION             "CF .NET PKCS#11 Module"
+#define MANUFACTURER_ID                 "Gemalto"
+
+#include <string>
+
+#include "stdafx.h"
+#include <winscard.h>
+#include "error.h"
+#include "platconfig.h"
+#include "config.h"
+#include "digest.h"
+#include "symmalgo.h"
+#include "thread.h"
+#include "event.h"
+#include "mutex.h"
+#include "session.h"
+#include "slot.h"
+#include "application.h"
+#include "critsect.h"
+#include "log.h"
+
+
+static CK_BBOOL _isInitialized = FALSE;
+
+
+// This libarary is thread protected by a single critical section
+// This coarse grained approach is for simplicty, the alternative
+// require significant work.
+CCriticalSection _critSect;
+
+static const CK_FUNCTION_LIST FunctionList = {
+   { CRYPTOKIVERSION_LIBRARY_MAJOR, CRYPTOKIVERSION_LIBRARY_MINOR },
+
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+
+#define CK_PKCS11_FUNCTION_INFO(func) func,
+
+#include "pkcs11f.h"
+
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+};
+
+
+#define PKCS11_TRY \
+   if (!_isInitialized) { \
+   return CKR_CRYPTOKI_NOT_INITIALIZED; } \
+   CCriticalSectionLocker __cslock(_critSect); \
+   try
+
+
+#define PKCS11_CATCH(rv) \
+   catch(CkError & err) { rv = err.Error(); } \
+   catch(PcscError & ) { rv = CKR_FUNCTION_FAILED; } \
+   catch(Marshaller::Exception & exc) { rv = CkError::CheckMarshallerException(exc); } \
+   catch(...) { rv = CKR_GENERAL_ERROR; }
+
+
+// Put all static initializations here to ensure they
+// occur in correct order.
+
+CEvent CryptokiEvent(0xFFFFFFFF);
+
+// CStartStopControl to support clean up at DLL unload
+class CStartStopControl
+{
+public:
+   CStartStopControl() {};
+   ~CStartStopControl() {
+      Application::End( );
+   }
+} foo;
+
+
+extern "C"
+{
+
+
+   /**
+   * C_Initialize initializes the Cryptoki library.
+   *
+   * @param pInitArgs
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Initialize )( CK_VOID_PTR pInitArgs )
+   {
+      Log::begin( "C_Initialize" );
+      Log::in( "C_Initialize" );
+      Log::log( "C_Initialize - pInitArgs <%#02x>", pInitArgs );
+      Log::log( "C_Initialize - isInitialized <%#02x>", _isInitialized );
+
+      CK_RV rv = CKR_OK;
+
+      // Already Initialized
+      if( TRUE == _isInitialized )
+      {
+         Log::error( "C_Initialize", "CKR_CRYPTOKI_ALREADY_INITIALIZED" );
+         rv = CKR_CRYPTOKI_ALREADY_INITIALIZED;
+      }
+      else if( NULL_PTR != pInitArgs )
+      {
+         CK_C_INITIALIZE_ARGS initArgs = *(CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
+
+         Log::logCK_C_INITIALIZE_ARGS_PTR( "C_Initialize", (CK_C_INITIALIZE_ARGS_PTR)pInitArgs );
+
+         if( NULL_PTR != initArgs.pReserved )
+         {
+            Log::error( "C_Initialize", "CKR_ARGUMENTS_BAD" );
+            rv = CKR_ARGUMENTS_BAD;
+         }
+         else if( initArgs.flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS )
+         {
+            Log::error( "C_Initialize", "CKR_NEED_TO_CREATE_THREADS" );
+            rv = CKR_NEED_TO_CREATE_THREADS;
+         }
+         else if( initArgs.flags & CKF_OS_LOCKING_OK )
+         {
+            if( initArgs.CreateMutex || initArgs.DestroyMutex || initArgs.LockMutex || initArgs.UnlockMutex )
+            {
+               Log::error( "C_Initialize", "CKR_CANT_LOCK" );
+               rv = CKR_CANT_LOCK;
+            }
+         }
+         else if( initArgs.CreateMutex || initArgs.DestroyMutex || initArgs.LockMutex || initArgs.UnlockMutex )
+         {
+            if( !initArgs.CreateMutex || !initArgs.DestroyMutex || !initArgs.LockMutex || !initArgs.UnlockMutex )
+            {
+               Log::error( "C_Initialize", "CKR_ARGUMENTS_BAD" );
+               rv = CKR_ARGUMENTS_BAD;
+            }
+            else if( !( initArgs.flags & CKF_OS_LOCKING_OK ) )
+            {
+               Log::error( "C_Initialize", "CKR_CANT_LOCK" );
+               rv = CKR_CANT_LOCK;
+            }
+         }
+      }
+
+      if (rv == CKR_OK)
+      {
+         Application::InitApplication( );
+         _isInitialized = TRUE;
+      }
+
+      Log::log( "C_Initialize - isInitialized <%#02x>", _isInitialized );
+
+      Log::logCK_RV( "C_Initialize", rv );
+      Log::end( "C_Initialize" );
+
+      return rv;
+   }
+
+
+   /**
+   * C_Finalize indicates that an application is done with the
+   * Cryptoki library.
+   *
+   * @param pReserved reserved.Should be NULL_PTR
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Finalize )( CK_VOID_PTR pReserved )
+   {
+      Log::begin( "C_Finalize" );
+      Log::in( "C_Finalize" );
+      Log::log( "C_Finalize - pReserved <%#02x>", pReserved );
+
+      CK_RV rv = CKR_OK;
+
+      // Not Initialized
+      if( !_isInitialized )
+      {
+         Log::error( "C_Finalize", "CKR_CRYPTOKI_NOT_INITIALIZED" );
+         rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      }
+      else if( NULL_PTR != pReserved )
+      {
+         Log::error( "C_Finalize", "CKR_ARGUMENTS_BAD" );
+         rv = CKR_ARGUMENTS_BAD;
+      }
+      else
+      {
+         _isInitialized = FALSE;
+         Application::End( );
+      }
+
+      Log::logCK_RV( "C_Finalize", rv );
+      Log::end( "C_Finalize" );
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetInfo returns general information about Cryptoki.
+   *
+   * @param pInfo location that receives information
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetInfo )( CK_INFO_PTR pInfo )
+   {
+      Log::begin( "C_GetInfo" );
+      Log::in( "C_GetInfo" );
+      Log::logCK_INFO( "C_GetInfo", pInfo );
+
+      CK_RV rv = CKR_OK;
+      if( FALSE == _isInitialized )
+      {
+         rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      }
+      else if( NULL_PTR == pInfo )
+      {
+         rv = CKR_ARGUMENTS_BAD;
+      }
+      else
+      {
+         pInfo->cryptokiVersion.major = CRYPTOKIVERSION_INTERFACE_MAJOR;
+         pInfo->cryptokiVersion.minor = CRYPTOKIVERSION_INTERFACE_MINOR;
+         pInfo->flags = 0;
+         memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription));
+         memcpy(pInfo->libraryDescription, LIBRARY_DESCRIPTION, strlen(LIBRARY_DESCRIPTION));
+         memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
+         memcpy(pInfo->manufacturerID, MANUFACTURER_ID, strlen(MANUFACTURER_ID));
+         pInfo->libraryVersion.major  = CRYPTOKIVERSION_LIBRARY_MAJOR;
+         pInfo->libraryVersion.minor  = CRYPTOKIVERSION_LIBRARY_MINOR;
+      }
+
+      Log::logCK_RV( "C_GetInfo", rv );
+      Log::out( "C_GetInfo" );
+      Log::logCK_INFO( "C_GetInfo", pInfo );
+      Log::end( "C_GetInfo" );
+
+      return rv;
+   }
+
+   /**
+   * C_GetFunctionList returns the function list.
+   *
+   * @param ppFunctionList receives pointer to function list
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_GetFunctionList )( CK_FUNCTION_LIST_PTR_PTR ppFunctionList )
+   {
+      Log::begin( "C_GetFunctionList" );
+      Log::in( "C_GetFunctionList" );
+      Log::log( "C_GetFunctionList - CK_FUNCTION_LIST_PTR_PTR <%#02x>", ppFunctionList );
+
+      CK_RV rv = CKR_OK;
+      if( NULL_PTR == ppFunctionList )
+      {
+         rv = CKR_ARGUMENTS_BAD;
+      }
+      else
+      {
+         // this is the only function which an application can call before calling C_Initialize
+         *ppFunctionList = (CK_FUNCTION_LIST_PTR)&FunctionList;
+      }
+
+      Log::logCK_RV( "C_GetFunctionList", rv );
+      Log::out( "C_GetFunctionList" );
+      Log::log( "C_GetFunctionList - CK_FUNCTION_LIST_PTR_PTR <%#02x>", ppFunctionList );
+      Log::end( "C_GetFunctionList" );
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetSlotList obtains a list of slots in the system.
+   *
+   * @param tokenPresent only slots with tokens
+   * @param pSlotList    receives array of slot IDs
+   * @param pulCount     receives number of slots
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetSlotList )( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+   {
+      Log::begin( "C_GetSlotList" );
+      Log::in( "C_GetSlotList" );
+      Log::log( "C_GetSlotList - tokenPresent <%d>", tokenPresent );
+      Log::logCK_SLOT_ID_PTR( "C_GetSlotList", pSlotList, pulCount );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Application::Enumerate( tokenPresent, pSlotList, pulCount );
+      }
+      PKCS11_CATCH( rv )
+
+      Log::logCK_RV( "C_GetSlotList", rv );
+      Log::out( "C_GetSlotList" );
+      Log::logCK_SLOT_ID_PTR( "C_GetSlotList", pSlotList, pulCount );
+      Log::end( "C_GetSlotList" );
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetSlotInfo obtains information about a particular slot in
+   * the system.
+   *
+   * @param slotId the ID of the slot
+   * @param pInfo  received the slot information
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetSlotInfo )( CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo )
+   {
+      Log::begin( "C_GetSlotInfo" );
+      Log::in( "C_GetSlotInfo" );
+      Log::log( "C_GetSlotInfo - slotID <%ld>", slotID );
+      Log::logCK_SLOT_INFO_PTR( "C_GetSlotInfo", pInfo );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+        if(Application::_numSlots == 0)
+         {
+            CK_ULONG slotCount = 0;
+            Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+            Application::Enumerate(CK_FALSE,slots,&slotCount);
+            free(slots);
+         }
+
+         Slot* pSlot = NULL_PTR;
+         rv = Application::GetSlotFromSlotId( slotID, &pSlot );
+
+         if(rv == CKR_OK)
+         {
+            rv = pSlot->GetInfo( pInfo );
+         }
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_GetSlotInfo", rv );
+      Log::out( "C_GetSlotInfo" );
+      Log::logCK_SLOT_INFO_PTR( "C_GetSlotInfo", pInfo );
+      Log::end( "C_GetSlotInfo" );
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetTokenInfo obtains information about a particular token
+   * in the system.
+   *
+   * @param slotID ID of the token's slot
+   * @param pInfo  receives the token information
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetTokenInfo )( CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo )
+   {
+      Log::begin( "C_GetTokenInfo" );
+      Log::in( "C_GetTokenInfo" );
+      Log::log( "C_GetTokenInfo - slotID <%ld>", slotID );
+      Log::logCK_TOKEN_INFO_PTR( "C_GetTokenInfo", pInfo );
+
+      CK_RV rv = CKR_OK;
+
+      PKCS11_TRY
+      {
+         if(Application::_numSlots == 0)
+         {
+            CK_ULONG slotCount = 0;
+            Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+            Application::Enumerate(CK_FALSE,slots,&slotCount);
+            free(slots);
+         }
+
+         Slot* slot = NULL_PTR;
+         rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+         if(rv == CKR_OK)
+         {
+            rv = slot->GetTokenInfo(pInfo);
+         }
+      }
+      //PKCS11_CATCH(rv)
+      catch( CkError & e )
+      {
+         rv = e.Error( );
+         Log::log( "C_GetTokenInfo - ## Error ## CkError <%s> <%#02x>", e.what( ), e.Error( ) );
+      }
+      catch( PcscError & e )
+      {
+         rv = CKR_FUNCTION_FAILED;
+         Log::log( "C_GetTokenInfo - ## Error ## PcscError <%s> <%#02x> <%#02x>", e.what( ), e.Error( ), rv );
+      }
+      catch( Marshaller::Exception & e )
+      {
+         rv = CkError::CheckMarshallerException( e );
+         Log::log( "C_GetTokenInfo - ## Error ## PcscError <%s> <%#02x>", e.what( ), rv );
+      }
+      catch( ... )
+      {
+         rv = CKR_GENERAL_ERROR;
+         Log::log( "C_GetTokenInfo - ## Error ## (...) <%#02x>", rv );
+      }
+
+      Log::logCK_RV( "C_GetTokenInfo", rv );
+      Log::out( "C_GetTokenInfo" );
+      Log::logCK_TOKEN_INFO_PTR( "C_GetTokenInfo", pInfo );
+      Log::end( "C_GetTokenInfo" );
+
+      return rv;
+   }
+
+
+   /**
+   * C_GetMechanismList obtains a list of mechanism types
+   * supported by a token.
+   *
+   * @param slotID ID of token's slot
+   * @param pMechanismList gets mech. array
+   * @param pulCount get number of mechs
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetMechanismList )( CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount )
+   {
+      Log::begin( "C_GetMechanismList" );
+      Log::in( "C_GetMechanismList" );
+      Log::log( "C_GetMechanismList - slotID <%#02x>", slotID );
+      Log::logCK_MECHANISM_TYPE( "C_GetMechanismList", pMechanismList, pulCount );
+
+      CK_RV rv = CKR_OK;
+
+      PKCS11_TRY
+      {
+         if(Application::_numSlots == 0)
+         {
+            CK_ULONG slotCount = 0;
+            Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+            Application::Enumerate(CK_FALSE,slots,&slotCount);
+            free(slots);
+         }
+
+         Slot* slot = NULL_PTR;
+         rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+         if(rv == CKR_OK)
+         {
+            rv = slot->GetMechanismList(pMechanismList,pulCount);
+         }
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_GetMechanismList", rv );
+      Log::out( "C_GetMechanismList" );
+      Log::logCK_MECHANISM_TYPE( "C_GetMechanismList", pMechanismList, pulCount );
+      Log::end( "C_GetMechanismList" );
+      return rv;
+   }
+
+
+   /**
+   * C_GetMechanismInfo obtains information about a particular
+   * mechanism possibly supported by a token.
+   *
+   * @param slotID ID of the token's slot
+   * @param type  type of mechanism
+   * @param pInfo receives mechanism info
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetMechanismInfo )( CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo )
+   {
+      Log::begin( "C_GetMechanismInfo" );
+      Log::in( "C_GetMechanismInfo" );
+      Log::log( "C_GetMechanismInfo - slotID <%#02x>", slotID );
+      Log::logCK_MECHANISM_TYPE( "C_GetMechanismInfo", type );
+      Log::logCK_MECHANISM_INFO_PTR( "C_GetMechanismInfo", pInfo );
+
+      CK_RV rv = CKR_OK;
+
+      PKCS11_TRY
+      {
+         if(Application::_numSlots == 0)
+         {
+            CK_ULONG slotCount = 0;
+            Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+            Application::Enumerate(CK_FALSE,slots,&slotCount);
+            free(slots);
+         }
+
+         Slot* slot = NULL_PTR;
+         rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+         if(rv == CKR_OK)
+         {
+            rv = slot->GetMechanismInfo(type,pInfo);
+         }
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_GetMechanismInfo", rv );
+      Log::out( "C_GetMechanismInfo" );
+      Log::logCK_MECHANISM_INFO_PTR( "C_GetMechanismInfo", pInfo );
+      Log::end( "C_GetMechanismInfo" );
+      return rv;
+   }
+
+
+   /**
+   * C_InitToken initializes a token.
+   *
+   * @param slotID ID of the token's slot
+   * @param pPin   the SO's initial PIN
+   * @param ulPinLen length in bytes of the PIN
+   * @param pLabel 32-byte token label (blank padded) pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_InitToken )( CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel )
+   {
+      Log::begin( "C_InitToken" );
+      Log::in( "C_InitToken" );
+      Log::log( "C_InitToken - slotID <%#02x>", slotID );
+      Log::logCK_UTF8CHAR_PTR( "C_InitToken - pPin", pPin, ulPinLen );
+      Log::logCK_UTF8CHAR_PTR( "C_InitToken - pLabel", pLabel, 32 );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         if(Application::_numSlots == 0)
+         {
+            CK_ULONG slotCount = 0;
+            Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+            Application::Enumerate(CK_FALSE,slots,&slotCount);
+            free(slots);
+         }
+
+         Slot* slot = NULL_PTR;
+         rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+         if(rv == CKR_OK)
+         {
+            rv = slot->InitToken(pPin,ulPinLen,pLabel);
+         }
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_InitToken", rv );
+      Log::end( "C_InitToken" );
+      return rv;
+   }
+
+
+   /**
+   * C_InitPIN initializes the normal user's PIN.
+   *
+   * @param hSession the session's handle
+   * @param pPin the noraml user's PIN
+   * @param ulPinLen length in bytes of the PIN
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_InitPIN )( CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen )
+   {
+      Log::begin( "C_InitPIN" );
+      Log::in( "C_InitPIN" );
+      Log::log( "C_InitPIN - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_InitPIN - pPin", pPin, ulPinLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::InitPIN( hSession, pPin, ulPinLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_InitPIN", rv );
+      Log::end( "C_InitPIN" );
+      return rv;
+   }
+
+
+   /**
+   * C_SetPIN modifies the PIN of the user who is logged in.
+   *
+   * @param hSession   the session's handle
+   * @param pOldPin     the old PIN
+   * @param ulOldPin    length of the old PIN
+   * @param pNewPin     the new PIN
+   * @param ulNewLen    length of the new PIN
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SetPIN )( CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen )
+   {
+      Log::begin( "C_SetPIN" );
+      Log::in( "C_SetPIN" );
+      Log::log( "C_SetPIN - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_SetPIN - pOldPin", pOldPin, ulOldLen );
+      Log::logCK_UTF8CHAR_PTR( "C_SetPIN - pNewPin", pNewPin, ulNewLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::SetPIN( hSession, pOldPin, ulOldLen, pNewPin, ulNewLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_SetPIN", rv );
+      Log::end( "C_SetPIN" );
+      return rv;
+   }
+
+
+   /**
+   * C_OpenSession opens a session between an application and a
+   * token.
+   *
+   * @param slotID       the slot's ID
+   * @param flags        from CK_SESSION_INFO
+   * @param pApplication passed to callback
+   * @param Notify       callback function
+   * @param phSession    gets session handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_OpenSession )( CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession )
+   {
+      Log::begin( "C_OpenSession" );
+      Log::in( "C_OpenSession" );
+      Log::log( "C_OpenSession - slotID <%#02x>", slotID );
+      Log::logSessionFlags( "C_OpenSession", flags );
+      Log::log( "C_OpenSession - pApplication <%#02x>", pApplication );
+      Log::log( "C_OpenSession - Notify <%#02x>", Notify );
+      Log::log( "C_OpenSession - phSession <%#02x> (%#02x)", phSession, ( ( NULL_PTR != phSession ) ? *phSession : 0 ) );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         if(Application::_numSlots == 0)
+         {
+            CK_ULONG slotCount = 0;
+            Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+            Application::Enumerate(CK_FALSE,slots,&slotCount);
+            free(slots);
+         }
+
+         Slot* slot = NULL_PTR;
+         rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+         if(rv == CKR_OK)
+         {
+            PKCS11_ASSERT(slot != NULL_PTR);
+            rv = slot->OpenSession(flags,pApplication,Notify,phSession);
+         }
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_OpenSession", rv );
+      Log::out( "C_OpenSession" );
+      Log::log( "C_OpenSession - phSession <%#02x> (%ld)", phSession, ( ( NULL_PTR != phSession ) ? *phSession : 0 ) );
+      Log::end( "C_OpenSession" );
+      return rv;
+   }
+
+
+   /**
+   * C_CloseSession closes a session between an application and a
+   * token.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CloseSession )( CK_SESSION_HANDLE hSession )
+   {
+      Log::begin( "C_CloseSession" );
+      Log::in( "C_CloseSession" );
+      Log::log( "C_CloseSession - hSession <%#02x>", hSession );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::CloseSession(hSession);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_CloseSession", rv );
+      Log::end( "C_CloseSession" );
+      return rv;
+   }
+
+
+   /**
+   * C_CloseAllSessions closes all sessions with a token.
+   *
+   * @param slotID the token's slot
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CloseAllSessions )( CK_SLOT_ID slotID )
+   {
+      Log::begin( "C_CloseAllSessions" );
+      Log::in( "C_CloseAllSessions" );
+      Log::log( "C_CloseAllSessions - slotID <%#02x>", slotID );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         if(Application::_numSlots == 0)
+         {
+            CK_ULONG slotCount = 0;
+            Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+            CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+            Application::Enumerate(CK_FALSE,slots,&slotCount);
+            free(slots);
+         }
+
+         Slot* slot = NULL_PTR;
+         rv    = Application::GetSlotFromSlotId(slotID,&slot);
+
+         if(rv == CKR_OK)
+         {
+            rv = slot->CloseAllSessions();
+         }
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_CloseAllSessions", rv );
+      Log::end( "C_CloseAllSessions" );
+      return rv;
+   }
+
+
+   /**
+   * C_GetSessionInfo obtains information about the session.
+   *
+   * @param hSession the session's handle
+   * @param receives session info
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetSessionInfo )( CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo )
+   {
+      Log::begin( "C_GetSessionInfo" );
+      Log::in( "C_GetSessionInfo" );
+      Log::log( "C_GetSessionInfo - hSession <%#02x>", hSession );
+      Log::logCK_SESSION_INFO_PTR( "C_GetSessionInfo", pInfo );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::GetSessionInfo(hSession,pInfo);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_GetSessionInfo", rv );
+      Log::out( "C_GetSessionInfo" );
+      Log::logCK_SESSION_INFO_PTR( "C_GetSessionInfo", pInfo );
+      Log::end( "C_GetSessionInfo" );
+      return rv;
+   }
+
+
+   /**
+   * C_GetOperationState obtains the state of the cryptographic operation
+   * in a session.
+   *
+   * @param hSession session's handle
+   * @param pOperationState gets State
+   * @param pulOperationStateLen gets state length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetOperationState )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_GetOperationState" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+      Log::logCK_RV( "C_GetOperationState", rv );
+      Log::end( "C_GetOperationState" );
+      return rv;
+   }
+
+
+   /**
+   * C_SetOperationState restores the state of the cryptographic
+   * operation in a session.
+   *
+   * @param hSession session's handle
+   * @param pOperationState hold state
+   * @param ulOperationStateLen holds state length
+   * @param hEncryptionKey en/decryption key
+   * @param hAuthenticationKey sig/verify key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SetOperationState )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_SetOperationState" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+      Log::logCK_RV( "C_SetOperationState", rv );
+      Log::end( "C_SetOperationState" );
+      return rv;
+   }
+
+   /**
+   * C_Login logs a user into a token.
+   *
+   * @param hSession the session's handle
+   * @param userType the user type
+   * @param pPin the user's PIN
+   * @param ulPinLen the length of the PIN
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Login )( CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen )
+   {
+      Log::begin( "C_Login" );
+      Log::in( "C_Login" );
+      Log::log( "C_Login - hSession <%#02x>", hSession );
+      Log::logCK_USER_TYPE( "C_Login", userType );
+      Log::logCK_UTF8CHAR_PTR( "C_Login - pPin", pPin, ulPinLen );
+      Log::log( "C_Login - ulPinLen <%ld>", ulPinLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::Login(hSession,userType,pPin,ulPinLen);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_Login", rv );
+      Log::end( "C_Login" );
+      return rv;
+   }
+
+
+   /**
+   * C_Logout logs a user out from a token.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Logout )( CK_SESSION_HANDLE hSession )
+   {
+      Log::begin( "C_Logout" );
+      Log::in( "C_Logout" );
+      Log::log( "C_Logout - hSession <%#02x>", hSession );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::Logout(hSession);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_Logout", rv );
+      Log::end( "C_Logout" );
+      return rv;
+   }
+
+
+   /**
+   * C_CreateObject creates a new object.
+   *
+   * @param hSession  the session's handle
+   * @param pTemplate the object's template
+   * @param ulCount   attributes in template
+   * @param phObject  gets new object's handle.
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CreateObject )( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject )
+   {
+      Log::begin( "C_CreateObject" );
+      Log::in( "C_CreateObject" );
+      Log::log( "C_CreateObject - hSession <%#02x>", hSession );
+      Log::logCK_ATTRIBUTE_PTR( "C_CreateObject", pTemplate, ulCount );
+      Log::log( "C_CreateObject - phObject <%#02x>", phObject );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::CreateObject( hSession, pTemplate, ulCount, phObject );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_CreateObject", rv );
+      Log::out( "C_CreateObject" );
+      Log::log( "C_CreateObject - phObject <%#02x> (%ld)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+      Log::end( "C_CreateObject" );
+      return rv;
+   }
+
+
+   /* C_CopyObject copies an object, creating a new object for the
+   * copy. */
+   CK_DEFINE_FUNCTION(CK_RV,C_CopyObject )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_CopyObject" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_CopyObject", rv );
+      Log::end( "C_CopyObject" );
+      return rv;
+   }
+
+
+   /**
+   * C_DestroyObject destroys an object.
+   *
+   * @param hSession the session's handle
+   * @param hObject the object's handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DestroyObject )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject )
+   {
+      Log::begin( "C_DestroyObject" );
+      Log::in( "C_DestroyObject" );
+      Log::log( "C_DestroyObject - hSession <%#02x>", hSession );
+      Log::log( "C_DestroyObject - hObject <%#02x>", hObject );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::DestroyObject( hSession, hObject );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_DestroyObject", rv );
+      Log::end( "C_DestroyObject" );
+      return rv;
+   }
+
+
+   /* C_GetObjectSize gets the size of an object in bytes. */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetObjectSize )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ULONG_PTR )
+   {
+      Log::begin( "C_GetObjectSize" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_GetObjectSize", rv );
+      Log::end( "C_GetObjectSize" );
+      return rv;
+   }
+
+
+   /**
+   * C_GetAttributeValue obtains the value of one or more object
+   * attributes.
+   *
+   * @param hSession    the session's handle
+   * @param hObject     the object's handle
+   * @param pTemplate   specifies attrs; gets vals
+   * @param ulCount     attributes in template
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetAttributeValue )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+   {
+      Log::begin( "C_GetAttributeValue" );
+      Log::in( "C_GetAttributeValue" );
+      Log::log( "C_GetAttributeValue - hSession <%#02x>", hSession );
+      Log::logCK_ATTRIBUTE_PTR( "C_GetAttributeValue", pTemplate, ulCount );
+      Log::log( "C_GetAttributeValue - hObject <%#02x>", hObject );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::GetAttributeValue(hSession,hObject,pTemplate,ulCount);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_GetAttributeValue", rv );
+      Log::out( "C_GetAttributeValue" );
+      Log::logCK_ATTRIBUTE_PTR( "C_GetAttributeValue", pTemplate, ulCount );
+      Log::end( "C_GetAttributeValue" );
+      return rv;
+   }
+
+
+   /**
+   * C_SetAttributeValue modifies the value of one or more object
+   * attributes
+   *
+   * @param   hSession    the session's handle
+   * @param   hObject     the object's handle
+   * @param   pTemplate   specifies attrs and values
+   * @param   ulCount     attributes in template
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SetAttributeValue )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+   {
+      Log::begin( "C_SetAttributeValue" );
+      Log::in( "C_SetAttributeValue" );
+      Log::log( "C_SetAttributeValue - hSession <%#02x>", hSession );
+      Log::logCK_ATTRIBUTE_PTR( "C_SetAttributeValue", pTemplate, ulCount );
+      Log::log( "C_SetAttributeValue - hObject <%#02x>", hObject );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::SetAttributeValue( hSession, hObject, pTemplate, ulCount );
+      }
+      PKCS11_CATCH( rv )
+
+      Log::logCK_RV( "C_SetAttributeValue", rv );
+      Log::end( "C_SetAttributeValue" );
+      return rv;
+   }
+
+
+   /**
+   * C_FindObjectsInit initializes a search for token and session
+   * objects that match a template.
+   *
+   * @param hSession the session's handle
+   * @param pTemplate attribute values to match
+   * @param ulCount atrs in search template
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsInit )( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+   {
+      Log::begin( "C_FindObjectsInit" );
+      Log::in( "C_FindObjectsInit" );
+      Log::log( "C_FindObjectsInit - hSession <%#02x>", hSession );
+      Log::logCK_ATTRIBUTE_PTR( "C_FindObjectsInit", pTemplate, ulCount );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::FindObjectsInit(hSession,pTemplate,ulCount);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_FindObjectsInit", rv );
+      Log::end( "C_FindObjectsInit" );
+      return rv;
+   }
+
+
+   /**
+   * C_FindObjects continues a search for token and session
+   * objects that match a template, obtaining additional object
+   * handles.
+   *
+   * @param hSession                session's handle
+   * @param phObject                gets obj. handles
+   * @param ulMaxObjectCount        max handles to get
+   * @param pulObjectCount          actual # returned
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_FindObjects )(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount )
+   {
+      Log::begin( "C_FindObjects" );
+      Log::in( "C_FindObjects" );
+      Log::log( "C_FindObjects - hSession <%#02x>", hSession );
+      Log::log( "C_FindObjects - phObject <%#02x> (%#02x)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+      Log::log( "C_FindObjects - ulMaxObjectCount <%#02x>", ulMaxObjectCount );
+      Log::log( "C_FindObjects - pulObjectCount <%#02x> (%#02x)", pulObjectCount, ( ( NULL_PTR != pulObjectCount ) ? *pulObjectCount : 0 ) );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::FindObjects( hSession, phObject, ulMaxObjectCount, pulObjectCount );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_FindObjects", rv );
+      Log::out( "C_FindObjects" );
+      Log::log( "C_FindObjects - phObject <%#02x> (%#02x)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+      Log::log( "C_FindObjects - pulObjectCount <%#02x> (%#02x)", pulObjectCount, ( ( NULL_PTR != pulObjectCount ) ? *pulObjectCount : 0 ) );
+      Log::end( "C_FindObjects" );
+      return rv;
+   }
+
+
+   /**
+   * C_FindObjectsFinal finishes a search for token and session
+   * objects.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsFinal )( CK_SESSION_HANDLE hSession )
+   {
+      Log::begin( "C_FindObjectsFinal" );
+      Log::in( "C_FindObjectsFinal" );
+      Log::log( "C_FindObjectsFinal - hSession <%#02x>", hSession );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::FindObjectsFinal(hSession);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_FindObjectsFinal", rv );
+      Log::end( "C_FindObjectsFinal" );
+      return rv;
+   }
+
+
+   /**
+   * C_EncryptInit initializes an encryption operation.
+   *
+   * @param hSession          the session's handle
+   * @param pMechanism        the encryption mechanism
+   * @param hKey              handle of encryption key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_EncryptInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      Log::begin( "C_EncryptInit" );
+      Log::in( "C_EncryptInit" );
+      Log::log( "C_EncryptInit - hSession <%#02x>", hSession );
+      Log::logCK_MECHANISM_PTR( "C_EncryptInit", pMechanism );
+      Log::log( "C_EncryptInit - hKey <%#02x>", hKey );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::EncryptInit(hSession,pMechanism,hKey);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_EncryptInit", rv );
+      Log::end( "C_EncryptInit" );
+      return rv;
+   }
+
+
+   /**
+   * C_Encrypt encrypts single-part data.
+   *
+   * @param hSession               session's handle
+   * @param pData                  the plaintext data
+   * @param ulDataLen              bytes of plaintext
+   * @param pEncryptedData         gets ciphertext
+   * @param pulEncryptedData Len   gets c-text size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Encrypt )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen )
+   {
+      Log::begin( "C_Encrypt" );
+      Log::in( "C_Encrypt" );
+      Log::log( "C_Encrypt - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pData", pData, ulDataLen );
+      Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pEncryptedData", pEncryptedData, (NULL_PTR == pulEncryptedDataLen) ? 0 : *pulEncryptedDataLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::Encrypt( hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_Encrypt", rv );
+      Log::out( "C_Encrypt" );
+      Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pEncryptedData", pEncryptedData, (NULL_PTR == pulEncryptedDataLen) ? 0 : *pulEncryptedDataLen );
+      Log::end( "C_Encrypt" );
+      return rv;
+   }
+
+
+   /**
+   * C_EncryptUpdate continues a multiple-part encryption
+   * operation.
+   *
+   * @param hSession                  session's handle
+   * @param pPart                     the plaintext data
+   * @param ulPartLen                 plaintext data len
+   * @param pEncryptedPart            gets ciphertext
+   * @param pulEncryptedPartLen       gets c-text size
+   *
+   */
+   CK_DEFINE_FUNCTION(CK_RV,C_EncryptUpdate)( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_EncryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_EncryptUpdate", rv );
+      Log::end( "C_EncryptUpdate" );
+      return rv;
+   }
+
+
+   /**
+   * C_EncryptFinal finishes a multiple-part encryption
+   * operation.
+   *
+   * @param hSession                   session handle
+   * @param pLastEncryptedPart         last c-text
+   * @param pulLastEncryptedPartLen    gets last size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_EncryptFinal )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_EncryptFinal" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_EncryptFinal", rv );
+      Log::end( "C_EncryptFinal" );
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptInit initializes a decryption operation.
+   *
+   * @param hSession the session's handle
+   * @param pMechanism the decryption mechanism
+   * @param hKey handle of decrypting key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      Log::begin( "C_DecryptInit" );
+      Log::in( "C_DecryptInit" );
+      Log::log( "C_DecryptInit - hSession <%#02x>", hSession );
+      Log::logCK_MECHANISM_PTR( "C_DecryptInit", pMechanism );
+      Log::log( "C_DecryptInit - hKey <%#02x>", hKey );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::DecryptInit( hSession, pMechanism, hKey );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_DecryptInit", rv );
+      Log::end( "C_DecryptInit" );
+      return rv;
+   }
+
+
+
+   /**
+   * C_Decrypt decrypts encrypted data in a single part.
+   *
+   * @param hSession                   session's handle
+   * @param pEncryptedData             ciphertext
+   * @param ulEncryptedDataLen         ciphertext length
+   * @param pData                      gets plaintext
+   * @param pulDataLen                 gets p-text size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Decrypt )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen )
+   {
+      Log::begin( "C_Decrypt" );
+      Log::in( "C_Decrypt" );
+      Log::log( "C_Decrypt - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pEncryptedData", pEncryptedData, ulEncryptedDataLen );
+      Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pData", pData, (NULL_PTR == pulDataLen) ? 0 : *pulDataLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::Decrypt(hSession,pEncryptedData,ulEncryptedDataLen,pData,pulDataLen);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_Decrypt", rv );
+      Log::out( "C_Decrypt" );
+      Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pData", pData, (NULL_PTR == pulDataLen) ? 0 : *pulDataLen );
+      Log::end( "C_Decrypt" );
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptUpdate continues a multiple-part decryption
+   * operation.
+   *
+   * @param hSession           session's handle
+   * @param pEncryptedPart     encrypted data
+   * @param ulEncryptedPart    input length
+   * @param pPart              gets plaintext
+   * @param pulPartLen         p-text size
+   */
+   CK_DEFINE_FUNCTION(CK_RV,C_DecryptUpdate)( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptUpdate", rv );
+      Log::end( "C_DecryptUpdate" );
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptFinal finishes a multiple-part decryption
+   * operation.
+   *
+   * @param hSession           the session's handle
+   * @param pLastPart          gets plaintext
+   * @param pulLastPartLen     p-text size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptFinal )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptFinal" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptFinal", rv );
+      Log::end( "C_DecryptFinal" );
+      return rv;
+   }
+
+
+   /**
+   * C_DigestInit initializes a message-digesting operation.
+   *
+   * @param hSession the session's handle
+   * @param pMechanism the digesting mechanism
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism )
+   {
+      Log::begin( "C_DigestInit" );
+      Log::in( "C_DigestInit" );
+      Log::log( "C_DigestInit - hSession <%#02x>", hSession );
+      Log::logCK_MECHANISM_PTR( "C_DigestInit", pMechanism );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::DigestInit(hSession,pMechanism);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_DigestInit", rv );
+      Log::end( "C_DigestInit" );
+      return rv;
+   }
+
+
+   /**
+   * C_Digest digests data in a single part.
+   *
+   * @param hSession      the session's handle
+   * @param pData         data to be digested
+   * @param ulDataLen     bytes of data to digest
+   * @param pDigest       gets the message digest
+   * @param pulDigestLen  gets digest length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Digest )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen )
+   {
+      Log::begin( "C_Digest" );
+      Log::in( "C_Digest" );
+      Log::log( "C_Digest - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_Digest - pData", pData, ulDataLen );
+      Log::logCK_UTF8CHAR_PTR( "C_Digest - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::Digest( hSession, pData, ulDataLen, pDigest, pulDigestLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_Digest", rv );
+      Log::out( "C_Digest" );
+      Log::logCK_UTF8CHAR_PTR( "C_Digest - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+      Log::end( "C_Digest" );
+      return rv;
+   }
+
+
+   /**
+   * C_DigestUpdate continues a multiple-part message-digesting
+   * operation.
+   *
+   * @param hSession       the session's handle
+   * @param pPart          data to be digested
+   * @param ulPartLen      bytes of data to be digested
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+   {
+      Log::begin( "C_DigestUpdate" );
+      Log::in( "C_DigestUpdate" );
+      Log::log( "C_DigestUpdate - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_DigestUpdate - pPart", pPart, ulPartLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::DigestUpdate( hSession, pPart, ulPartLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_DigestUpdate", rv );
+      Log::end( "C_DigestUpdate" );
+      return rv;
+   }
+
+
+   /* C_DigestKey continues a multi-part message-digesting
+   * operation, by digesting the value of a secret key as part of
+   * the data already digested. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestKey )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_DigestKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DigestKey", rv );
+      Log::end( "C_DigestKey" );
+      return rv;
+   }
+
+
+   /**
+   * C_DigestFinal finishes a multiple-part message-digesting
+   * operation.
+   *
+   * @param hSession       the session's handle
+   * @param pDigest        gets the message digest
+   * @param pulDigestLen   gets byte count of digest
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen )
+   {
+      Log::begin( "C_DigestFinal" );
+      Log::in( "C_DigestFinal" );
+      Log::log( "C_DigestFinal - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_DigestFinal - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::DigestFinal( hSession, pDigest, pulDigestLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_DigestFinal", rv );
+      Log::out( "C_DigestFinal" );
+      Log::logCK_UTF8CHAR_PTR( "C_DigestFinal - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+      Log::end( "C_DigestFinal" );
+      return rv;
+   }
+
+
+   /**
+   * C_SignInit initializes a signature (private key encryption)
+   * operation, where the signature is (will be) an appendix to
+   * the data, and plaintext cannot be recovered from the
+   * signature.
+   *
+   * @param hSession           the session's handle
+   * @param pMechanism         the signature mechanism
+   * @param hKey               handle of signature key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      Log::begin( "C_SignInit" );
+      Log::in( "C_SignInit" );
+      Log::log( "C_SignInit - hSession <%#02x>", hSession );
+      Log::logCK_MECHANISM_PTR( "C_SignInit", pMechanism );
+      Log::log( "C_SignInit - hKey <%#02x>", hKey );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::SignInit(hSession,pMechanism,hKey);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_SignInit", rv );
+      Log::end( "C_SignInit" );
+      return rv;
+   }
+
+
+   /**
+   * C_Sign signs (encrypts with private key) data in a single
+   * part, where the signature is (will be) an appendix to the
+   * data, and plaintext cannot be recovered from the signature.
+   *
+   * @param hSession          the session's handle
+   * @param pData             the data to sign
+   * @param ulDataLen         count of bytes to sign
+   * @param pSignature        gets the signature
+   * @param pulSignatureLen   gets signature length
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Sign )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen )
+   {
+      Log::begin( "C_Sign" );
+      Log::in( "C_Sign" );
+      Log::log( "C_Sign - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_Sign - pData", pData, ulDataLen );
+      Log::logCK_UTF8CHAR_PTR( "C_Sign - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::Sign( hSession, pData, ulDataLen, pSignature, pulSignatureLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_Sign", rv );
+      Log::out( "C_Sign" );
+      Log::logCK_UTF8CHAR_PTR( "C_Sign - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+      Log::end( "C_Sign" );
+      return rv;
+   }
+
+
+   /**
+   * C_SignUpdate continues a multiple-part signature operation,
+   * where the signature is (will be) an appendix to the data,
+   * and plaintext cannot be recovered from the signature.
+   *
+   * @param hSession       the session's handle
+   * @param pPart          the data to sign
+   * @param ulPartLen      count of bytes to sign
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+   {
+      Log::begin( "C_SignUpdate" );
+      Log::in( "C_SignUpdate" );
+      Log::log( "C_SignUpdate - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_SignUpdate - pPart", pPart, ulPartLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::SignUpdate(hSession,pPart,ulPartLen);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_SignUpdate", rv );
+      Log::end( "C_SignUpdate" );
+      return rv;
+   }
+
+
+   /**
+   * C_SignFinal finishes a multiple-part signature operation,
+   * returning the signature.
+   *
+   * @param hSession           the session's handle
+   * @param pSignature         gets the signature
+   * @param pulSignatureLen    gets signature length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen )
+   {
+      Log::begin( "C_SignFinal" );
+      Log::in( "C_SignFinal" );
+      Log::log( "C_SignFinal - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_SignFinal - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv =  Slot::SignFinal(hSession,pSignature,pulSignatureLen);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_SignFinal", rv );
+      Log::out( "C_SignFinal" );
+      Log::logCK_UTF8CHAR_PTR( "C_SignFinal - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+      Log::end( "C_SignFinal" );
+      return rv;
+   }
+
+
+   /* C_SignRecoverInit initializes a signature operation, where
+   * the data can be recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignRecoverInit )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_SignRecoverInit" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SignRecoverInit", rv );
+      Log::end( "C_SignRecoverInit" );
+      return rv;
+   }
+
+
+   /* C_SignRecover signs data in a single operation, where the data can be recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignRecover )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_SignRecover" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SignRecover", rv );
+      Log::end( "C_SignRecover" );
+      return rv;
+   }
+
+
+   /**
+   * C_VerifyInit initializes a verification operation, where the
+   * signature is an appendix to the data, and plaintext cannot
+   * cannot be recovered from the signature (e.g. DSA).
+   *
+   * @param hSession      the session's handle
+   * @param pMechanism    the verification mechanism
+   * @param hKey          verification key
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+   {
+      Log::begin( "C_VerifyInit" );
+      Log::in( "C_VerifyInit" );
+      Log::log( "C_VerifyInit - hSession <%#02x>", hSession );
+      Log::logCK_MECHANISM_PTR( "C_VerifyInit", pMechanism );
+      Log::log( "C_VerifyInit - hKey <%#02x>", hKey );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::VerifyInit( hSession, pMechanism, hKey );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_VerifyInit", rv );
+      Log::end( "C_VerifyInit" );
+      return rv;
+   }
+
+
+   /**
+   * C_Verify verifies a signature in a single-part operation,
+   * where the signature is an appendix to the data, and plaintext
+   * cannot be recovered from the signature.
+   *
+   * @param hSession           the session's handle
+   * @param pData              signed data
+   * @param ulDataLen          length of signed data
+   * @param pSignature         signature
+   * @param ulSignatureLen     signature length
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_Verify )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen )
+   {
+      Log::begin( "C_Verify" );
+      Log::in( "C_Verify" );
+      Log::log( "C_Verify - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_Verify - pData", pData, ulDataLen );
+      Log::logCK_UTF8CHAR_PTR( "C_Verify - pSignature", pSignature, ulSignatureLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::Verify(hSession,pData,ulDataLen,pSignature,ulSignatureLen);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_Verify", rv );
+      Log::out( "C_Verify" );
+      Log::logCK_UTF8CHAR_PTR( "C_Verify - pSignature", pSignature, ulSignatureLen );
+      Log::end( "C_Verify" );
+      return rv;
+   }
+
+
+   /* C_VerifyUpdate continues a multiple-part verification
+   * operation, where the signature is an appendix to the data,
+   * and plaintext cannot be recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+   {
+      Log::begin( "C_VerifyUpdate" );
+      Log::in( "C_VerifyUpdate" );
+      Log::log( "C_VerifyUpdate - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_VerifyUpdate - pPart", pPart, ulPartLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::VerifyUpdate(hSession,pPart,ulPartLen);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_VerifyUpdate", rv );
+      Log::end( "C_VerifyUpdate" );
+      return rv;
+   }
+
+
+   /* C_VerifyFinal finishes a multiple-part verification
+   * operation, checking the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen )
+   {
+      Log::begin( "C_VerifyFinal" );
+      Log::in( "C_VerifyFinal" );
+      Log::log( "C_VerifyFinal - hSession <%#02x>", hSession );
+      Log::logCK_UTF8CHAR_PTR( "C_VerifyFinal - pSignature", pSignature, ulSignatureLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::VerifyFinal(hSession,pSignature,ulSignatureLen);
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_VerifyFinal", rv );
+      Log::end( "C_VerifyFinal" );
+      return rv;
+   }
+
+
+   /* C_VerifyRecoverInit initializes a signature verification
+   * operation, where the data is recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyRecoverInit )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE )
+   {
+      Log::begin( "C_VerifyRecoverInit" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_VerifyRecoverInit", rv );
+      Log::end( "C_VerifyRecoverInit" );
+      return rv;
+   }
+
+
+   /* C_VerifyRecover verifies a signature in a single-part
+   * operation, where the data is recovered from the signature. */
+   CK_DEFINE_FUNCTION( CK_RV, C_VerifyRecover )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_VerifyRecover" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_VerifyRecover", rv );
+      Log::end( "C_VerifyRecover" );
+      return rv;
+   }
+
+
+   /* C_DigestEncryptUpdate continues a multiple-part digesting and encryption operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DigestEncryptUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DigestEncryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DigestEncryptUpdate", rv );
+      Log::end( "C_DigestEncryptUpdate" );
+      return rv;
+   }
+
+
+   /* C_DecryptDigestUpdate continues a multiple-part decryption and digesting operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptDigestUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptDigestUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptDigestUpdate", rv );
+      Log::end( "C_DecryptDigestUpdate" );
+      return rv;
+   }
+
+
+   /* C_SignEncryptUpdate continues a multiple-part signing and encryption operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_SignEncryptUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_SignEncryptUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SignEncryptUpdate", rv );
+      Log::end( "C_SignEncryptUpdate" );
+      return rv;
+   }
+
+
+   /**
+   * C_DecryptVerifyUpdate continues a multiple-part decryption and verify operation. */
+   CK_DEFINE_FUNCTION( CK_RV, C_DecryptVerifyUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR , CK_ULONG_PTR )
+   {
+      Log::begin( "C_DecryptVerifyUpdate" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DecryptVerifyUpdate", rv );
+      Log::end( "C_DecryptVerifyUpdate" );
+      return rv;
+   }
+
+
+   /**
+   * C_GenerateKey generates a secret key, creating a new key object.
+   *
+   * @param    hSession,    the session's handle
+   * @param    pMechanism   key generation mech.
+   * @param    pTemplate    template for new key
+   * @param    ulCount      # of attrs in template
+   * @param    phKey        gets handle of new key
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GenerateKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_GenerateKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_GenerateKey", rv );
+      Log::end( "C_GenerateKey" );
+      return rv;
+   }
+
+
+   /**
+   * C_GenerateKeyPair generates a public-key/private-key pair,
+   * creating new key objects.
+   *
+   * @param hSession,                    session handle
+   * @param pMechanism,                  key-gen mech.
+   * @param pPublicKeyTemplate,          template for pub. key
+   * @param ulPublicKeyAttributeCount,   # pub. attrs.
+   * @param pPrivateKeyTemplate,         template for priv. key
+   * @param ulPrivateKeyAttributeCount,  # priv. attrs.
+   * @param phPublicKey,                 gets pub. key handle
+   * @param phPrivateKey                 gets priv key handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GenerateKeyPair )(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey )
+   {
+      Log::begin( "C_GenerateKeyPair" );
+      Log::in( "C_GenerateKeyPair" );
+      Log::log( "C_GenerateKeyPair - hSession <%#02x>", hSession );
+      Log::logCK_MECHANISM_PTR( "C_GenerateKeyPair", pMechanism );
+      Log::logCK_ATTRIBUTE_PTR( "C_GenerateKeyPair", pPublicKeyTemplate, ulPublicKeyAttributeCount );
+      Log::logCK_ATTRIBUTE_PTR( "C_GenerateKeyPair", pPrivateKeyTemplate, ulPrivateKeyAttributeCount );
+      Log::log( "C_GenerateKeyPair - phPublicKey <%#02x>", (phPublicKey == NULL_PTR) ? 0 : *phPublicKey );
+      Log::log( "C_GenerateKeyPair - phPrivateKey <%#02x>", (phPrivateKey == NULL_PTR) ? 0 : *phPrivateKey );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::GenerateKeyPair( hSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_GenerateKeyPair", rv );
+      Log::out( "C_GenerateKeyPair" );
+      Log::log( "C_GenerateKeyPair - phPublicKey <%#02x>", (phPublicKey == NULL_PTR) ? 0 : *phPublicKey );
+      Log::log( "C_GenerateKeyPair - phPrivateKey <%#02x>", (phPrivateKey == NULL_PTR) ? 0 : *phPrivateKey );
+      Log::end( "C_GenerateKeyPair" );
+      return rv;
+   }
+
+
+   /**
+   * C_WrapKey wraps (i.e., encrypts) a key.
+   *
+   * @param hSession              the session's handle
+   * @param pMechanism            the wrapping mechanism
+   * @param hWrappingKey          wrapping key
+   * @param hKey                  key to be wrapped
+   * @param pWrapperKey           gets wrapped key
+   * @param pulWrappedKeyLen      gets wrapped key size
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_WrapKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+   {
+      Log::begin( "C_WrapKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_WrapKey", rv );
+      Log::end( "C_WrapKey" );
+      return rv;
+   }
+
+
+   /**
+   * C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+   * key object.
+   *
+   * @param   hSession           session's handle
+   * @param   pMechanism         unwrapping mech.
+   * @param   hUnwrappingKey     unwrapping key
+   * @param   pWrappedKey        the wrapped key
+   * @param   ulWrappedKeyLen    wrapped key len
+   * @param   pTemplate          new key template
+   * @param   ulAttributeCount   template length
+   * @param   phKey              gets new handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_UnwrapKey )(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_UnwrapKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_UnwrapKey", rv );
+      Log::end( "C_UnwrapKey" );
+      return rv;
+   }
+
+
+   /**
+   * C_DeriveKey derives a key from a base key, creating a new key
+   * object.
+   *
+   * @param hSession              session's handle
+   * @param pMechanism            key deriv. mech.
+   * @param hBaseKey              base key
+   * @param pTemplate             new key template
+   * @param ulAttributeCount      template length
+   * @param phKey                 gets new handle
+   *
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_DeriveKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+   {
+      Log::begin( "C_DeriveKey" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_DeriveKey", rv );
+      Log::end( "C_DeriveKey" );
+      return rv;
+   }
+
+
+   /**
+   * C_SeedRandom mixes additional seed material into the token's
+   * random number generator.
+   *
+   * @param hSession   the session's handle
+   * @param pSeed      the seed material
+   * @param ulSeedLen  length of seed material
+   */
+   CK_DEFINE_FUNCTION( CK_RV,C_SeedRandom )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG )
+   {
+      Log::begin( "C_SeedRandom" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_RANDOM_SEED_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_SeedRandom", rv );
+      Log::end( "C_SeedRandom" );
+      return rv;
+   }
+
+
+   /**
+   * C_GenerateRandom generates random data.
+   *
+   * @param hSession       the session's handle
+   * @param RandomData     receives the random data
+   * @param ulRandomLen    # of bytes to generate
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GenerateRandom )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen )
+   {
+      Log::begin( "C_GenerateRandom" );
+      Log::in( "C_GenerateRandom" );
+      Log::logCK_UTF8CHAR_PTR( "C_GenerateRandom", pRandomData, ulRandomLen );
+
+      CK_RV rv = CKR_OK;
+      PKCS11_TRY
+      {
+         rv = Slot::GenerateRandom( hSession, pRandomData, ulRandomLen );
+      }
+      PKCS11_CATCH(rv)
+
+      Log::logCK_RV( "C_GenerateRandom", rv );
+      Log::out( "C_GenerateRandom" );
+      Log::logCK_UTF8CHAR_PTR( "C_GenerateRandom", pRandomData, ulRandomLen );
+      Log::end( "C_GenerateRandom" );
+      return rv;
+   }
+
+
+   /**
+   * C_GetFunctionStatus is a legacy function; it obtains an
+   * updated status of a function running in parallel with an
+   * application.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_GetFunctionStatus )( CK_SESSION_HANDLE )
+   {
+      Log::begin( "C_GetFunctionStatus" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_GetFunctionStatus", rv );
+      Log::end( "C_GetFunctionStatus" );
+      return rv;
+   }
+
+
+   /**
+   * C_CancelFunction is a legacy function; it cancels a function
+   * running in parallel.
+   *
+   * @param hSession the session's handle
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_CancelFunction )( CK_SESSION_HANDLE )
+   {
+      Log::begin( "C_CancelFunction" );
+
+      CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+      if( _isInitialized )
+      {
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+      }
+
+      Log::logCK_RV( "C_CancelFunction", rv );
+      Log::end( "C_CancelFunction" );
+      return rv;
+   }
+
+   /* Functions added in for Cryptoki Version 2.01 or later */
+
+   /**
+   * C_WaitForSlotEvent waits for a slot event (token insertion,
+   * removal, etc.) to occur.
+   *
+   * @param flags      blocking/nonblocking flag
+   * @param pSlot      location that receives the slot ID
+   * @param pReserved  reserved.  Should be NULL_PTR
+   */
+   CK_DEFINE_FUNCTION( CK_RV, C_WaitForSlotEvent )( CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved )
+   {
+      //Log::begin("C_WaitForSlotEvent");
+
+      // Not Initialized
+      if (!_isInitialized)
+      {
+         Log::error( "C_WaitForSlotEvent", "CKR_CRYPTOKI_NOT_INITIALIZED" );
+         return CKR_CRYPTOKI_NOT_INITIALIZED;
+      }
+
+      if((pReserved != NULL_PTR) || (pSlot == NULL_PTR))
+      {
+         Log::error( "C_WaitForSlotEvent", "CKR_ARGUMENTS_BAD" );
+         return CKR_ARGUMENTS_BAD;
+      }
+
+      *pSlot = CK_UNAVAILABLE_INFORMATION;// -1;
+
+#ifdef INCLUDE_EVENTING
+      CMutex mut("a");
+
+      CK_SLOT_ID sid = 0;
+      for(;sid<CONFIG_MAX_SLOT;sid++)
+      {
+         Slot* slot = Application::_slotCache[sid];
+         if(slot != NULL_PTR)
+         {
+            if(slot->GetEvent())
+            {
+               *pSlot = slot->GetSlotId();
+               slot->SetEvent(CK_FALSE);
+               break;
+            }
+         }
+      }
+
+      mut.release();
+
+      if(*pSlot == (CK_SLOT_ID)-1)
+      {
+
+         if(flags & CKF_DONT_BLOCK)
+         {
+            //Log::log("CKR_NO_EVENT");
+            return CKR_NO_EVENT;
+         }
+         else
+         {
+            CryptokiEvent.Wait();
+            //Log::log("CryptokiEvent signal received in WaitForSlotEvent..");
+
+            CMutex mut("b");
+
+            CK_SLOT_ID sid = 0;
+
+            for(;sid<CONFIG_MAX_SLOT;sid++)
+            {
+               Slot* slot = Application::_slotCache[sid];
+
+               if(slot != NULL_PTR)
+               {
+                  if(slot->GetEvent())
+                  {
+                     *pSlot = slot->GetSlotId();
+                     Log::log( "C_WaitForSlotEvent - SlotID <%#02x>\n", *pSlot );
+                     slot->SetEvent(CK_FALSE);
+                     break;
+                  }
+               }
+            }
+
+            mut.release();
+
+            if(*pSlot == (CK_SLOT_ID)-1)
+            {
+               //Log::log("CKR_NO_EVENT");
+               return CKR_NO_EVENT;
+            }
+         }
+      }
+
+      return CKR_OK;
+#else
+      return CKR_NO_EVENT;
+#endif
+   }
+
+} // extern "C"

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,300 @@
+/* pkcs11.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined.  These
+ * macros are described below, and typical definitions for them
+ * are also given.  Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for Cryptoki structures should be set.  The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this.  You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object.  It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable Cryptoki library function definition out of a
+ * return type and a function name.  It should be used in the
+ * following fashion to define the exposed Cryptoki functions in
+ * a Cryptoki library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ *   CK_VOID_PTR pReserved
+ * )
+ * {
+ *   ...
+ * }
+ *
+ * If you're using Microsoft Developer Studio 5.0 to define a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ *   returnType __declspec(dllexport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to define a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ *   returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ *   returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name.  It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ *   CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ *   returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ *   returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ *   returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name.  It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ *   returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ *   returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ *   returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV.  It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ *   returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ *   returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ *   returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y)      x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST  1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+  extern CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points.  That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST  1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+  typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points.  A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library.  This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+  __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+  CK_VERSION    version;  /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,903 @@
+/* pkcs11f.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This header file contains pretty much everything about all the */
+/* Cryptoki function prototypes.  Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_VOID_PTR   pInitArgs  /* if this is not NULL_PTR, it gets
+                            * cast to CK_C_INITIALIZE_ARGS_PTR
+                            * and dereferenced */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_VOID_PTR   pReserved  /* reserved.  Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_INFO_PTR   pInfo  /* location that receives information */
+);
+#endif
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_FUNCTION_LIST_PTR_PTR ppFunctionList  /* receives pointer to
+                                            * function list */
+);
+#endif
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_BBOOL       tokenPresent,  /* only slots with tokens? */
+  CK_SLOT_ID_PTR pSlotList,     /* receives array of slot IDs */
+  CK_ULONG_PTR   pulCount       /* receives number of slots */
+);
+#endif
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID       slotID,  /* the ID of the slot */
+  CK_SLOT_INFO_PTR pInfo    /* receives the slot information */
+);
+#endif
+
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID        slotID,  /* ID of the token's slot */
+  CK_TOKEN_INFO_PTR pInfo    /* receives the token information */
+);
+#endif
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID            slotID,          /* ID of token's slot */
+  CK_MECHANISM_TYPE_PTR pMechanismList,  /* gets mech. array */
+  CK_ULONG_PTR          pulCount         /* gets # of mechs. */
+);
+#endif
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID            slotID,  /* ID of the token's slot */
+  CK_MECHANISM_TYPE     type,    /* type of mechanism */
+  CK_MECHANISM_INFO_PTR pInfo    /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+  CK_SLOT_ID      slotID,    /* ID of the token's slot */
+  CK_UTF8CHAR_PTR pPin,      /* the SO's initial PIN */
+  CK_ULONG        ulPinLen,  /* length in bytes of the PIN */
+  CK_UTF8CHAR_PTR pLabel     /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_UTF8CHAR_PTR   pPin,      /* the normal user's PIN */
+  CK_ULONG          ulPinLen   /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_UTF8CHAR_PTR   pOldPin,   /* the old PIN */
+  CK_ULONG          ulOldLen,  /* length of the old PIN */
+  CK_UTF8CHAR_PTR   pNewPin,   /* the new PIN */
+  CK_ULONG          ulNewLen   /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID            slotID,        /* the slot's ID */
+  CK_FLAGS              flags,         /* from CK_SESSION_INFO */
+  CK_VOID_PTR           pApplication,  /* passed to callback */
+  CK_NOTIFY             Notify,        /* callback function */
+  CK_SESSION_HANDLE_PTR phSession      /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SLOT_ID     slotID  /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE   hSession,  /* the session's handle */
+  CK_SESSION_INFO_PTR pInfo      /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,             /* session's handle */
+  CK_BYTE_PTR       pOperationState,      /* gets state */
+  CK_ULONG_PTR      pulOperationStateLen  /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR      pOperationState,      /* holds state */
+  CK_ULONG         ulOperationStateLen,  /* holds state length */
+  CK_OBJECT_HANDLE hEncryptionKey,       /* en/decryption key */
+  CK_OBJECT_HANDLE hAuthenticationKey    /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_USER_TYPE      userType,  /* the user type */
+  CK_UTF8CHAR_PTR   pPin,      /* the user's PIN */
+  CK_ULONG          ulPinLen   /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,   /* the object's template */
+  CK_ULONG          ulCount,     /* attributes in template */
+  CK_OBJECT_HANDLE_PTR phObject  /* gets new object's handle. */
+);
+#endif
+
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,    /* the session's handle */
+  CK_OBJECT_HANDLE     hObject,     /* the object's handle */
+  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new object */
+  CK_ULONG             ulCount,     /* attributes in template */
+  CK_OBJECT_HANDLE_PTR phNewObject  /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_OBJECT_HANDLE  hObject    /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_OBJECT_HANDLE  hObject,   /* the object's handle */
+  CK_ULONG_PTR      pulSize    /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_OBJECT_HANDLE  hObject,    /* the object's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs; gets vals */
+  CK_ULONG          ulCount     /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_OBJECT_HANDLE  hObject,    /* the object's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs and values */
+  CK_ULONG          ulCount     /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_ATTRIBUTE_PTR  pTemplate,  /* attribute values to match */
+  CK_ULONG          ulCount     /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE    hSession,          /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject,          /* gets obj. handles */
+ CK_ULONG             ulMaxObjectCount,  /* max handles to get */
+ CK_ULONG_PTR         pulObjectCount     /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the encryption mechanism */
+  CK_OBJECT_HANDLE  hKey         /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pData,               /* the plaintext data */
+  CK_ULONG          ulDataLen,           /* bytes of plaintext */
+  CK_BYTE_PTR       pEncryptedData,      /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedDataLen  /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,           /* session's handle */
+  CK_BYTE_PTR       pPart,              /* the plaintext data */
+  CK_ULONG          ulPartLen,          /* plaintext data len */
+  CK_BYTE_PTR       pEncryptedPart,     /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,                /* session handle */
+  CK_BYTE_PTR       pLastEncryptedPart,      /* last c-text */
+  CK_ULONG_PTR      pulLastEncryptedPartLen  /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the decryption mechanism */
+  CK_OBJECT_HANDLE  hKey         /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,           /* session's handle */
+  CK_BYTE_PTR       pEncryptedData,     /* ciphertext */
+  CK_ULONG          ulEncryptedDataLen, /* ciphertext length */
+  CK_BYTE_PTR       pData,              /* gets plaintext */
+  CK_ULONG_PTR      pulDataLen          /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pEncryptedPart,      /* encrypted data */
+  CK_ULONG          ulEncryptedPartLen,  /* input length */
+  CK_BYTE_PTR       pPart,               /* gets plaintext */
+  CK_ULONG_PTR      pulPartLen           /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,       /* the session's handle */
+  CK_BYTE_PTR       pLastPart,      /* gets plaintext */
+  CK_ULONG_PTR      pulLastPartLen  /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism  /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,     /* the session's handle */
+  CK_BYTE_PTR       pData,        /* data to be digested */
+  CK_ULONG          ulDataLen,    /* bytes of data to digest */
+  CK_BYTE_PTR       pDigest,      /* gets the message digest */
+  CK_ULONG_PTR      pulDigestLen  /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pPart,     /* data to be digested */
+  CK_ULONG          ulPartLen  /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_OBJECT_HANDLE  hKey       /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,     /* the session's handle */
+  CK_BYTE_PTR       pDigest,      /* gets the message digest */
+  CK_ULONG_PTR      pulDigestLen  /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the signature mechanism */
+  CK_OBJECT_HANDLE  hKey         /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pData,           /* the data to sign */
+  CK_ULONG          ulDataLen,       /* count of bytes to sign */
+  CK_BYTE_PTR       pSignature,      /* gets the signature */
+  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pPart,     /* the data to sign */
+  CK_ULONG          ulPartLen  /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pSignature,      /* gets the signature */
+  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,   /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism, /* the signature mechanism */
+  CK_OBJECT_HANDLE  hKey        /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pData,           /* the data to sign */
+  CK_ULONG          ulDataLen,       /* count of bytes to sign */
+  CK_BYTE_PTR       pSignature,      /* gets the signature */
+  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ *  cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */
+  CK_OBJECT_HANDLE  hKey         /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,       /* the session's handle */
+  CK_BYTE_PTR       pData,          /* signed data */
+  CK_ULONG          ulDataLen,      /* length of signed data */
+  CK_BYTE_PTR       pSignature,     /* signature */
+  CK_ULONG          ulSignatureLen  /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pPart,     /* signed data */
+  CK_ULONG          ulPartLen  /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,       /* the session's handle */
+  CK_BYTE_PTR       pSignature,     /* signature to verify */
+  CK_ULONG          ulSignatureLen  /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */
+  CK_OBJECT_HANDLE  hKey         /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_BYTE_PTR       pSignature,      /* signature to verify */
+  CK_ULONG          ulSignatureLen,  /* signature length */
+  CK_BYTE_PTR       pData,           /* gets signed data */
+  CK_ULONG_PTR      pulDataLen       /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pPart,               /* the plaintext data */
+  CK_ULONG          ulPartLen,           /* plaintext length */
+  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */
+  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */
+  CK_BYTE_PTR       pPart,               /* gets plaintext */
+  CK_ULONG_PTR      pulPartLen           /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pPart,               /* the plaintext data */
+  CK_ULONG          ulPartLen,           /* plaintext length */
+  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */
+  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,            /* session's handle */
+  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */
+  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */
+  CK_BYTE_PTR       pPart,               /* gets plaintext */
+  CK_ULONG_PTR      pulPartLen           /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,    /* the session's handle */
+  CK_MECHANISM_PTR     pMechanism,  /* key generation mech. */
+  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new key */
+  CK_ULONG             ulCount,     /* # of attrs in template */
+  CK_OBJECT_HANDLE_PTR phKey        /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,                    /* session
+                                                     * handle */
+  CK_MECHANISM_PTR     pMechanism,                  /* key-gen
+                                                     * mech. */
+  CK_ATTRIBUTE_PTR     pPublicKeyTemplate,          /* template
+                                                     * for pub.
+                                                     * key */
+  CK_ULONG             ulPublicKeyAttributeCount,   /* # pub.
+                                                     * attrs. */
+  CK_ATTRIBUTE_PTR     pPrivateKeyTemplate,         /* template
+                                                     * for priv.
+                                                     * key */
+  CK_ULONG             ulPrivateKeyAttributeCount,  /* # priv.
+                                                     * attrs. */
+  CK_OBJECT_HANDLE_PTR phPublicKey,                 /* gets pub.
+                                                     * key
+                                                     * handle */
+  CK_OBJECT_HANDLE_PTR phPrivateKey                 /* gets
+                                                     * priv. key
+                                                     * handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,        /* the session's handle */
+  CK_MECHANISM_PTR  pMechanism,      /* the wrapping mechanism */
+  CK_OBJECT_HANDLE  hWrappingKey,    /* wrapping key */
+  CK_OBJECT_HANDLE  hKey,            /* key to be wrapped */
+  CK_BYTE_PTR       pWrappedKey,     /* gets wrapped key */
+  CK_ULONG_PTR      pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,          /* session's handle */
+  CK_MECHANISM_PTR     pMechanism,        /* unwrapping mech. */
+  CK_OBJECT_HANDLE     hUnwrappingKey,    /* unwrapping key */
+  CK_BYTE_PTR          pWrappedKey,       /* the wrapped key */
+  CK_ULONG             ulWrappedKeyLen,   /* wrapped key len */
+  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */
+  CK_ULONG             ulAttributeCount,  /* template length */
+  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE    hSession,          /* session's handle */
+  CK_MECHANISM_PTR     pMechanism,        /* key deriv. mech. */
+  CK_OBJECT_HANDLE     hBaseKey,          /* base key */
+  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */
+  CK_ULONG             ulAttributeCount,  /* template length */
+  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,  /* the session's handle */
+  CK_BYTE_PTR       pSeed,     /* the seed material */
+  CK_ULONG          ulSeedLen  /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession,    /* the session's handle */
+  CK_BYTE_PTR       RandomData,  /* receives the random data */
+  CK_ULONG          ulRandomLen  /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_SESSION_HANDLE hSession  /* the session's handle */
+);
+#endif
+
+/* Functions added in for Cryptoki Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+  CK_FLAGS flags,        /* blocking/nonblocking flag */
+  CK_SLOT_ID_PTR pSlot,  /* location that receives the slot ID */
+  CK_VOID_PTR pRserved   /* reserved.  Should be NULL_PTR */
+);
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,1701 @@
+/* pkcs11t.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file. */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE CK_FALSE
+#endif
+
+#ifndef TRUE
+#define TRUE CK_TRUE
+#endif
+#endif
+
+typedef unsigned short CK_USHORT;
+
+/* an unsigned 8-bit value */
+typedef unsigned char     CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE           CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE           CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE           CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int          CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG          CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE    0
+
+
+typedef CK_BYTE     CK_PTR   CK_BYTE_PTR;
+typedef CK_CHAR     CK_PTR   CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR   CK_UTF8CHAR_PTR;
+typedef CK_ULONG    CK_PTR   CK_ULONG_PTR;
+typedef void        CK_PTR   CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+
+typedef struct CK_VERSION {
+  CK_BYTE       major;  /* integer portion of version number */
+  CK_BYTE       minor;  /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+  /* manufacturerID and libraryDecription have been changed from
+   * CK_CHAR to CK_UTF8CHAR for v2.10 */
+  CK_VERSION    cryptokiVersion;     /* Cryptoki interface ver */
+  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */
+  CK_FLAGS      flags;               /* must be zero */
+
+  /* libraryDescription and libraryVersion are new for v2.0 */
+  CK_UTF8CHAR   libraryDescription[32];  /* blank padded */
+  CK_VERSION    libraryVersion;          /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR    CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER       0
+
+
+typedef CK_ULONG          CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+  /* slotDescription and manufacturerID have been changed from
+   * CK_CHAR to CK_UTF8CHAR for v2.10 */
+  CK_UTF8CHAR   slotDescription[64];  /* blank padded */
+  CK_UTF8CHAR   manufacturerID[32];   /* blank padded */
+  CK_FLAGS      flags;
+
+  /* hardwareVersion and firmwareVersion are new for v2.0 */
+  CK_VERSION    hardwareVersion;  /* version of hardware */
+  CK_VERSION    firmwareVersion;  /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ *      Bit Flag              Mask        Meaning
+ */
+#define CKF_TOKEN_PRESENT     0x00000001  /* a token is there */
+#define CKF_REMOVABLE_DEVICE  0x00000002  /* removable devices*/
+#define CKF_HW_SLOT           0x00000004  /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+  /* label, manufacturerID, and model have been changed from
+   * CK_CHAR to CK_UTF8CHAR for v2.10 */
+  CK_UTF8CHAR   label[32];           /* blank padded */
+  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */
+  CK_UTF8CHAR   model[16];           /* blank padded */
+  CK_CHAR       serialNumber[16];    /* blank padded */
+  CK_FLAGS      flags;               /* see below */
+
+  /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+   * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+   * changed from CK_USHORT to CK_ULONG for v2.0 */
+  CK_ULONG      ulMaxSessionCount;     /* max open sessions */
+  CK_ULONG      ulSessionCount;        /* sess. now open */
+  CK_ULONG      ulMaxRwSessionCount;   /* max R/W sessions */
+  CK_ULONG      ulRwSessionCount;      /* R/W sess. now open */
+  CK_ULONG      ulMaxPinLen;           /* in bytes */
+  CK_ULONG      ulMinPinLen;           /* in bytes */
+  CK_ULONG      ulTotalPublicMemory;   /* in bytes */
+  CK_ULONG      ulFreePublicMemory;    /* in bytes */
+  CK_ULONG      ulTotalPrivateMemory;  /* in bytes */
+  CK_ULONG      ulFreePrivateMemory;   /* in bytes */
+
+  /* hardwareVersion, firmwareVersion, and time are new for
+   * v2.0 */
+  CK_VERSION    hardwareVersion;       /* version of hardware */
+  CK_VERSION    firmwareVersion;       /* version of firmware */
+  CK_CHAR       utcTime[16];           /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ *      Bit Flag                    Mask        Meaning
+ */
+#define CKF_RNG                     0x00000001  /* has random #
+                                                 * generator */
+#define CKF_WRITE_PROTECTED         0x00000002  /* token is
+                                                 * write-
+                                                 * protected */
+#define CKF_LOGIN_REQUIRED          0x00000004  /* user must
+                                                 * login */
+#define CKF_USER_PIN_INITIALIZED    0x00000008  /* normal user's
+                                                 * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0.  If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED  0x00000020
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0.  If it is set, that means
+ * that the token has some sort of clock.  The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN          0x00000040
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0.  If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0.  If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS  0x00000200
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED       0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. This flag is deprecated in v2.11 and
+   onwards. */
+#define CKF_SECONDARY_AUTHENTICATION  0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW       0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY       0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED          0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED   0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW         0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY         0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED            0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED     0x00800000
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session */
+typedef CK_ULONG          CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO    0
+/* Normal user */
+#define CKU_USER  1
+/* Context specific (added in v2.20) */
+#define CKU_CONTEXT_SPECIFIC   2
+
+/* Not defined in PKCS#11, Add by KS */
+#define CKU_NONE 99
+#define CO_OBJECT_HANDLE_MASK  0x0000FFFF
+#define CO_SESSION_OBJECT      0x00000000
+#define CO_TOKEN_OBJECT        0x10000000
+
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_STATE;
+#define CKS_RO_PUBLIC_SESSION  0
+#define CKS_RO_USER_FUNCTIONS  1
+#define CKS_RW_PUBLIC_SESSION  2
+#define CKS_RW_USER_FUNCTIONS  3
+#define CKS_RW_SO_FUNCTIONS    4
+
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+  CK_SLOT_ID    slotID;
+  CK_STATE      state;
+  CK_FLAGS      flags;          /* see below */
+
+  /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+   * v2.0 */
+  CK_ULONG      ulDeviceError;  /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ *      Bit Flag                Mask        Meaning
+ */
+#define CKF_RW_SESSION          0x00000002  /* session is r/w */
+#define CKF_SERIAL_SESSION      0x00000004  /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object  */
+typedef CK_ULONG          CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes.  It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+/* CKO_MECHANISM is new for v2.20 */
+#define CKO_DATA              0x00000000
+#define CKO_CERTIFICATE       0x00000001
+#define CKO_PUBLIC_KEY        0x00000002
+#define CKO_PRIVATE_KEY       0x00000003
+#define CKO_SECRET_KEY        0x00000004
+#define CKO_HW_FEATURE        0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_MECHANISM         0x00000007
+#define CKO_VENDOR_DEFINED    0x80000000
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG          CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+/* CKH_USER_INTERFACE is new for v2.20 */
+#define CKH_MONOTONIC_COUNTER  0x00000001
+#define CKH_CLOCK           0x00000002
+#define CKH_USER_INTERFACE  0x00000003
+#define CKH_VENDOR_DEFINED  0x80000000
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG          CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA             0x00000000
+#define CKK_DSA             0x00000001
+#define CKK_DH              0x00000002
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA           0x00000003
+#define CKK_EC              0x00000003
+#define CKK_X9_42_DH        0x00000004
+#define CKK_KEA             0x00000005
+
+#define CKK_GENERIC_SECRET  0x00000010
+#define CKK_RC2             0x00000011
+#define CKK_RC4             0x00000012
+#define CKK_DES             0x00000013
+#define CKK_DES2            0x00000014
+#define CKK_DES3            0x00000015
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST            0x00000016
+#define CKK_CAST3           0x00000017
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5           0x00000018
+#define CKK_CAST128         0x00000018
+#define CKK_RC5             0x00000019
+#define CKK_IDEA            0x0000001A
+#define CKK_SKIPJACK        0x0000001B
+#define CKK_BATON           0x0000001C
+#define CKK_JUNIPER         0x0000001D
+#define CKK_CDMF            0x0000001E
+#define CKK_AES             0x0000001F
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKK_BLOWFISH        0x00000020
+#define CKK_TWOFISH         0x00000021
+
+#define CKK_VENDOR_DEFINED  0x80000000
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG          CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+/* CKC_WTLS is new for v2.20 */
+#define CKC_X_509           0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
+#define CKC_WTLS            0x00000002
+#define CKC_VENDOR_DEFINED  0x80000000
+
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
+
+/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
+   consists of an array of values. */
+#define CKF_ARRAY_ATTRIBUTE    0x40000000
+
+/* The following attribute types are defined: */
+#define CKA_CLASS              0x00000000
+#define CKA_TOKEN              0x00000001
+#define CKA_PRIVATE            0x00000002
+#define CKA_LABEL              0x00000003
+#define CKA_APPLICATION        0x00000010
+#define CKA_VALUE              0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID          0x00000012
+
+#define CKA_CERTIFICATE_TYPE   0x00000080
+#define CKA_ISSUER             0x00000081
+#define CKA_SERIAL_NUMBER      0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER          0x00000083
+#define CKA_OWNER              0x00000084
+#define CKA_ATTR_TYPES         0x00000085
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED            0x00000086
+
+/* CKA_CERTIFICATE_CATEGORY ...
+ * CKA_CHECK_VALUE are new for v2.20 */
+#define CKA_CERTIFICATE_CATEGORY        0x00000087
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN   0x00000088
+#define CKA_URL                         0x00000089
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008A
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008B
+#define CKA_CHECK_VALUE                 0x00000090
+
+#define CKA_KEY_TYPE           0x00000100
+#define CKA_SUBJECT            0x00000101
+#define CKA_ID                 0x00000102
+#define CKA_SENSITIVE          0x00000103
+#define CKA_ENCRYPT            0x00000104
+#define CKA_DECRYPT            0x00000105
+#define CKA_WRAP               0x00000106
+#define CKA_UNWRAP             0x00000107
+#define CKA_SIGN               0x00000108
+#define CKA_SIGN_RECOVER       0x00000109
+#define CKA_VERIFY             0x0000010A
+#define CKA_VERIFY_RECOVER     0x0000010B
+#define CKA_DERIVE             0x0000010C
+#define CKA_START_DATE         0x00000110
+#define CKA_END_DATE           0x00000111
+#define CKA_MODULUS            0x00000120
+#define CKA_MODULUS_BITS       0x00000121
+#define CKA_PUBLIC_EXPONENT    0x00000122
+#define CKA_PRIVATE_EXPONENT   0x00000123
+#define CKA_PRIME_1            0x00000124
+#define CKA_PRIME_2            0x00000125
+#define CKA_EXPONENT_1         0x00000126
+#define CKA_EXPONENT_2         0x00000127
+#define CKA_COEFFICIENT        0x00000128
+#define CKA_PRIME              0x00000130
+#define CKA_SUBPRIME           0x00000131
+#define CKA_BASE               0x00000132
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS         0x00000133
+#define CKA_SUBPRIME_BITS      0x00000134
+#define CKA_SUB_PRIME_BITS     CKA_SUBPRIME_BITS
+/* (To retain backwards-compatibility) */
+
+#define CKA_VALUE_BITS         0x00000160
+#define CKA_VALUE_LEN          0x00000161
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE        0x00000162
+#define CKA_LOCAL              0x00000163
+#define CKA_NEVER_EXTRACTABLE  0x00000164
+#define CKA_ALWAYS_SENSITIVE   0x00000165
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM  0x00000166
+
+#define CKA_MODIFIABLE         0x00000170
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS       0x00000180
+#define CKA_EC_PARAMS          0x00000180
+
+#define CKA_EC_POINT           0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * are new for v2.10. Deprecated in v2.11 and onwards. */
+#define CKA_SECONDARY_AUTH     0x00000200
+#define CKA_AUTH_PIN_FLAGS     0x00000201
+
+/* CKA_ALWAYS_AUTHENTICATE ...
+ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
+#define CKA_ALWAYS_AUTHENTICATE  0x00000202
+
+#define CKA_WRAP_WITH_TRUSTED    0x00000210
+#define CKA_WRAP_TEMPLATE        (CKF_ARRAY_ATTRIBUTE|0x00000211)
+#define CKA_UNWRAP_TEMPLATE      (CKF_ARRAY_ATTRIBUTE|0x00000212)
+
+/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_HW_FEATURE_TYPE    0x00000300
+#define CKA_RESET_ON_INIT      0x00000301
+#define CKA_HAS_RESET          0x00000302
+
+/* The following attributes are new for v2.20 */
+#define CKA_PIXEL_X                     0x00000400
+#define CKA_PIXEL_Y                     0x00000401
+#define CKA_RESOLUTION                  0x00000402
+#define CKA_CHAR_ROWS                   0x00000403
+#define CKA_CHAR_COLUMNS                0x00000404
+#define CKA_COLOR                       0x00000405
+#define CKA_BITS_PER_PIXEL              0x00000406
+#define CKA_CHAR_SETS                   0x00000480
+#define CKA_ENCODING_METHODS            0x00000481
+#define CKA_MIME_TYPES                  0x00000482
+#define CKA_MECHANISM_TYPE              0x00000500
+#define CKA_REQUIRED_CMS_ATTRIBUTES     0x00000501
+#define CKA_DEFAULT_CMS_ATTRIBUTES      0x00000502
+#define CKA_SUPPORTED_CMS_ATTRIBUTES    0x00000503
+#define CKA_ALLOWED_MECHANISMS          (CKF_ARRAY_ATTRIBUTE|0x00000600)
+
+#define CKA_VENDOR_DEFINED     0x80000000
+
+// Gemalto CKA
+#define CKA_GEMALTO_CTRINDEX   0x80000001
+#define CKA_GEMALTO_KEYSPEC    0x80000002
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+  CK_ATTRIBUTE_TYPE type;
+  CK_VOID_PTR       pValue;
+
+  /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+  CK_ULONG          ulValueLen;  /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+  CK_CHAR       year[4];   /* the year ("1900" - "9999") */
+  CK_CHAR       month[2];  /* the month ("01" - "12") */
+  CK_CHAR       day[2];    /* the day   ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG          CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN      0x00000000
+#define CKM_RSA_PKCS                   0x00000001
+#define CKM_RSA_9796                   0x00000002
+#define CKM_RSA_X_509                  0x00000003
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0.  They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS               0x00000004
+#define CKM_MD5_RSA_PKCS               0x00000005
+#define CKM_SHA1_RSA_PKCS              0x00000006
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS         0x00000007
+#define CKM_RIPEMD160_RSA_PKCS         0x00000008
+#define CKM_RSA_PKCS_OAEP              0x00000009
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000A
+#define CKM_RSA_X9_31                  0x0000000B
+#define CKM_SHA1_RSA_X9_31             0x0000000C
+#define CKM_RSA_PKCS_PSS               0x0000000D
+#define CKM_SHA1_RSA_PKCS_PSS          0x0000000E
+
+#define CKM_DSA_KEY_PAIR_GEN           0x00000010
+#define CKM_DSA                        0x00000011
+#define CKM_DSA_SHA1                   0x00000012
+#define CKM_DH_PKCS_KEY_PAIR_GEN       0x00000020
+#define CKM_DH_PKCS_DERIVE             0x00000021
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN      0x00000030
+#define CKM_X9_42_DH_DERIVE            0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE     0x00000032
+#define CKM_X9_42_MQV_DERIVE           0x00000033
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_RSA_PKCS            0x00000040
+#define CKM_SHA384_RSA_PKCS            0x00000041
+#define CKM_SHA512_RSA_PKCS            0x00000042
+#define CKM_SHA256_RSA_PKCS_PSS        0x00000043
+#define CKM_SHA384_RSA_PKCS_PSS        0x00000044
+#define CKM_SHA512_RSA_PKCS_PSS        0x00000045
+
+#define CKM_RC2_KEY_GEN                0x00000100
+#define CKM_RC2_ECB                    0x00000101
+#define CKM_RC2_CBC                    0x00000102
+#define CKM_RC2_MAC                    0x00000103
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL            0x00000104
+#define CKM_RC2_CBC_PAD                0x00000105
+
+#define CKM_RC4_KEY_GEN                0x00000110
+#define CKM_RC4                        0x00000111
+#define CKM_DES_KEY_GEN                0x00000120
+#define CKM_DES_ECB                    0x00000121
+#define CKM_DES_CBC                    0x00000122
+#define CKM_DES_MAC                    0x00000123
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL            0x00000124
+#define CKM_DES_CBC_PAD                0x00000125
+
+#define CKM_DES2_KEY_GEN               0x00000130
+#define CKM_DES3_KEY_GEN               0x00000131
+#define CKM_DES3_ECB                   0x00000132
+#define CKM_DES3_CBC                   0x00000133
+#define CKM_DES3_MAC                   0x00000134
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL           0x00000135
+#define CKM_DES3_CBC_PAD               0x00000136
+#define CKM_CDMF_KEY_GEN               0x00000140
+#define CKM_CDMF_ECB                   0x00000141
+#define CKM_CDMF_CBC                   0x00000142
+#define CKM_CDMF_MAC                   0x00000143
+#define CKM_CDMF_MAC_GENERAL           0x00000144
+#define CKM_CDMF_CBC_PAD               0x00000145
+
+/* the following four DES mechanisms are new for v2.20 */
+#define CKM_DES_OFB64                  0x00000150
+#define CKM_DES_OFB8                   0x00000151
+#define CKM_DES_CFB64                  0x00000152
+#define CKM_DES_CFB8                   0x00000153
+
+#define CKM_MD2                        0x00000200
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC                   0x00000201
+#define CKM_MD2_HMAC_GENERAL           0x00000202
+
+#define CKM_MD5                        0x00000210
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC                   0x00000211
+#define CKM_MD5_HMAC_GENERAL           0x00000212
+
+#define CKM_SHA_1                      0x00000220
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC                 0x00000221
+#define CKM_SHA_1_HMAC_GENERAL         0x00000222
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128                  0x00000230
+#define CKM_RIPEMD128_HMAC             0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL     0x00000232
+#define CKM_RIPEMD160                  0x00000240
+#define CKM_RIPEMD160_HMAC             0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL     0x00000242
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256                     0x00000250
+#define CKM_SHA256_HMAC                0x00000251
+#define CKM_SHA256_HMAC_GENERAL        0x00000252
+#define CKM_SHA384                     0x00000260
+#define CKM_SHA384_HMAC                0x00000261
+#define CKM_SHA384_HMAC_GENERAL        0x00000262
+#define CKM_SHA512                     0x00000270
+#define CKM_SHA512_HMAC                0x00000271
+#define CKM_SHA512_HMAC_GENERAL        0x00000272
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN               0x00000300
+#define CKM_CAST_ECB                   0x00000301
+#define CKM_CAST_CBC                   0x00000302
+#define CKM_CAST_MAC                   0x00000303
+#define CKM_CAST_MAC_GENERAL           0x00000304
+#define CKM_CAST_CBC_PAD               0x00000305
+#define CKM_CAST3_KEY_GEN              0x00000310
+#define CKM_CAST3_ECB                  0x00000311
+#define CKM_CAST3_CBC                  0x00000312
+#define CKM_CAST3_MAC                  0x00000313
+#define CKM_CAST3_MAC_GENERAL          0x00000314
+#define CKM_CAST3_CBC_PAD              0x00000315
+#define CKM_CAST5_KEY_GEN              0x00000320
+#define CKM_CAST128_KEY_GEN            0x00000320
+#define CKM_CAST5_ECB                  0x00000321
+#define CKM_CAST128_ECB                0x00000321
+#define CKM_CAST5_CBC                  0x00000322
+#define CKM_CAST128_CBC                0x00000322
+#define CKM_CAST5_MAC                  0x00000323
+#define CKM_CAST128_MAC                0x00000323
+#define CKM_CAST5_MAC_GENERAL          0x00000324
+#define CKM_CAST128_MAC_GENERAL        0x00000324
+#define CKM_CAST5_CBC_PAD              0x00000325
+#define CKM_CAST128_CBC_PAD            0x00000325
+#define CKM_RC5_KEY_GEN                0x00000330
+#define CKM_RC5_ECB                    0x00000331
+#define CKM_RC5_CBC                    0x00000332
+#define CKM_RC5_MAC                    0x00000333
+#define CKM_RC5_MAC_GENERAL            0x00000334
+#define CKM_RC5_CBC_PAD                0x00000335
+#define CKM_IDEA_KEY_GEN               0x00000340
+#define CKM_IDEA_ECB                   0x00000341
+#define CKM_IDEA_CBC                   0x00000342
+#define CKM_IDEA_MAC                   0x00000343
+#define CKM_IDEA_MAC_GENERAL           0x00000344
+#define CKM_IDEA_CBC_PAD               0x00000345
+#define CKM_GENERIC_SECRET_KEY_GEN     0x00000350
+#define CKM_CONCATENATE_BASE_AND_KEY   0x00000360
+#define CKM_CONCATENATE_BASE_AND_DATA  0x00000362
+#define CKM_CONCATENATE_DATA_AND_BASE  0x00000363
+#define CKM_XOR_BASE_AND_DATA          0x00000364
+#define CKM_EXTRACT_KEY_FROM_KEY       0x00000365
+#define CKM_SSL3_PRE_MASTER_KEY_GEN    0x00000370
+#define CKM_SSL3_MASTER_KEY_DERIVE     0x00000371
+#define CKM_SSL3_KEY_AND_MAC_DERIVE    0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH  0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN     0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE      0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE     0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH   0x00000377
+
+/* CKM_TLS_PRF is new for v2.20 */
+#define CKM_TLS_PRF                    0x00000378
+
+#define CKM_SSL3_MD5_MAC               0x00000380
+#define CKM_SSL3_SHA1_MAC              0x00000381
+#define CKM_MD5_KEY_DERIVATION         0x00000390
+#define CKM_MD2_KEY_DERIVATION         0x00000391
+#define CKM_SHA1_KEY_DERIVATION        0x00000392
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_KEY_DERIVATION      0x00000393
+#define CKM_SHA384_KEY_DERIVATION      0x00000394
+#define CKM_SHA512_KEY_DERIVATION      0x00000395
+
+#define CKM_PBE_MD2_DES_CBC            0x000003A0
+#define CKM_PBE_MD5_DES_CBC            0x000003A1
+#define CKM_PBE_MD5_CAST_CBC           0x000003A2
+#define CKM_PBE_MD5_CAST3_CBC          0x000003A3
+#define CKM_PBE_MD5_CAST5_CBC          0x000003A4
+#define CKM_PBE_MD5_CAST128_CBC        0x000003A4
+#define CKM_PBE_SHA1_CAST5_CBC         0x000003A5
+#define CKM_PBE_SHA1_CAST128_CBC       0x000003A5
+#define CKM_PBE_SHA1_RC4_128           0x000003A6
+#define CKM_PBE_SHA1_RC4_40            0x000003A7
+#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003A8
+#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003A9
+#define CKM_PBE_SHA1_RC2_128_CBC       0x000003AA
+#define CKM_PBE_SHA1_RC2_40_CBC        0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2                0x000003B0
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003C0
+
+/* WTLS mechanisms are new for v2.20 */
+#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003D0
+#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003D1
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003D2
+#define CKM_WTLS_PRF                        0x000003D3
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003D4
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003D5
+
+#define CKM_KEY_WRAP_LYNKS             0x00000400
+#define CKM_KEY_WRAP_SET_OAEP          0x00000401
+
+/* CKM_CMS_SIG is new for v2.20 */
+#define CKM_CMS_SIG                    0x00000500
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN           0x00001000
+#define CKM_SKIPJACK_ECB64             0x00001001
+#define CKM_SKIPJACK_CBC64             0x00001002
+#define CKM_SKIPJACK_OFB64             0x00001003
+#define CKM_SKIPJACK_CFB64             0x00001004
+#define CKM_SKIPJACK_CFB32             0x00001005
+#define CKM_SKIPJACK_CFB16             0x00001006
+#define CKM_SKIPJACK_CFB8              0x00001007
+#define CKM_SKIPJACK_WRAP              0x00001008
+#define CKM_SKIPJACK_PRIVATE_WRAP      0x00001009
+#define CKM_SKIPJACK_RELAYX            0x0000100a
+#define CKM_KEA_KEY_PAIR_GEN           0x00001010
+#define CKM_KEA_KEY_DERIVE             0x00001011
+#define CKM_FORTEZZA_TIMESTAMP         0x00001020
+#define CKM_BATON_KEY_GEN              0x00001030
+#define CKM_BATON_ECB128               0x00001031
+#define CKM_BATON_ECB96                0x00001032
+#define CKM_BATON_CBC128               0x00001033
+#define CKM_BATON_COUNTER              0x00001034
+#define CKM_BATON_SHUFFLE              0x00001035
+#define CKM_BATON_WRAP                 0x00001036
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN         0x00001040
+#define CKM_EC_KEY_PAIR_GEN            0x00001040
+
+#define CKM_ECDSA                      0x00001041
+#define CKM_ECDSA_SHA1                 0x00001042
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE               0x00001050
+#define CKM_ECDH1_COFACTOR_DERIVE      0x00001051
+#define CKM_ECMQV_DERIVE               0x00001052
+
+#define CKM_JUNIPER_KEY_GEN            0x00001060
+#define CKM_JUNIPER_ECB128             0x00001061
+#define CKM_JUNIPER_CBC128             0x00001062
+#define CKM_JUNIPER_COUNTER            0x00001063
+#define CKM_JUNIPER_SHUFFLE            0x00001064
+#define CKM_JUNIPER_WRAP               0x00001065
+#define CKM_FASTHASH                   0x00001070
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN                0x00001080
+#define CKM_AES_ECB                    0x00001081
+#define CKM_AES_CBC                    0x00001082
+#define CKM_AES_MAC                    0x00001083
+#define CKM_AES_MAC_GENERAL            0x00001084
+#define CKM_AES_CBC_PAD                0x00001085
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKM_BLOWFISH_KEY_GEN           0x00001090
+#define CKM_BLOWFISH_CBC               0x00001091
+#define CKM_TWOFISH_KEY_GEN            0x00001092
+#define CKM_TWOFISH_CBC                0x00001093
+
+
+/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
+#define CKM_DES_ECB_ENCRYPT_DATA       0x00001100
+#define CKM_DES_CBC_ENCRYPT_DATA       0x00001101
+#define CKM_DES3_ECB_ENCRYPT_DATA      0x00001102
+#define CKM_DES3_CBC_ENCRYPT_DATA      0x00001103
+#define CKM_AES_ECB_ENCRYPT_DATA       0x00001104
+#define CKM_AES_CBC_ENCRYPT_DATA       0x00001105
+
+#define CKM_DSA_PARAMETER_GEN          0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN      0x00002001
+#define CKM_X9_42_DH_PARAMETER_GEN     0x00002002
+
+#define CKM_VENDOR_DEFINED             0x80000000
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism  */
+typedef struct CK_MECHANISM {
+  CK_MECHANISM_TYPE mechanism;
+  CK_VOID_PTR       pParameter;
+
+  /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+   * v2.0 */
+  CK_ULONG          ulParameterLen;  /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+    CK_ULONG    ulMinKeySize;
+    CK_ULONG    ulMaxKeySize;
+    CK_FLAGS    flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ *      Bit Flag               Mask        Meaning */
+#define CKF_HW                 0x00000001  /* performed by HW */
+
+// Added by KS
+#define CKF_SW                 0x00000000 /* performed by SW */
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0.  They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT            0x00000100
+#define CKF_DECRYPT            0x00000200
+#define CKF_DIGEST             0x00000400
+#define CKF_SIGN               0x00000800
+#define CKF_SIGN_RECOVER       0x00001000
+#define CKF_VERIFY             0x00002000
+#define CKF_VERIFY_RECOVER     0x00004000
+#define CKF_GENERATE           0x00008000
+#define CKF_GENERATE_KEY_PAIR  0x00010000
+#define CKF_WRAP               0x00020000
+#define CKF_UNWRAP             0x00040000
+#define CKF_DERIVE             0x00080000
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P             0x00100000
+#define CKF_EC_F_2M            0x00200000
+#define CKF_EC_ECPARAMETERS    0x00400000
+#define CKF_EC_NAMEDCURVE      0x00800000
+#define CKF_EC_UNCOMPRESS      0x01000000
+#define CKF_EC_COMPRESS        0x02000000
+
+#define CKF_EXTENSION          0x80000000 /* FALSE for this version */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG          CK_RV;
+
+#define CKR_OK                                0x00000000
+#define CKR_CANCEL                            0x00000001
+#define CKR_HOST_MEMORY                       0x00000002
+#define CKR_SLOT_ID_INVALID                   0x00000003
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR                     0x00000005
+#define CKR_FUNCTION_FAILED                   0x00000006
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD                     0x00000007
+#define CKR_NO_EVENT                          0x00000008
+#define CKR_NEED_TO_CREATE_THREADS            0x00000009
+#define CKR_CANT_LOCK                         0x0000000A
+
+#define CKR_ATTRIBUTE_READ_ONLY               0x00000010
+#define CKR_ATTRIBUTE_SENSITIVE               0x00000011
+#define CKR_ATTRIBUTE_TYPE_INVALID            0x00000012
+#define CKR_ATTRIBUTE_VALUE_INVALID           0x00000013
+#define CKR_DATA_INVALID                      0x00000020
+#define CKR_DATA_LEN_RANGE                    0x00000021
+#define CKR_DEVICE_ERROR                      0x00000030
+#define CKR_DEVICE_MEMORY                     0x00000031
+#define CKR_DEVICE_REMOVED                    0x00000032
+#define CKR_ENCRYPTED_DATA_INVALID            0x00000040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE          0x00000041
+#define CKR_FUNCTION_CANCELED                 0x00000050
+#define CKR_FUNCTION_NOT_PARALLEL             0x00000051
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED            0x00000054
+
+#define CKR_KEY_HANDLE_INVALID                0x00000060
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE                    0x00000062
+#define CKR_KEY_TYPE_INCONSISTENT             0x00000063
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED                    0x00000064
+#define CKR_KEY_CHANGED                       0x00000065
+#define CKR_KEY_NEEDED                        0x00000066
+#define CKR_KEY_INDIGESTIBLE                  0x00000067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED        0x00000068
+#define CKR_KEY_NOT_WRAPPABLE                 0x00000069
+#define CKR_KEY_UNEXTRACTABLE                 0x0000006A
+
+#define CKR_MECHANISM_INVALID                 0x00000070
+#define CKR_MECHANISM_PARAM_INVALID           0x00000071
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID             0x00000082
+#define CKR_OPERATION_ACTIVE                  0x00000090
+#define CKR_OPERATION_NOT_INITIALIZED         0x00000091
+#define CKR_PIN_INCORRECT                     0x000000A0
+#define CKR_PIN_INVALID                       0x000000A1
+#define CKR_PIN_LEN_RANGE                     0x000000A2
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED                       0x000000A3
+#define CKR_PIN_LOCKED                        0x000000A4
+
+#define CKR_SESSION_CLOSED                    0x000000B0
+#define CKR_SESSION_COUNT                     0x000000B1
+#define CKR_SESSION_HANDLE_INVALID            0x000000B3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED    0x000000B4
+#define CKR_SESSION_READ_ONLY                 0x000000B5
+#define CKR_SESSION_EXISTS                    0x000000B6
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS          0x000000B7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS      0x000000B8
+
+#define CKR_SIGNATURE_INVALID                 0x000000C0
+#define CKR_SIGNATURE_LEN_RANGE               0x000000C1
+#define CKR_TEMPLATE_INCOMPLETE               0x000000D0
+#define CKR_TEMPLATE_INCONSISTENT             0x000000D1
+#define CKR_TOKEN_NOT_PRESENT                 0x000000E0
+#define CKR_TOKEN_NOT_RECOGNIZED              0x000000E1
+#define CKR_TOKEN_WRITE_PROTECTED             0x000000E2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID     0x000000F0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE         0x000000F1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT  0x000000F2
+#define CKR_USER_ALREADY_LOGGED_IN            0x00000100
+#define CKR_USER_NOT_LOGGED_IN                0x00000101
+#define CKR_USER_PIN_NOT_INITIALIZED          0x00000102
+#define CKR_USER_TYPE_INVALID                 0x00000103
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN    0x00000104
+#define CKR_USER_TOO_MANY_TYPES               0x00000105
+
+#define CKR_WRAPPED_KEY_INVALID               0x00000110
+#define CKR_WRAPPED_KEY_LEN_RANGE             0x00000112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID       0x00000113
+#define CKR_WRAPPING_KEY_SIZE_RANGE           0x00000114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT    0x00000115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED         0x00000120
+
+/* These are new to v2.0 */
+#define CKR_RANDOM_NO_RNG                     0x00000121
+
+/* These are new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID             0x00000130
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL                  0x00000150
+#define CKR_SAVED_STATE_INVALID               0x00000160
+#define CKR_INFORMATION_SENSITIVE             0x00000170
+#define CKR_STATE_UNSAVEABLE                  0x00000180
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED          0x00000190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED      0x00000191
+#define CKR_MUTEX_BAD                         0x000001A0
+#define CKR_MUTEX_NOT_LOCKED                  0x000001A1
+
+/* This is new to v2.20 */
+#define CKR_FUNCTION_REJECTED                 0x00000200
+
+#define CKR_VENDOR_DEFINED                    0x80000000
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+  CK_SESSION_HANDLE hSession,     /* the session's handle */
+  CK_NOTIFICATION   event,
+  CK_VOID_PTR       pApplication  /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+  CK_VOID_PTR_PTR ppMutex  /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+  CK_VOID_PTR pMutex  /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+  CK_VOID_PTR pMutex  /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+  CK_VOID_PTR pMutex  /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+  CK_CREATEMUTEX CreateMutex;
+  CK_DESTROYMUTEX DestroyMutex;
+  CK_LOCKMUTEX LockMutex;
+  CK_UNLOCKMUTEX UnlockMutex;
+  CK_FLAGS flags;
+  CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ *      Bit Flag                           Mask       Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
+#define CKF_OS_LOCKING_OK                  0x00000002
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK     1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE  is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
+ * are new for v2.20 */
+#define CKG_MGF1_SHA1         0x00000001
+#define CKG_MGF1_SHA256       0x00000002
+#define CKG_MGF1_SHA384       0x00000003
+#define CKG_MGF1_SHA512       0x00000004
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE  is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED    0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+        CK_MECHANISM_TYPE hashAlg;
+        CK_RSA_PKCS_MGF_TYPE mgf;
+        CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+        CK_VOID_PTR pSourceData;
+        CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+        CK_MECHANISM_TYPE    hashAlg;
+        CK_RSA_PKCS_MGF_TYPE mgf;
+        CK_ULONG             sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+/* CK_EC_KDF_TYPE is new for v2.11. */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL                 0x00000001
+#define CKD_SHA1_KDF             0x00000002
+
+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+  CK_EC_KDF_TYPE kdf;
+  CK_ULONG ulSharedDataLen;
+  CK_BYTE_PTR pSharedData;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+
+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+  CK_EC_KDF_TYPE kdf;
+  CK_ULONG ulSharedDataLen;
+  CK_BYTE_PTR pSharedData;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_ECMQV_DERIVE_PARAMS {
+  CK_EC_KDF_TYPE kdf;
+  CK_ULONG ulSharedDataLen;
+  CK_BYTE_PTR pSharedData;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+  CK_OBJECT_HANDLE publicKey;
+} CK_ECMQV_DERIVE_PARAMS;
+
+typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* The following X9.42 DH key derivation functions are defined
+   (besides CKD_NULL already defined : */
+#define CKD_SHA1_KDF_ASN1        0x00000003
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004
+
+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+  CK_X9_42_DH_KDF_TYPE kdf;
+  CK_ULONG ulOtherInfoLen;
+  CK_BYTE_PTR pOtherInfo;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+  CK_X9_42_DH_KDF_TYPE kdf;
+  CK_ULONG ulOtherInfoLen;
+  CK_BYTE_PTR pOtherInfo;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
+  CK_X9_42_DH_KDF_TYPE kdf;
+  CK_ULONG ulOtherInfoLen;
+  CK_BYTE_PTR pOtherInfo;
+  CK_ULONG ulPublicDataLen;
+  CK_BYTE_PTR pPublicData;
+  CK_ULONG ulPrivateDataLen;
+  CK_OBJECT_HANDLE hPrivateData;
+  CK_ULONG ulPublicDataLen2;
+  CK_BYTE_PTR pPublicData2;
+  CK_OBJECT_HANDLE publicKey;
+} CK_X9_42_MQV_DERIVE_PARAMS;
+
+typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+  CK_BBOOL      isSender;
+  CK_ULONG      ulRandomLen;
+  CK_BYTE_PTR   pRandomA;
+  CK_BYTE_PTR   pRandomB;
+  CK_ULONG      ulPublicDataLen;
+  CK_BYTE_PTR   pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms.  An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG          CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+  /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+   * v2.0 */
+  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */
+
+  CK_BYTE       iv[8];            /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */
+  CK_ULONG      ulMacLength;      /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+  CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+  CK_ULONG      ulWordsize;  /* wordsize in bits */
+  CK_ULONG      ulRounds;    /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+  CK_ULONG      ulWordsize;  /* wordsize in bits */
+  CK_ULONG      ulRounds;    /* number of rounds */
+  CK_BYTE_PTR   pIv;         /* pointer to IV */
+  CK_ULONG      ulIvLen;     /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+  CK_ULONG      ulWordsize;   /* wordsize in bits */
+  CK_ULONG      ulRounds;     /* number of rounds */
+  CK_ULONG      ulMacLength;  /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+  CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms.  Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG          CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
+typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
+  CK_BYTE      iv[8];
+  CK_BYTE_PTR  pData;
+  CK_ULONG     length;
+} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+  CK_BYTE      iv[16];
+  CK_BYTE_PTR  pData;
+  CK_ULONG     length;
+} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+  CK_ULONG      ulPasswordLen;
+  CK_BYTE_PTR   pPassword;
+  CK_ULONG      ulPublicDataLen;
+  CK_BYTE_PTR   pPublicData;
+  CK_ULONG      ulPAndGLen;
+  CK_ULONG      ulQLen;
+  CK_ULONG      ulRandomLen;
+  CK_BYTE_PTR   pRandomA;
+  CK_BYTE_PTR   pPrimeP;
+  CK_BYTE_PTR   pBaseG;
+  CK_BYTE_PTR   pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+  CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+  CK_ULONG      ulOldWrappedXLen;
+  CK_BYTE_PTR   pOldWrappedX;
+  CK_ULONG      ulOldPasswordLen;
+  CK_BYTE_PTR   pOldPassword;
+  CK_ULONG      ulOldPublicDataLen;
+  CK_BYTE_PTR   pOldPublicData;
+  CK_ULONG      ulOldRandomLen;
+  CK_BYTE_PTR   pOldRandomA;
+  CK_ULONG      ulNewPasswordLen;
+  CK_BYTE_PTR   pNewPassword;
+  CK_ULONG      ulNewPublicDataLen;
+  CK_BYTE_PTR   pNewPublicData;
+  CK_ULONG      ulNewRandomLen;
+  CK_BYTE_PTR   pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+  CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+  CK_BYTE_PTR      pInitVector;
+  CK_UTF8CHAR_PTR  pPassword;
+  CK_ULONG         ulPasswordLen;
+  CK_BYTE_PTR      pSalt;
+  CK_ULONG         ulSaltLen;
+  CK_ULONG         ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+  CK_BYTE       bBC;     /* block contents byte */
+  CK_BYTE_PTR   pX;      /* extra data */
+  CK_ULONG      ulXLen;  /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
+  CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_RANDOM_DATA {
+  CK_BYTE_PTR  pClientRandom;
+  CK_ULONG     ulClientRandomLen;
+  CK_BYTE_PTR  pServerRandom;
+  CK_ULONG     ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+  CK_SSL3_RANDOM_DATA RandomInfo;
+  CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+  CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+  CK_OBJECT_HANDLE hClientMacSecret;
+  CK_OBJECT_HANDLE hServerMacSecret;
+  CK_OBJECT_HANDLE hClientKey;
+  CK_OBJECT_HANDLE hServerKey;
+  CK_BYTE_PTR      pIVClient;
+  CK_BYTE_PTR      pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+  CK_ULONG                ulMacSizeInBits;
+  CK_ULONG                ulKeySizeInBits;
+  CK_ULONG                ulIVSizeInBits;
+  CK_BBOOL                bIsExport;
+  CK_SSL3_RANDOM_DATA     RandomInfo;
+  CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+/* CK_TLS_PRF_PARAMS is new for version 2.20 */
+typedef struct CK_TLS_PRF_PARAMS {
+  CK_BYTE_PTR  pSeed;
+  CK_ULONG     ulSeedLen;
+  CK_BYTE_PTR  pLabel;
+  CK_ULONG     ulLabelLen;
+  CK_BYTE_PTR  pOutput;
+  CK_ULONG_PTR pulOutputLen;
+} CK_TLS_PRF_PARAMS;
+
+typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
+
+/* WTLS is new for version 2.20 */
+typedef struct CK_WTLS_RANDOM_DATA {
+  CK_BYTE_PTR pClientRandom;
+  CK_ULONG    ulClientRandomLen;
+  CK_BYTE_PTR pServerRandom;
+  CK_ULONG    ulServerRandomLen;
+} CK_WTLS_RANDOM_DATA;
+
+typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
+
+typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
+  CK_MECHANISM_TYPE   DigestMechanism;
+  CK_WTLS_RANDOM_DATA RandomInfo;
+  CK_BYTE_PTR         pVersion;
+} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+  CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_WTLS_PRF_PARAMS {
+  CK_MECHANISM_TYPE DigestMechanism;
+  CK_BYTE_PTR       pSeed;
+  CK_ULONG          ulSeedLen;
+  CK_BYTE_PTR       pLabel;
+  CK_ULONG          ulLabelLen;
+  CK_BYTE_PTR       pOutput;
+  CK_ULONG_PTR      pulOutputLen;
+} CK_WTLS_PRF_PARAMS;
+
+typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_OUT {
+  CK_OBJECT_HANDLE hMacSecret;
+  CK_OBJECT_HANDLE hKey;
+  CK_BYTE_PTR      pIV;
+} CK_WTLS_KEY_MAT_OUT;
+
+typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_PARAMS {
+  CK_MECHANISM_TYPE       DigestMechanism;
+  CK_ULONG                ulMacSizeInBits;
+  CK_ULONG                ulKeySizeInBits;
+  CK_ULONG                ulIVSizeInBits;
+  CK_ULONG                ulSequenceNumber;
+  CK_BBOOL                bIsExport;
+  CK_WTLS_RANDOM_DATA     RandomInfo;
+  CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_WTLS_KEY_MAT_PARAMS;
+
+typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
+
+/* CMS is new for version 2.20 */
+typedef struct CK_CMS_SIG_PARAMS {
+  CK_OBJECT_HANDLE      certificateHandle;
+  CK_MECHANISM_PTR      pSigningMechanism;
+  CK_MECHANISM_PTR      pDigestMechanism;
+  CK_UTF8CHAR_PTR       pContentType;
+  CK_BYTE_PTR           pRequestedAttributes;
+  CK_ULONG              ulRequestedAttributesLen;
+  CK_BYTE_PTR           pRequiredAttributes;
+  CK_ULONG              ulRequiredAttributesLen;
+} CK_CMS_SIG_PARAMS;
+
+typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+  CK_BYTE_PTR pData;
+  CK_ULONG    ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+  CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism.  It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED        0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+        CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE           saltSource;
+        CK_VOID_PTR                                pSaltSourceData;
+        CK_ULONG                                   ulSaltSourceDataLen;
+        CK_ULONG                                   iterations;
+        CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+        CK_VOID_PTR                                pPrfData;
+        CK_ULONG                                   ulPrfDataLen;
+        CK_UTF8CHAR_PTR                            pPassword;
+        CK_ULONG_PTR                               ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,97 @@
+/* cryptoki.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This is a sample file containing the top level include directives
+ * for building Win32 Cryptoki libraries and applications.
+ */
+
+#ifndef _include_platconfig_h
+#define _include_platconfig_h
+
+#ifndef NULL_PTR
+    #define NULL_PTR 0
+#endif
+
+#ifdef _WIN32
+
+#pragma pack(push, plcryptoki, 1)
+
+/* Specifies that the function is a DLL entry point. */
+#define CK_IMPORT_SPEC __declspec(dllimport)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_EXPORT_SPEC __declspec(dllexport)
+#else
+#define CK_EXPORT_SPEC CK_IMPORT_SPEC
+#endif
+
+/* Ensures the calling convention for Win32 builds */
+#define CK_CALL_SPEC __cdecl
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+  returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+  returnType (CK_CALL_SPEC CK_PTR name)
+
+#ifdef _DEBUG
+    #define PKCS11_ASSERT(X)        assert(X)
+#else
+    #define PKCS11_ASSERT(X)
+#endif
+
+#include "pkcs11.h"
+
+#pragma pack(pop, plcryptoki)
+
+#else
+
+#define CK_IMPORT_SPEC
+#define CK_EXPORT_SPEC
+#define CK_CALL_SPEC
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+  returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+  returnType (CK_CALL_SPEC CK_PTR name)
+
+#define PKCS11_ASSERT(X)
+
+#include "pkcs11.h"
+
+#endif
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,372 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "privatekeyobject.h"
+
+PrivateKeyObject :: PrivateKeyObject() : KeyObject()
+{
+    this->_class                = CKO_PRIVATE_KEY;
+
+    this->_subject              = NULL_PTR;
+    this->_sensitive            = CK_TRUE;
+    this->_decrypt              = CK_TRUE;
+    this->_sign                 = CK_TRUE;
+    this->_signRecover          = CK_TRUE;
+    this->_unwrap               = CK_FALSE;
+    this->_extractable          = CK_FALSE;
+    this->_alwaysSensitive      = CK_TRUE;
+    this->_neverExtractable     = CK_TRUE;
+    this->_wrapWithTrusted      = CK_FALSE;
+    this->_alwaysAuthenticate   = CK_FALSE;
+
+    this->_ctrIndex = 0xFF; //-1;
+    this->_keyType  = CK_UNAVAILABLE_INFORMATION; //-1;
+}
+
+PrivateKeyObject :: ~PrivateKeyObject(){
+
+    if(this->_subject != NULL_PTR){
+        delete this->_subject;
+    }
+}
+
+bool PrivateKeyObject::IsEqual(const StorageObject * that) const
+{
+    if(_uniqueId != 0 && that->_uniqueId != 0)
+        return (_uniqueId == that->_uniqueId);
+
+    // Only objects that have been stored under p11 directory
+    // will have a non-zero _uniqueId. For other objects, do
+    // a deep comparison based on other attributes.
+    if(_class != that->_class)
+        return false;
+
+    const PrivateKeyObject * thatCert = static_cast<const PrivateKeyObject*>(that);
+    return ( (_ctrIndex == thatCert->_ctrIndex) &&
+             (_keySpec == thatCert->_keySpec) &&
+             (_checkValue == thatCert->_checkValue));
+}
+
+CK_BBOOL PrivateKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+
+        case CKA_SENSITIVE:
+            return (this->_sensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_DECRYPT:
+            return (this->_decrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SIGN:
+            return (this->_sign == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SIGN_RECOVER:
+            return (this->_signRecover == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_UNWRAP:
+            return (this->_unwrap == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_EXTRACTABLE:
+            return (this->_extractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ALWAYS_SENSITIVE:
+            return (this->_alwaysSensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_NEVER_EXTRACTABLE:
+            return (this->_neverExtractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_WRAP_WITH_TRUSTED:
+            return (this->_wrapWithTrusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ALWAYS_AUTHENTICATE:
+            return (this->_alwaysAuthenticate == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SUBJECT:
+            return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return KeyObject::Compare(attribute);
+
+    }
+}
+
+CK_RV PrivateKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type){
+
+        case CKA_SENSITIVE:
+            return StorageObject::PutBBoolInAttribute(this->_sensitive,attribute);
+
+        case CKA_DECRYPT:
+            return StorageObject::PutBBoolInAttribute(this->_decrypt,attribute);
+
+        case CKA_SIGN:
+            return StorageObject::PutBBoolInAttribute(this->_sign,attribute);
+
+        case CKA_SIGN_RECOVER:
+            return StorageObject::PutBBoolInAttribute(this->_signRecover,attribute);
+
+        case CKA_UNWRAP:
+            return StorageObject::PutBBoolInAttribute(this->_unwrap,attribute);
+
+        case CKA_EXTRACTABLE:
+            return StorageObject::PutBBoolInAttribute(this->_extractable,attribute);
+
+        case CKA_ALWAYS_SENSITIVE:
+            return StorageObject::PutBBoolInAttribute(this->_alwaysSensitive,attribute);
+
+        case CKA_NEVER_EXTRACTABLE:
+            return StorageObject::PutBBoolInAttribute(this->_neverExtractable,attribute);
+
+        case CKA_WRAP_WITH_TRUSTED:
+            return StorageObject::PutBBoolInAttribute(this->_wrapWithTrusted,attribute);
+
+        case CKA_ALWAYS_AUTHENTICATE:
+            return StorageObject::PutBBoolInAttribute(this->_alwaysAuthenticate,attribute);
+
+        case CKA_SUBJECT:
+            return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+        default:
+            return KeyObject::GetAttribute(attribute);
+    }
+}
+
+CK_RV PrivateKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE)
+    {
+        switch(attribute.type)
+        {
+            case CKA_ALWAYS_AUTHENTICATE:
+            case CKA_ALWAYS_SENSITIVE:
+            case CKA_NEVER_EXTRACTABLE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+
+            case CKA_DECRYPT:
+            case CKA_EXTRACTABLE:
+            case CKA_SENSITIVE:
+            case CKA_SIGN:
+            case CKA_SIGN_RECOVER:
+            case CKA_UNWRAP:
+            case CKA_WRAP_WITH_TRUSTED:
+                if(*(CK_BBOOL*)attribute.pValue == CK_TRUE){
+                    return CKR_ATTRIBUTE_READ_ONLY;
+                }
+                break;
+        }
+    }
+
+    switch(attribute.type){
+
+        case CKA_SENSITIVE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+
+                    if((objCreation == CK_FALSE) && (this->_sensitive == CK_TRUE) && (btemp == CK_FALSE)){
+                        rv = CKR_ATTRIBUTE_READ_ONLY;
+                    }else{
+                        this->_sensitive = btemp;
+
+                        if(btemp == CK_FALSE){
+                            this->_alwaysSensitive = CK_FALSE;
+                        }
+                    }
+                }
+            }
+            break;
+
+        case CKA_DECRYPT:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_decrypt = btemp; }
+            }
+            break;
+
+        case CKA_SIGN:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_sign = btemp; }
+            }
+            break;
+
+        case CKA_SIGN_RECOVER:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_signRecover = btemp; }
+            }
+            break;
+
+        case CKA_UNWRAP:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_unwrap = btemp; }
+            }
+            break;
+
+        case CKA_EXTRACTABLE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+
+                    if((objCreation == CK_FALSE) && (this->_extractable == CK_FALSE) && (btemp == CK_TRUE)){
+                        rv = CKR_ATTRIBUTE_READ_ONLY;
+                    }else{
+                        this->_extractable = btemp;
+
+                        if(btemp == CK_TRUE){
+                            this->_neverExtractable = CK_FALSE;
+                        }
+                    }
+                }
+            }
+            break;
+
+        case CKA_ALWAYS_SENSITIVE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_alwaysSensitive = btemp; }
+            }
+            break;
+
+
+        case CKA_NEVER_EXTRACTABLE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_neverExtractable = btemp; }
+            }
+            break;
+
+        case CKA_WRAP_WITH_TRUSTED:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_wrapWithTrusted = btemp; }
+            }
+            break;
+
+        case CKA_ALWAYS_AUTHENTICATE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_alwaysAuthenticate = btemp; }
+            }
+            break;
+
+        case CKA_SUBJECT:
+            if(this->_subject != NULL_PTR){
+                delete this->_subject;
+            }
+            this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+
+            break;
+
+        default:
+            return KeyObject::SetAttribute(attribute,objCreation);
+    }
+
+    return rv;
+}
+
+void PrivateKeyObject::Serialize(std::vector<u1> *to)
+{
+    KeyObject::Serialize(to);
+
+    Util::PushBBoolInVector(to,this->_sensitive);
+
+    Util::PushBBoolInVector(to,this->_decrypt);
+
+    Util::PushBBoolInVector(to,this->_sign);
+
+    Util::PushBBoolInVector(to,this->_signRecover);
+
+    Util::PushBBoolInVector(to,this->_unwrap);
+
+    Util::PushBBoolInVector(to,this->_extractable);
+
+    Util::PushBBoolInVector(to,this->_alwaysSensitive);
+
+    Util::PushBBoolInVector(to,this->_neverExtractable);
+
+    Util::PushBBoolInVector(to,this->_wrapWithTrusted);
+
+    Util::PushBBoolInVector(to,this->_alwaysAuthenticate);
+
+    Util::PushByteArrayInVector(to,this->_subject);
+
+    // serialize the extra fields
+
+    PKCS11_ASSERT(_checkValue != 0);
+    PKCS11_ASSERT(_ctrIndex < 100);
+    PKCS11_ASSERT(_keySpec == 1 || _keySpec == 2 );
+
+    Util::PushULongLongInVector(to,this->_checkValue);
+
+    Util::PushBBoolInVector(to,this->_ctrIndex);
+
+    Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void PrivateKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    KeyObject::Deserialize(from,idx);
+
+    this->_sensitive = Util::ReadBBoolFromVector(from,idx);
+
+    this->_decrypt = Util::ReadBBoolFromVector(from,idx);
+
+    this->_sign = Util::ReadBBoolFromVector(from,idx);
+
+    this->_signRecover = Util::ReadBBoolFromVector(from,idx);
+
+    this->_unwrap = Util::ReadBBoolFromVector(from,idx);
+
+    this->_extractable = Util::ReadBBoolFromVector(from,idx);
+
+    this->_alwaysSensitive = Util::ReadBBoolFromVector(from,idx);
+
+    this->_neverExtractable = Util::ReadBBoolFromVector(from,idx);
+
+    this->_wrapWithTrusted = Util::ReadBBoolFromVector(from,idx);
+
+    this->_alwaysAuthenticate = Util::ReadBBoolFromVector(from,idx);
+
+    this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+    // deserialize extra fields
+
+    this->_checkValue = Util::ReadULongLongFromVector(from,idx);
+
+    this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+    this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,63 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_privatekeyobject_h
+#define _include_privatekeyobject_h
+
+#include "keyobject.h"
+
+class PrivateKeyObject : public KeyObject
+{
+
+public:
+    u1Array*     _subject;
+    CK_BBOOL     _sensitive;
+    CK_BBOOL     _decrypt;
+    CK_BBOOL     _sign;
+    CK_BBOOL     _signRecover;
+    CK_BBOOL     _unwrap;
+    CK_BBOOL     _extractable;
+    CK_BBOOL     _alwaysSensitive;
+    CK_BBOOL     _neverExtractable;
+    CK_BBOOL     _wrapWithTrusted;
+    CK_BBOOL     _alwaysAuthenticate;
+
+    // extra fields which are not part of PKCS#11
+    // but are needed as extra information in card
+    u8          _checkValue;
+    CK_BYTE     _ctrIndex;
+    CK_BYTE     _keySpec;
+
+public:
+    PrivateKeyObject();
+    virtual ~PrivateKeyObject();
+
+    virtual bool IsEqual(const StorageObject * that) const;
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,205 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "publickeyobject.h"
+
+PublicKeyObject :: PublicKeyObject() : KeyObject()
+{
+   this->_class         = CKO_PUBLIC_KEY;
+
+   this->_encrypt       = CK_TRUE;
+   this->_verify        = CK_TRUE;
+   this->_verifyRecover = CK_TRUE;
+   this->_wrap          = CK_FALSE;
+
+   this->_subject       = NULL_PTR;
+
+   this->_ctrIndex = 0xFF; //-1;
+   this->_keyType  = CK_UNAVAILABLE_INFORMATION; //-1;
+}
+
+PublicKeyObject :: ~PublicKeyObject(){
+
+   if(this->_subject != NULL_PTR){
+      delete this->_subject;
+   }
+}
+
+CK_BBOOL PublicKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_ENCRYPT:
+           return (this->_encrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VERIFY:
+           return (this->_verify == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VERIFY_RECOVER:
+           return (this->_verifyRecover == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_WRAP:
+           return (this->_wrap == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SUBJECT:
+           return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+        default:
+           return KeyObject::Compare(attribute);
+   }
+}
+
+CK_RV PublicKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type){
+
+        case CKA_ENCRYPT:
+           return StorageObject::PutBBoolInAttribute(this->_encrypt,attribute);
+
+        case CKA_VERIFY:
+           return StorageObject::PutBBoolInAttribute(this->_verify,attribute);
+
+        case CKA_VERIFY_RECOVER:
+           return StorageObject::PutBBoolInAttribute(this->_verifyRecover,attribute);
+
+        case CKA_WRAP:
+           return StorageObject::PutBBoolInAttribute(this->_wrap,attribute);
+
+        case CKA_SUBJECT:
+           return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+        default:
+           return KeyObject::GetAttribute(attribute);
+
+   }
+}
+
+CK_RV PublicKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+   if(objCreation == CK_FALSE){
+      switch(attribute.type){
+            case CKA_ENCRYPT:
+            case CKA_TRUSTED:
+            case CKA_VERIFY:
+            case CKA_VERIFY_RECOVER:
+            case CKA_WRAP:
+               if(*(CK_BBOOL*)attribute.pValue == CK_TRUE){
+                  return CKR_ATTRIBUTE_READ_ONLY;
+               }
+               break;
+      }
+   }
+
+   switch(attribute.type){
+
+        case CKA_ENCRYPT:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_encrypt = btemp; }
+           }
+           break;
+
+        case CKA_VERIFY:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_verify = btemp; }
+           }
+           break;
+
+        case CKA_VERIFY_RECOVER:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_verifyRecover = btemp; }
+           }
+           break;
+
+        case CKA_WRAP:
+           {
+              CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_wrap = btemp; }
+           }
+           break;
+
+        case CKA_SUBJECT:
+           if(this->_subject != NULL_PTR){
+              delete this->_subject;
+           }
+           this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        default:
+           return KeyObject::SetAttribute(attribute,objCreation);
+   }
+
+   return rv;
+}
+
+void PublicKeyObject::Serialize(std::vector<u1> *to)
+{
+   KeyObject::Serialize(to);
+
+   Util::PushBBoolInVector(to,this->_encrypt);
+
+   Util::PushBBoolInVector(to,this->_verify);
+
+   Util::PushBBoolInVector(to,this->_verifyRecover);
+
+   Util::PushBBoolInVector(to,this->_wrap);
+
+   Util::PushByteArrayInVector(to,this->_subject);
+
+   // serialize the extra fields
+   Util::PushBBoolInVector(to,this->_ctrIndex);
+
+   Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void PublicKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   KeyObject::Deserialize(from,idx);
+
+   this->_encrypt = Util::ReadBBoolFromVector(from,idx);
+
+   this->_verify = Util::ReadBBoolFromVector(from,idx);
+
+   this->_verifyRecover = Util::ReadBBoolFromVector(from,idx);
+
+   this->_wrap = Util::ReadBBoolFromVector(from,idx);
+
+   this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+   // deserialize extra fields
+   this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+   this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,56 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_publickeyobject_h
+#define _include_publickeyobject_h
+
+#include "keyobject.h"
+
+class PublicKeyObject : public KeyObject
+{
+
+public:
+    u1Array*     _subject;
+    CK_BBOOL     _encrypt;
+    CK_BBOOL     _verify;
+    CK_BBOOL     _verifyRecover;
+    CK_BBOOL     _wrap;
+    CK_BBOOL     _trusted;
+
+    // extra fields which are not part of PKCS#11
+    // but are needed as extra information in card
+    CK_BYTE     _ctrIndex;
+    CK_BYTE     _keySpec;
+
+public:
+    PublicKeyObject();
+    virtual ~PublicKeyObject();
+
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by PKCS11Module.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,132 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_digit.h"
+
+/**
+ * Computes a = b * c, where b and c are digits.
+ *
+ * Lengths: a[2].
+ */
+void NN_DigitMult (NN_DIGIT a[2], NN_DIGIT b, NN_DIGIT c)
+{
+    NN_DIGIT t, u;
+    NN_HALF_DIGIT bHigh, bLow, cHigh, cLow;
+
+    bHigh = (NN_HALF_DIGIT)HIGH_HALF (b);
+    bLow = (NN_HALF_DIGIT)LOW_HALF (b);
+    cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
+    cLow = (NN_HALF_DIGIT)LOW_HALF (c);
+
+    a[0] = (NN_DIGIT)bLow * (NN_DIGIT)cLow;
+    t = (NN_DIGIT)bLow * (NN_DIGIT)cHigh;
+    u = (NN_DIGIT)bHigh * (NN_DIGIT)cLow;
+    a[1] = (NN_DIGIT)bHigh * (NN_DIGIT)cHigh;
+
+    if ((t += u) < u)
+        a[1] += TO_HIGH_HALF (1);
+    u = TO_HIGH_HALF (t);
+
+    if ((a[0] += u) < u)
+        a[1]++;
+    a[1] += HIGH_HALF (t);
+
+    return ;
+}
+
+/**
+ * Sets a = b / c, where a and c are digits.
+ *
+ * Lengths: b[2].
+ * Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be
+ * normalized.
+ */
+void NN_DigitDiv (NN_DIGIT *a, NN_DIGIT b[2], NN_DIGIT c)
+{
+    NN_DIGIT t[2], u, v;
+    NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
+
+    cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
+    cLow = (NN_HALF_DIGIT)LOW_HALF (c);
+
+    t[0] = b[0];
+    t[1] = b[1];
+
+    /**
+     * Underestimate high half of quotient and subtract.
+     */
+    if (cHigh == MAX_NN_HALF_DIGIT)
+        aHigh = (NN_HALF_DIGIT)HIGH_HALF (t[1]);
+    else
+        aHigh = (NN_HALF_DIGIT)(t[1] / (cHigh + 1));
+
+    u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow;
+    v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh;
+    if ((t[0] -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u)))
+        t[1]--;
+    t[1] -= HIGH_HALF (u);
+    t[1] -= v;
+
+    /**
+     * Correct estimate.
+     */
+    while ((t[1] > cHigh) ||
+         ((t[1] == cHigh) && (t[0] >= TO_HIGH_HALF (cLow))))
+    {
+        if ((t[0] -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow))
+            t[1]--;
+        t[1] -= cHigh;
+        aHigh++;
+    }
+
+    /**
+     * Underestimate low half of quotient and subtract.
+     */
+    if (cHigh == MAX_NN_HALF_DIGIT)
+        aLow = (NN_HALF_DIGIT)LOW_HALF (t[1]);
+    else
+        aLow = (NN_HALF_DIGIT)((TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) / (cHigh + 1));
+
+    u = (NN_DIGIT)aLow * (NN_DIGIT)cLow;
+    v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh;
+    if ((t[0] -= u) > (MAX_NN_DIGIT - u))
+        t[1]--;
+    if ((t[0] -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v)))
+        t[1]--;
+    t[1] -= HIGH_HALF (v);
+
+    /**
+     * Correct estimate.
+     */
+    while ((t[1] > 0) || ((t[1] == 0) && t[0] >= c))
+    {
+        if ((t[0] -= c) > (MAX_NN_DIGIT - c))
+            t[1]--;
+        aLow++;
+    }
+
+    *a = TO_HIGH_HALF (aHigh) + aLow;
+
+    return ;
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,28 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_DIGIT_H_
+#define _CR_DIGIT_H_
+
+void NN_DigitMult(NN_DIGIT [2], NN_DIGIT, NN_DIGIT) ;
+void NN_DigitDiv(NN_DIGIT *, NN_DIGIT [2], NN_DIGIT) ;
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,55 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_GLOBAL_H_
+#define _CR_GLOBAL_H_
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+typedef unsigned long int UINT4;
+
+/* Error codes.
+ */
+#define RE_CONTENT_ENCODING		0x0400
+#define RE_DATA					0x0401
+#define RE_DIGEST_ALGORITHM		0x0402
+#define RE_ENCODING				0x0403
+#define RE_KEY					0x0404
+#define RE_KEY_ENCODING			0x0405
+#define RE_LEN					0x0406
+#define RE_MODULUS_LEN			0x0407
+#define RE_NEED_RANDOM			0x0408
+#define RE_PRIVATE_KEY			0x0409
+#define RE_PUBLIC_KEY			0x040a
+#define RE_SIGNATURE			0x040b
+#define RE_SIGNATURE_ENCODING	0x040c
+#define RE_ENCRYPTION_ALGORITHM 0x040d
+
+#define R_memset(x, y, z)   memset(x, y, z)
+#define R_memcpy(x, y, z)   memcpy(x, y, z)
+#define R_memcmp(x, y, z)   memcmp(x, y, z)
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,695 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_rsa.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_digit.h"
+
+static NN_DIGIT NN_AddDigitMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
+static NN_DIGIT NN_SubDigitMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
+
+static unsigned int NN_DigitBits(NN_DIGIT);
+
+/**
+ * Decodes character string b into a, where character string is ordered
+ * from most to least significant.
+ *
+ * Lengths: a[digits], b[len].
+ * Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
+ * significant bytes are truncated.)
+ */
+void NN_Decode (NN_DIGIT *a,
+                unsigned int digits,
+                const unsigned char *b,
+                unsigned int len)
+{
+    NN_DIGIT t;
+    int j;
+    unsigned int i, u;
+
+    for (i = 0, j = len - 1; i < digits && j >= 0; i++)
+    {
+        t = 0;
+        for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
+            t |= ((NN_DIGIT)b[j]) << u;
+        a[i] = t;
+    }
+
+    for (; i < digits; i++)
+        a[i] = 0;
+
+    return ;
+}
+
+/**
+ * Encodes b into character string a, where character string is ordered
+ * from most to least significant.
+ *
+ * Lengths: a[len], b[digits].
+ * Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
+ * digits are truncated.)
+ */
+void NN_Encode (unsigned char *a,
+                unsigned int len,
+                NN_DIGIT *b,
+                unsigned int digits)
+{
+    NN_DIGIT t;
+    int j;
+    unsigned int i, u;
+
+    for (i = 0, j = len - 1; i < digits && j >= 0; i++)
+    {
+        t = b[i];
+        for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
+            a[j] = (unsigned char)(t >> u);
+    }
+
+    for (; j >= 0; j--)
+        a[j] = 0;
+
+    return ;
+}
+
+/**
+ * Assigns a = b.
+ *
+ * Lengths: a[digits], b[digits].
+ */
+void NN_Assign (NN_DIGIT *a, NN_DIGIT *b, unsigned int digits)
+{
+    unsigned int i;
+
+    for (i = 0; i < digits; i++)
+        a[i] = b[i];
+
+    return ;
+}
+
+/**
+ * Assigns a = 0.
+ *
+ * Lengths: a[digits].
+ */
+void NN_AssignZero (NN_DIGIT *a, unsigned int digits)
+{
+    unsigned int i;
+
+    for (i = 0; i < digits; i++)
+        a[i] = 0;
+
+    return ;
+}
+
+/**
+ * Assigns a = 2^b.
+ *
+ * Lengths: a[digits].
+ * Requires b < digits * NN_DIGIT_BITS.
+ */
+void NN_Assign2Exp (NN_DIGIT *a, unsigned int b, unsigned int digits)
+{
+    NN_AssignZero (a, digits);
+
+    if (b >= digits * NN_DIGIT_BITS)
+        return;
+
+    a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
+
+    return ;
+}
+
+/**
+ * Computes a = b + c. Returns carry.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ */
+NN_DIGIT NN_Add (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT ai, carry;
+    unsigned int i;
+
+    carry = 0;
+
+    for (i = 0; i < digits; i++)
+    {
+        if ((ai = b[i] + carry) < carry)
+            ai = c[i];
+        else if ((ai += c[i]) < c[i])
+            carry = 1;
+        else
+            carry = 0;
+        a[i] = ai;
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = b - c. Returns borrow.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ */
+NN_DIGIT NN_Sub (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT ai, borrow;
+    unsigned int i;
+
+    borrow = 0;
+
+    for (i = 0; i < digits; i++)
+    {
+        if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
+            ai = MAX_NN_DIGIT - c[i];
+        else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i]))
+            borrow = 1;
+        else
+            borrow = 0;
+
+        a[i] = ai;
+    }
+
+    return (borrow);
+}
+
+/**
+ * Computes a = b * c.
+ *
+ * Lengths: a[2*digits], b[digits], c[digits].
+ * Assumes digits < MAX_NN_DIGITS.
+ */
+void NN_Mult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT t[2*MAX_NN_DIGITS];
+    unsigned int bDigits, cDigits, i;
+
+    NN_AssignZero (t, 2 * digits);
+
+    bDigits = NN_Digits (b, digits);
+    cDigits = NN_Digits (c, digits);
+
+    for (i = 0; i < bDigits; i++)
+        t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
+
+    NN_Assign (a, t, 2 * digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+
+/**
+ * Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
+ *
+ * Lengths: a[digits], b[digits].
+ * Requires c < NN_DIGIT_BITS.
+ */
+NN_DIGIT NN_LShift (NN_DIGIT *a, NN_DIGIT *b, unsigned int c, unsigned int digits)
+{
+    NN_DIGIT bi, carry;
+    unsigned int i, t;
+
+    if (c >= NN_DIGIT_BITS)
+        return (0);
+
+    t = NN_DIGIT_BITS - c;
+
+    carry = 0;
+
+    for (i = 0; i < digits; i++)
+    {
+        bi = b[i];
+        a[i] = (bi << c) | carry;
+        carry = c ? (bi >> t) : 0;
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
+ *
+ * Lengths: a[digits], b[digits].
+ * Requires: c < NN_DIGIT_BITS.
+ */
+NN_DIGIT NN_RShift (NN_DIGIT *a, NN_DIGIT *b, unsigned int c, unsigned int digits)
+{
+    NN_DIGIT bi, carry;
+    int i;
+    unsigned int t;
+
+    if (c >= NN_DIGIT_BITS)
+        return (0);
+
+    t = NN_DIGIT_BITS - c;
+
+    carry = 0;
+
+    for (i = digits - 1; i >= 0; i--)
+    {
+        bi = b[i];
+        a[i] = (bi >> c) | carry;
+        carry = c ? (bi << t) : 0;
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = c div d and b = c mod d.
+ *
+ * Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
+ * Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
+ *         dDigits < MAX_NN_DIGITS.
+ */
+void NN_Div (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c,
+             unsigned int cDigits, NN_DIGIT *d, unsigned int dDigits)
+{
+    NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
+    int i;
+    unsigned int ddDigits, shift;
+
+    ddDigits = NN_Digits (d, dDigits);
+    if (ddDigits == 0)
+        return;
+
+    /**
+     * Normalize operands.
+     */
+    shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
+    NN_AssignZero (cc, ddDigits);
+    cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
+    NN_LShift (dd, d, shift, ddDigits);
+    t = dd[ddDigits-1];
+
+    NN_AssignZero (a, cDigits);
+
+    for (i = cDigits-ddDigits; i >= 0; i--)
+    {
+        /**
+         * Underestimate quotient digit and subtract.
+         */
+        if (t == MAX_NN_DIGIT)
+            ai = cc[i+ddDigits];
+        else
+            NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
+
+        cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
+
+        /**
+         * Correct estimate.
+         */
+        while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0))
+        {
+            ai++;
+            cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
+        }
+
+        a[i] = ai;
+    }
+
+    /**
+     * Restore result.
+     */
+    NN_AssignZero (b, dDigits);
+    NN_RShift (b, cc, shift, ddDigits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)cc, 0, sizeof (cc));
+    R_memset ((POINTER)dd, 0, sizeof (dd));
+
+    return ;
+}
+
+/**
+ * Computes a = b mod c.
+ *
+ * Lengths: a[cDigits], b[bDigits], c[cDigits].
+ * Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
+ */
+void NN_Mod (NN_DIGIT *a, NN_DIGIT *b, unsigned int bDigits,
+             NN_DIGIT *c, unsigned int cDigits)
+{
+    NN_DIGIT t[2 * MAX_NN_DIGITS];
+
+    NN_Div (t, a, b, bDigits, c, cDigits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+
+/**
+ * Computes a = b * c mod d.
+ *
+ * Lengths: a[digits], b[digits], c[digits], d[digits].
+ * Assumes d > 0, digits < MAX_NN_DIGITS.
+ */
+void NN_ModMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_DIGIT *d,
+                 unsigned int digits)
+{
+    NN_DIGIT t[2*MAX_NN_DIGITS];
+
+    NN_Mult (t, b, c, digits);
+    NN_Mod (a, t, 2 * digits, d, digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+
+/**
+ * Computes a = b^c mod d.
+ *
+ * Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
+ * Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
+ *
+ * NOTE:
+ * PGP 2.5's mpilib contains a faster modular exponentiation routine, mp_modexp.
+ * If USEMPILIB is defined, NN_ModExp is replaced in the PGP 2.5 sources with a
+ * stub call to mp_modexp.  If USEMPILIB is not defined, we'll get a pure (albeit
+ * slower) RSAREF implementation.
+ *
+ * The RSAREF 2.0 license, clause 1(c), permits "...modify[ing] the Program in any
+ * manner for porting or performance improvement purposes..."
+ */
+
+#ifndef USEMPILIB
+void NN_ModExp (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c,
+                unsigned int cDigits, NN_DIGIT *d,
+                unsigned int dDigits)
+{
+    NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
+    int i;
+    unsigned int ciBits, j, s;
+
+    /**
+     * Store b, b^2 mod d, and b^3 mod d.
+     */
+    NN_Assign (bPower[0], b, dDigits);
+    NN_ModMult (bPower[1], bPower[0], b, d, dDigits);
+    NN_ModMult (bPower[2], bPower[1], b, d, dDigits);
+
+    NN_ASSIGN_DIGIT (t, 1, dDigits);
+
+    cDigits = NN_Digits (c, cDigits);
+    for (i = cDigits - 1; i >= 0; i--)
+    {
+        ci = c[i];
+        ciBits = NN_DIGIT_BITS;
+
+        /**
+         * Scan past leading zero bits of most significant digit.
+         */
+        if (i == (int)(cDigits - 1))
+        {
+            while (! DIGIT_2MSB (ci))
+            {
+                ci <<= 2;
+                ciBits -= 2;
+            }
+        }
+
+        for (j = 0; j < ciBits; j += 2, ci <<= 2)
+        {
+            /**
+             * Compute t = t^4 * b^s mod d, where s = two MSB's of ci.
+             */
+            NN_ModMult (t, t, t, d, dDigits);
+            NN_ModMult (t, t, t, d, dDigits);
+
+            if ((s = DIGIT_2MSB (ci)) != 0)
+                NN_ModMult (t, t, bPower[s-1], d, dDigits);
+        }
+    }
+
+    NN_Assign (a, t, dDigits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)bPower, 0, sizeof (bPower));
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return ;
+}
+#endif
+
+/**
+ * Compute a = 1/b mod c, assuming inverse exists.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ * Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
+ */
+void NN_ModInv (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT	q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS],
+                u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS],
+                v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS];
+    int u1Sign;
+
+    /**
+     * Apply extended Euclidean algorithm, modified to avoid negative
+     * numbers.
+     */
+    NN_ASSIGN_DIGIT (u1, 1, digits);
+    NN_AssignZero (v1, digits);
+    NN_Assign (u3, b, digits);
+    NN_Assign (v3, c, digits);
+    u1Sign = 1;
+
+    while (! NN_Zero (v3, digits))
+    {
+        NN_Div (q, t3, u3, digits, v3, digits);
+        NN_Mult (w, q, v1, digits);
+        NN_Add (t1, u1, w, digits);
+        NN_Assign (u1, v1, digits);
+        NN_Assign (v1, t1, digits);
+        NN_Assign (u3, v3, digits);
+        NN_Assign (v3, t3, digits);
+        u1Sign = -u1Sign;
+    }
+
+    /**
+     * Negate result if sign is negative.
+     */
+    if (u1Sign < 0)
+        NN_Sub (a, c, u1, digits);
+    else
+        NN_Assign (a, u1, digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)q, 0, sizeof (q));
+    R_memset ((POINTER)t1, 0, sizeof (t1));
+    R_memset ((POINTER)t3, 0, sizeof (t3));
+    R_memset ((POINTER)u1, 0, sizeof (u1));
+    R_memset ((POINTER)u3, 0, sizeof (u3));
+    R_memset ((POINTER)v1, 0, sizeof (v1));
+    R_memset ((POINTER)v3, 0, sizeof (v3));
+    R_memset ((POINTER)w, 0, sizeof (w));
+
+    return ;
+}
+
+/**
+ * Computes a = gcd(b, c).
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ * Assumes b > c, digits < MAX_NN_DIGITS.
+ */
+void NN_Gcd (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+    NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
+
+    NN_Assign (u, b, digits);
+    NN_Assign (v, c, digits);
+
+    while (! NN_Zero (v, digits))
+    {
+        NN_Mod (t, u, digits, v, digits);
+        NN_Assign (u, v, digits);
+        NN_Assign (v, t, digits);
+    }
+
+    NN_Assign (a, u, digits);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)t, 0, sizeof (t));
+    R_memset ((POINTER)u, 0, sizeof (u));
+    R_memset ((POINTER)v, 0, sizeof (v));
+}
+
+/**
+ * Returns sign of a - b.
+ *
+ * Lengths: a[digits], b[digits].
+ */
+int NN_Cmp (NN_DIGIT *a, NN_DIGIT *b, unsigned int digits)
+{
+    int i;
+
+    for (i = digits - 1; i >= 0; i--)
+    {
+        if (a[i] > b[i])
+            return (1);
+        if (a[i] < b[i])
+            return (-1);
+    }
+
+    return (0);
+}
+
+/**
+ * Returns nonzero iff a is zero.
+ *
+ * Lengths: a[digits].
+ */
+int NN_Zero (NN_DIGIT *a, unsigned int digits)
+{
+    unsigned int i;
+
+    for (i = 0; i < digits; i++)
+      if (a[i])
+        return (0);
+
+    return (1);
+}
+
+/**
+ * Returns the significant length of a in bits.
+ *
+ * Lengths: a[digits].
+ */
+unsigned int NN_Bits (NN_DIGIT *a, unsigned int digits)
+{
+    if ((digits = NN_Digits (a, digits)) == 0)
+        return (0);
+
+    return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
+}
+
+/**
+ * Returns the significant length of a in digits.
+ *
+ * Lengths: a[digits].
+ */
+unsigned int NN_Digits (NN_DIGIT *a, unsigned int digits)
+{
+    int i;
+
+    for (i = digits - 1; i >= 0; i--)
+        if (a[i])
+            break;
+
+    return (i + 1);
+}
+
+/**
+ * Computes a = b + c*d, where c is a digit. Returns carry.
+ *
+ * Lengths: a[digits], b[digits], d[digits].
+ */
+static NN_DIGIT NN_AddDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c,
+                                 NN_DIGIT *d, unsigned int digits)
+{
+    NN_DIGIT carry, t[2];
+    unsigned int i;
+
+    if (c == 0)
+        return (0);
+
+    carry = 0;
+    for (i = 0; i < digits; i++)
+    {
+        NN_DigitMult (t, c, d[i]);
+        if ((a[i] = b[i] + carry) < carry)
+            carry = 1;
+        else
+            carry = 0;
+        if ((a[i] += t[0]) < t[0])
+            carry++;
+        carry += t[1];
+    }
+
+    return (carry);
+}
+
+/**
+ * Computes a = b - c*d, where c is a digit. Returns borrow.
+ *
+ * Lengths: a[digits], b[digits], d[digits].
+ */
+static NN_DIGIT NN_SubDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c,
+                                 NN_DIGIT *d, unsigned int digits)
+{
+    NN_DIGIT borrow, t[2];
+    unsigned int i;
+
+    if (c == 0)
+        return (0);
+
+    borrow = 0;
+    for (i = 0; i < digits; i++)
+    {
+        NN_DigitMult (t, c, d[i]);
+        if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
+            borrow = 1;
+        else
+            borrow = 0;
+        if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
+            borrow++;
+        borrow += t[1];
+    }
+
+    return (borrow);
+}
+
+/**
+ *  Returns the significant length of a in bits, where a is a digit.
+ */
+static unsigned int NN_DigitBits (NN_DIGIT a)
+{
+    unsigned int i;
+
+    for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)
+        if (a == 0)
+            break;
+
+    return (i);
+}
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,147 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_NN_H_
+#define _CR_NN_H_
+
+
+/**
+ * Type definitions.
+ */
+typedef UINT4 NN_DIGIT;
+typedef UINT2 NN_HALF_DIGIT;
+
+/**
+ * Constants:
+ *
+ * Note: MAX_NN_DIGITS is long enough to hold any RSA modulus, plus
+ * one more digit as required by R_GeneratePEMKeys (for n and phiN,
+ * whose lengths must be even). All natural numbers have at most
+ * MAX_NN_DIGITS digits, except for double-length intermediate values
+ * in NN_Mult (t), NN_ModMult (t), NN_ModInv (w), and NN_Div (c).
+ */
+
+/**
+ * Length of digit in bits
+ */
+#define NN_DIGIT_BITS		32
+#define NN_HALF_DIGIT_BITS	16
+
+/**
+ * Length of digit in bytes
+ */
+#define NN_DIGIT_LEN		(NN_DIGIT_BITS / 8)
+
+/**
+ * Maximum length in digits
+ */
+#define MAX_NN_DIGITS \
+  ((MAX_RSA_MODULUS_LEN + NN_DIGIT_LEN - 1) / NN_DIGIT_LEN + 1)
+
+/**
+ *  Maximum digits
+ */
+#define MAX_NN_DIGIT		0xffffffff
+#define MAX_NN_HALF_DIGIT	0xffff
+
+/**
+ * Some macros:
+ */
+#define LOW_HALF(x) ((x) & MAX_NN_HALF_DIGIT)
+#define HIGH_HALF(x) (((x) >> NN_HALF_DIGIT_BITS) & MAX_NN_HALF_DIGIT)
+#define TO_HIGH_HALF(x) (((NN_DIGIT)(x)) << NN_HALF_DIGIT_BITS)
+#define DIGIT_MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 1)) & 1)
+#define DIGIT_2MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 2)) & 3)
+
+#define NN_ASSIGN_DIGIT(a, b, digits) {NN_AssignZero (a, digits); a[0] = b;}
+#define NN_EQUAL(a, b, digits) (! NN_Cmp (a, b, digits))
+#define NN_EVEN(a, digits) (((digits) == 0) || ! (a[0] & 1))
+
+
+/**
+ * Declaration of conversion functions:
+ *
+   NN_Decode (a, digits, b, len)   Decodes character string b into a.
+   NN_Encode (a, len, b, digits)   Encodes a into character string b.
+
+   ASSIGNMENTS
+   NN_Assign (a, b, digits)        Assigns a = b.
+   NN_ASSIGN_DIGIT (a, b, digits)  Assigns a = b, where b is a digit.
+   NN_AssignZero (a, b, digits)    Assigns a = 0.
+   NN_Assign2Exp (a, b, digits)    Assigns a = 2^b.
+
+   ARITHMETIC OPERATIONS
+   NN_Add (a, b, c, digits)        Computes a = b + c.
+   NN_Sub (a, b, c, digits)        Computes a = b - c.
+   NN_Mult (a, b, c, digits)       Computes a = b * c.
+   NN_LShift (a, b, c, digits)     Computes a = b * 2^c.
+   NN_RShift (a, b, c, digits)     Computes a = b / 2^c.
+   NN_Div (a, b, c, cDigits, d, dDigits)  Computes a = c div d and b = c mod d.
+
+   NUMBER THEORY
+   NN_Mod (a, b, bDigits, c, cDigits)  Computes a = b mod c.
+   NN_ModMult (a, b, c, d, digits) Computes a = b * c mod d.
+   NN_ModExp (a, b, c, cDigits, d, dDigits)  Computes a = b^c mod d.
+   NN_ModInv (a, b, c, digits)     Computes a = 1/b mod c.
+   NN_Gcd (a, b, c, digits)        Computes a = gcd (b, c).
+
+   OTHER OPERATIONS
+   NN_EVEN (a, digits)             Returns 1 iff a is even.
+   NN_Cmp (a, b, digits)           Returns sign of a - b.
+   NN_EQUAL (a, digits)            Returns 1 iff a = b.
+   NN_Zero (a, digits)             Returns 1 iff a = 0.
+   NN_Digits (a, digits)           Returns significant length of a in digits.
+   NN_Bits (a, digits)             Returns significant length of a in bits.
+ *
+ */
+
+/**
+ * The third parameter changed from 'unsigned char *'
+ */
+void NN_Decode(NN_DIGIT *, unsigned int, const unsigned char *, unsigned int);
+
+void NN_Encode(unsigned char *, unsigned int, NN_DIGIT *, unsigned int);
+
+void NN_Assign(NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_AssignZero(NN_DIGIT *, unsigned int);
+void NN_Assign2Exp(NN_DIGIT *, unsigned int, unsigned int);
+
+NN_DIGIT NN_Add(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+NN_DIGIT NN_Sub(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Mult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Div(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+NN_DIGIT NN_LShift(NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int);
+NN_DIGIT NN_RShift(NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int);
+
+void NN_Mod(NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+void NN_ModMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_ModExp(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+void NN_ModInv(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Gcd(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+
+int NN_Cmp(NN_DIGIT *, NN_DIGIT *, unsigned int);
+int NN_Zero(NN_DIGIT *, unsigned int);
+unsigned int NN_Bits(NN_DIGIT *, unsigned int);
+unsigned int NN_Digits(NN_DIGIT *, unsigned int);
+
+
+#endif /* _CR_NN_H_ */
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,170 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "ha_config.h"
+#include "cr_random.h"
+#include "cr_global.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "md5.h"
+
+#include "cr_rsa.h"
+
+#define RANDOM_BYTES_NEEDED 256
+
+int R_GenerateBytes(
+    unsigned char *block,				/* block			*/
+    unsigned int blockLen,				/* length of block	*/
+    R_RANDOM_STRUCT *randomStruct)		/* random structure */
+{
+    unsigned int available, i;
+
+    if (randomStruct->bytesNeeded)
+    {
+        return (RE_NEED_RANDOM);
+    }
+
+    available = randomStruct->outputAvailable;
+
+    while (blockLen > available)
+    {
+        R_memcpy( (POINTER)block,
+                  (POINTER)&randomStruct->output[16-available],
+                  available) ;
+        block += available;
+        blockLen -= available;
+
+        // Generate new output
+        CMD5* md4Ctx = new CMD5();
+        md4Ctx->HashCore(randomStruct->state,0,16);
+        md4Ctx->HashFinal(randomStruct->output);
+        delete md4Ctx;
+
+        available = 16;
+
+        /**
+         * increment state
+         */
+        for (i = 0; i < 16; i++)
+        {
+            if (randomStruct->state[15-i]++)
+                break;
+        }
+    }
+
+    R_memcpy((POINTER)block, (POINTER)&randomStruct->output[16-available], blockLen);
+    randomStruct->outputAvailable = available - blockLen;
+
+    return (0);
+}
+
+
+int R_RandomInit(R_RANDOM_STRUCT *randomStruct)
+{
+    randomStruct->bytesNeeded = RANDOM_BYTES_NEEDED;
+    R_memset ((POINTER)randomStruct->state, 0, sizeof (randomStruct->state));
+    randomStruct->outputAvailable = 0;
+
+    return (0);
+}
+
+
+int R_RandomUpdate(
+    R_RANDOM_STRUCT *randomStruct,            /* random structure			*/
+    unsigned char *block,                     /* block of values to mix in	*/
+    unsigned int blockLen)                    /* length of block			*/
+{
+    unsigned char digest[16];
+    unsigned int i, x;
+
+    CMD5* md5Ctx = new CMD5();
+    md5Ctx->HashCore(block,0,blockLen);
+    md5Ctx->HashFinal(digest);
+    delete md5Ctx;
+
+    /* add digest to state */
+    x = 0;
+    for (i = 0; i < 16; i++)
+    {
+        x += randomStruct->state[15-i] + digest[15-i];
+        randomStruct->state[15-i] = (unsigned char)x;
+        x >>= 8;
+    }
+
+    if (randomStruct->bytesNeeded < blockLen)
+        randomStruct->bytesNeeded = 0;
+    else
+        randomStruct->bytesNeeded -= blockLen;
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)digest, 0, sizeof (digest));
+    x = 0;
+
+    return (0);
+}
+
+
+int R_GetRandomBytesNeeded(
+    unsigned int *bytesNeeded,             /* number of mix-in bytes needed */
+    R_RANDOM_STRUCT *randomStruct)         /* random structure				*/
+{
+    *bytesNeeded = randomStruct->bytesNeeded;
+    return (0);
+}
+
+
+void R_RandomFinal(R_RANDOM_STRUCT *randomStruct)
+{
+    R_memset((POINTER)randomStruct, 0, sizeof (*randomStruct)) ;
+}
+
+
+/**
+ * Initialize the random structure with all zero seed bytes.
+ *
+ * NOTE: that this will cause the output of the "random" process
+ * to be the same every time. To produce random bytes, the random
+ * struct needs random seeds.
+ */
+void InitRandomStruct(R_RANDOM_STRUCT *randomStruct)
+{
+    static unsigned char seedByte = 0;
+    unsigned int bytesNeeded;
+
+    R_RandomInit (randomStruct);
+
+    /**
+     * Initialize with all zero seed bytes, which will not yield
+     * an actual random number output.
+     */
+    int iCondition = 1;
+    while( iCondition )
+    {
+        R_GetRandomBytesNeeded (&bytesNeeded, randomStruct);
+        if (bytesNeeded == 0)
+            break;
+
+        R_RandomUpdate (randomStruct, &seedByte, 1);
+    }
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,46 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_RANDOM_H_
+#define _CR_RANDOM_H_
+
+
+/**
+ * RSA Random structure.
+ */
+typedef struct {
+    unsigned int  bytesNeeded;
+    unsigned char state[16];
+    unsigned int  outputAvailable;
+    unsigned char output[16];
+} R_RANDOM_STRUCT;
+
+
+int  R_GenerateBytes(unsigned char *, unsigned int, R_RANDOM_STRUCT *);
+
+int  R_RandomInit(R_RANDOM_STRUCT *randomStruct) ;
+void InitRandomStruct(R_RANDOM_STRUCT *randomStruct) ;
+int  R_GetRandomBytesNeeded(unsigned int *bytesNeeded, R_RANDOM_STRUCT *randomStruct) ;
+int  R_RandomUpdate(R_RANDOM_STRUCT *randomStruct, unsigned char *block, unsigned int blockLen) ;
+void R_RandomFinal(R_RANDOM_STRUCT *randomStruct) ;
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,375 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_rsa.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_random.h"
+
+#include "ha_config.h"
+
+/**
+ * RSA private-key decryption, according to PKCS #1.
+ */
+int RSAPrivateDecrypt(
+    unsigned char *output,				/* output block				*/
+    unsigned int *outputLen,            /* length of output block	*/
+    unsigned char *input,               /* input block				*/
+    unsigned int inputLen,              /* length of input block	*/
+    R_RSA_PRIVATE_KEY *privateKey)      /* RSA private key			*/
+{
+    int status;
+    unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen, pkcsBlockLen;
+
+    modulusLen = (privateKey->bits + 7) / 8;
+    if (inputLen > modulusLen)
+        return (RE_LEN);
+
+    //if (status = RSAPrivateBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey))
+    status = RSAPrivateBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey);
+    if ( status )
+        return (status);
+
+    if (pkcsBlockLen != modulusLen)
+        return (RE_LEN);
+
+    /* Require block type 2.
+    */
+    if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 2))
+        return (RE_DATA);
+
+    for (i = 2; i < modulusLen-1; i++)
+    {
+        if (pkcsBlock[i] == 0)
+            break;
+    }
+
+    i++;
+    if (i >= modulusLen)
+        return (RE_DATA);
+
+    *outputLen = modulusLen - i;
+
+    if (*outputLen + 11 > modulusLen)
+        return (RE_DATA);
+
+    R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (0);
+}
+
+
+/**
+ * Raw RSA private-key operation. Output has same length as modulus.
+ *
+ * Assumes inputLen < length of modulus.
+ * Requires input < modulus.
+ */
+int RSAPrivateBlock (
+    unsigned char *output,              /* output block				*/
+    unsigned int *outputLen,            /* length of output block	*/
+    unsigned char *input,               /* input block				*/
+    unsigned int inputLen,              /* length of input block	*/
+    R_RSA_PRIVATE_KEY *privateKey)      /* RSA private key			*/
+{
+    NN_DIGIT	c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS],
+                dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS],
+                mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS],
+                q[MAX_NN_DIGITS], qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS] ;
+
+    unsigned int cDigits, nDigits, pDigits;
+    unsigned int len_Mod, len_Prime ;
+
+    len_Mod = (privateKey->bits + 7) / 8  ;
+    len_Prime = (((privateKey->bits + 1) / 2) + 7) / 8 ;
+
+    NN_Decode (c, MAX_NN_DIGITS, input, inputLen);
+    NN_Decode (n, MAX_NN_DIGITS, privateKey->modulus, len_Mod);
+    NN_Decode (p, MAX_NN_DIGITS, privateKey->prime[0], len_Prime);
+    NN_Decode (q, MAX_NN_DIGITS, privateKey->prime[1], len_Prime);
+    NN_Decode (dP, MAX_NN_DIGITS, privateKey->primeExponent[0], len_Prime);
+    NN_Decode (dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], len_Prime);
+    NN_Decode (qInv, MAX_NN_DIGITS, privateKey->coefficient, len_Prime);
+
+    cDigits = NN_Digits (c, MAX_NN_DIGITS);
+    nDigits = NN_Digits (n, MAX_NN_DIGITS);
+    pDigits = NN_Digits (p, MAX_NN_DIGITS);
+
+    if (NN_Cmp (c, n, nDigits) >= 0)
+        return (RE_DATA);
+
+    /**
+     * Compute mP = cP^dP mod p  and  mQ = cQ^dQ mod q. (Assumes q has
+     * length at most pDigits, i.e., p > q.)
+     */
+    NN_Mod (cP, c, cDigits, p, pDigits);
+    NN_Mod (cQ, c, cDigits, q, pDigits);
+    NN_ModExp (mP, cP, dP, pDigits, p, pDigits);
+    NN_AssignZero (mQ, nDigits);
+    NN_ModExp (mQ, cQ, dQ, pDigits, q, pDigits);
+
+    /**
+     * Chinese Remainder Theorem:
+     * m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ.
+     */
+    if (NN_Cmp (mP, mQ, pDigits) >= 0)
+    {
+        NN_Sub (t, mP, mQ, pDigits);
+    }
+    else
+    {
+        NN_Sub (t, mQ, mP, pDigits);
+        NN_Sub (t, p, t, pDigits);
+    }
+    NN_ModMult (t, t, qInv, p, pDigits);
+    NN_Mult (t, t, q, pDigits);
+    NN_Add (t, t, mQ, nDigits);
+
+    *outputLen = (privateKey->bits + 7) / 8;
+    NN_Encode (output, *outputLen, t, nDigits);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)c, 0, sizeof (c));
+    R_memset ((POINTER)cP, 0, sizeof (cP));
+    R_memset ((POINTER)cQ, 0, sizeof (cQ));
+    R_memset ((POINTER)dP, 0, sizeof (dP));
+    R_memset ((POINTER)dQ, 0, sizeof (dQ));
+    R_memset ((POINTER)mP, 0, sizeof (mP));
+    R_memset ((POINTER)mQ, 0, sizeof (mQ));
+    R_memset ((POINTER)p, 0, sizeof (p));
+    R_memset ((POINTER)q, 0, sizeof (q));
+    R_memset ((POINTER)qInv, 0, sizeof (qInv));
+    R_memset ((POINTER)t, 0, sizeof (t));
+
+    return (0);
+}
+
+
+/**
+ * RSA public-key encryption, according to PKCS #1.
+ */
+int RSAPublicEncrypt(
+    unsigned char *output,				/* output block				*/
+    unsigned int *outputLen,			/* length of output block	*/
+    unsigned char *input,				/* input block				*/
+    unsigned int inputLen,				/* length of input block	*/
+    R_RSA_PUBLIC_KEY *publicKey,		/* RSA public key			*/
+    R_RANDOM_STRUCT *randomStruct)		/* random structure			*/
+{
+    int status;
+    unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen;
+
+    modulusLen = (publicKey->bits + 7) / 8;
+    if (inputLen + 11 > modulusLen)
+    {
+        return (RE_LEN);
+    }
+
+    /**
+     * block type 2
+     */
+    pkcsBlock[0] = 0;
+    pkcsBlock[1] = 2;
+
+    for (i = 2; i < modulusLen - inputLen - 1; i++)
+    {
+        /**
+         * Find nonzero random byte.
+         */
+        do {
+          R_GenerateBytes (&byte, 1, randomStruct);
+        } while (byte == 0);
+
+        pkcsBlock[i] = byte;
+    }
+
+    /**
+     * separator
+     */
+    pkcsBlock[i++] = 0;
+    R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
+    status = RSAPublicBlock(output, outputLen, pkcsBlock, modulusLen, publicKey);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    byte = 0;
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (status);
+}
+
+
+/**
+ * Raw RSA public-key operation. Output has same length as modulus.
+ *
+ * Assumes inputLen < length of modulus.
+ * Requires input < modulus.
+ */
+int RSAPublicBlock(
+    unsigned char *output,				/* output block				*/
+    unsigned int *outputLen,			/* length of output block	*/
+    unsigned char *input,				/* input block				*/
+    unsigned int inputLen,				/* length of input block	*/
+    R_RSA_PUBLIC_KEY *publicKey)		/* RSA public key			*/
+{
+    unsigned int eDigits, nDigits;
+    NN_DIGIT c[MAX_NN_DIGITS],
+             e[MAX_NN_DIGITS],
+             m[MAX_NN_DIGITS],
+             n[MAX_NN_DIGITS] ;
+
+    unsigned int len_Mod ;
+
+    len_Mod = (publicKey->bits + 7) / 8  ;
+
+    NN_Decode (m, MAX_NN_DIGITS, input, inputLen);
+    NN_Decode (n, MAX_NN_DIGITS, publicKey->modulus, len_Mod);
+    NN_Decode (e, MAX_NN_DIGITS, publicKey->exponent, len_Mod);
+    nDigits = NN_Digits (n, MAX_NN_DIGITS);
+    eDigits = NN_Digits (e, MAX_NN_DIGITS);
+
+    if (NN_Cmp (m, n, nDigits) >= 0)
+    {
+        return (RE_DATA);
+    }
+
+    /**
+     * Compute c = m^e mod n.
+     */
+    NN_ModExp (c, m, e, eDigits, n, nDigits);
+
+    *outputLen = (publicKey->bits + 7) / 8;
+    NN_Encode (output, *outputLen, c, nDigits);
+
+    /**
+     * Zeroize sensitive information.
+     */
+    R_memset ((POINTER)c, 0, sizeof (c));
+    R_memset ((POINTER)m, 0, sizeof (m));
+
+    return (0);
+}
+
+
+/**
+ * RSA public-key decryption, according to PKCS #1.
+ */
+int RSAPublicDecrypt(
+    unsigned char *output,              /* output block				*/
+    unsigned int *outputLen,            /* length of output block	*/
+    unsigned char *input,               /* input block				*/
+    unsigned int inputLen,              /* length of input block	*/
+    R_RSA_PUBLIC_KEY *publicKey)        /* RSA public key			*/
+{
+    int status;
+    unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen, pkcsBlockLen;
+
+    modulusLen = (publicKey->bits + 7) / 8;
+    if (inputLen > modulusLen)
+        return (RE_LEN);
+
+    status = RSAPublicBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey) ;
+    if (status)
+        return (status);
+
+    if (pkcsBlockLen != modulusLen)
+        return (RE_LEN);
+
+    /**
+     * Require block type 1.
+     */
+    if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1))
+        return (RE_DATA);
+
+    for (i = 2; i < modulusLen-1; i++)
+    {
+        if (pkcsBlock[i] != 0xff)
+            break;
+    }
+
+    /* separator */
+    if (pkcsBlock[i++] != 0)
+        return (RE_DATA);
+
+    *outputLen = modulusLen - i;
+
+    if (*outputLen + 11 > modulusLen)
+        return (RE_DATA);
+
+    R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
+
+    /**
+     * Zeroize potentially sensitive information.
+     */
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (0);
+}
+
+/* RSA private-key encryption, according to PKCS #1.
+ */
+int RSAPrivateEncrypt(
+    unsigned char *output,                                      /* output block */
+    unsigned int *outputLen,                          /* length of output block */
+    unsigned char *input,                                        /* input block */
+    unsigned int inputLen,                             /* length of input block */
+    R_RSA_PRIVATE_KEY *privateKey)                           /* RSA private key */
+{
+    int status;
+    unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+    unsigned int i, modulusLen;
+
+    modulusLen = (privateKey->bits + 7) / 8;
+    if (inputLen + 11 > modulusLen)
+        return (RE_LEN);
+
+    pkcsBlock[0] = 0;
+    /* block type 1 */
+    pkcsBlock[1] = 1;
+
+    for (i = 2; i < modulusLen - inputLen - 1; i++)
+    pkcsBlock[i] = 0xff;
+
+    /* separator */
+    pkcsBlock[i++] = 0;
+
+    R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
+
+    status = RSAPrivateBlock(output, outputLen, pkcsBlock, modulusLen, privateKey);
+
+    /* Zeroize potentially sensitive information.
+    */
+    R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+    return (status);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,157 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _CR_RSA_H_
+#define _CR_RSA_H_
+
+#include "cr_random.h"
+
+/**
+ * RSA key lengths.
+ */
+#define MIN_RSA_MODULUS_BITS	512
+#define MAX_RSA_MODULUS_BITS	2048
+#define MAX_RSA_MODULUS_LEN		((MAX_RSA_MODULUS_BITS + 7) / 8)
+#define MAX_RSA_PRIME_BITS		((MAX_RSA_MODULUS_BITS + 1) / 2)
+#define MAX_RSA_PRIME_LEN		((MAX_RSA_PRIME_BITS + 7) / 8)
+
+
+/**
+ * RSA public key struct.
+ */
+typedef struct {
+    unsigned int bits;                           /* length in bits of modulus */
+    unsigned char modulus[MAX_RSA_MODULUS_LEN];                    /* modulus */
+    unsigned char exponent[MAX_RSA_MODULUS_LEN];           /* public exponent */
+} R_RSA_PUBLIC_KEY;
+
+
+/**
+ * RSA private key struct.
+ *
+ * The size of arrays for key should be:
+ *
+ * modulus			[MAX_RSA_MODULUS_LEN]
+ * publicExponent	[MAX_RSA_MODULUS_LEN]
+ * exponent			[MAX_RSA_MODULUS_LEN]
+ * prime[2]			[MAX_RSA_PRIME_LEN]
+ * primeExponent[2]	[MAX_RSA_PRIME_LEN]
+ * coefficient		[MAX_RSA_PRIME_LEN]
+ */
+typedef struct {
+  unsigned int bits;                           /* length in bits of modulus */
+  unsigned char modulus[MAX_RSA_MODULUS_LEN];                    /* modulus */
+  unsigned char publicExponent[MAX_RSA_MODULUS_LEN];     /* public exponent */
+  unsigned char exponent[MAX_RSA_MODULUS_LEN];          /* private exponent */
+  unsigned char prime[2][MAX_RSA_PRIME_LEN];               /* prime factors */
+  unsigned char primeExponent[2][MAX_RSA_PRIME_LEN];   /* exponents for CRT */
+  unsigned char coefficient[MAX_RSA_PRIME_LEN];          /* CRT coefficient */
+} R_RSA_PRIVATE_KEY;
+
+
+/**
+ * RSA prototype key.
+ */
+typedef struct {
+    unsigned int bits;						/* length in bits of modulus		*/
+    int useFermat4;							/* public exponent (1 = F4, 0 = 3)	*/
+} R_RSA_PROTO_KEY;
+
+
+ /**
+ * ------------------------------------------------------------------------
+ * RSA Interfaces
+ * ------------------------------------------------------------------------
+ */
+
+typedef struct
+{
+    DWORD  modulusLength;          /* length (bits) of modulus         */
+    BYTE* modulus;                /* modulus                          */
+    DWORD  publicExponentLength;   /* length (bits) of public exponent */
+    BYTE* publicExponent;         /* public exponent                  */
+} rsaPublicKey_t ;
+
+typedef struct
+{
+    DWORD  modulusLength;          /* length (bits) of modulus         */
+    BYTE* modulus;                /* modulus                          */
+    DWORD  publicExponentLength;   /* length (bits) of public exponent */
+    BYTE* publicExponent;         /* public exponent                  */
+    BYTE* privateExponent;        /* private exponent                 */
+    BYTE* prime[2];               /* prime factors                    */
+    BYTE* primeExponent[2];       /* exponents for CRT                */
+    BYTE* coefficient;            /* CRT coefficient                  */
+} rsaPrivateKey_t ;
+
+
+/**
+ * RSA function declaration for private/public key operation
+ */
+
+int RSAPrivateDecrypt(
+    unsigned char *output,                   /* output block				*/
+    unsigned int *outputLen,                 /* length of output block		*/
+    unsigned char *input,                    /* input block					*/
+    unsigned int inputLen,                   /* length of input block		*/
+    R_RSA_PRIVATE_KEY *privateKey);			 /* RSA private key				*/
+
+int RSAPrivateEncrypt(
+    unsigned char *output,                   /* output block                */
+    unsigned int *outputLen,                 /* length of output block      */
+    unsigned char *input,                    /* input block                 */
+    unsigned int inputLen,                   /* length of input block       */
+    R_RSA_PRIVATE_KEY *privateKey) ;         /* RSA private key				*/
+
+int RSAPrivateBlock(
+    unsigned char *output,                   /* output block				*/
+    unsigned int *outputLen,                 /* length of output block		*/
+    unsigned char *input,                    /* input block					*/
+    unsigned int inputLen,                   /* length of input block		*/
+    R_RSA_PRIVATE_KEY *privateKey) ;         /* RSA private key				*/
+
+
+int RSAPublicEncrypt(
+    unsigned char *output,					 /* output block				*/
+    unsigned int *outputLen,				 /* length of output block		*/
+    unsigned char *input,					 /* input block					*/
+    unsigned int inputLen,					 /* length of input block		*/
+    R_RSA_PUBLIC_KEY *publicKey,			 /* RSA public key				*/
+    R_RANDOM_STRUCT *randomStruct) ;		 /* random structure			*/
+
+
+int RSAPublicBlock(
+    unsigned char *output,					 /* output block				*/
+    unsigned int *outputLen,				 /* length of output block		*/
+    unsigned char *input,					 /* input block					*/
+    unsigned int inputLen,					 /* length of input block		*/
+    R_RSA_PUBLIC_KEY *publicKey) ;			 /* RSA public key				*/
+
+
+int RSAPublicDecrypt(
+    unsigned char *output,                    /* output block				*/
+    unsigned int *outputLen,                  /* length of output block		*/
+    unsigned char *input,                     /* input block				*/
+    unsigned int inputLen,                    /* length of input block		*/
+    R_RSA_PUBLIC_KEY *publicKey) ;            /* RSA public key				*/
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,42 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _HA_CONFIG_H_
+#define _HA_CONFIG_H_
+
+/**
+ * Global typedefs for use in various Host Agent components.
+ * TODO: Choose a single set and use it consistently.
+ */
+
+typedef signed char     s8_t;
+typedef signed short    s16_t;
+typedef signed long     s32_t;
+
+typedef unsigned char   u8_t ;
+typedef unsigned short  u16_t ;
+typedef unsigned long   u32_t ;
+
+typedef unsigned char   u1 ;
+typedef unsigned short  u2 ;
+typedef unsigned int    u4 ;
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,282 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "rsaprivatekeyobject.h"
+
+RSAPrivateKeyObject :: RSAPrivateKeyObject() : PrivateKeyObject()
+{
+    this->_modulus        = NULL_PTR;
+    this->_publicExponent = NULL_PTR;
+    this->_d              = NULL_PTR;
+    this->_p              = NULL_PTR;
+    this->_q              = NULL_PTR;
+    this->_dp             = NULL_PTR;
+    this->_dq             = NULL_PTR;
+    this->_inverseQ       = NULL_PTR;
+
+    this->_keyType        = CKK_RSA;
+
+}
+
+RSAPrivateKeyObject :: ~RSAPrivateKeyObject()
+{
+    if(this->_modulus != NULL_PTR){
+        delete this->_modulus;
+    }
+
+    if(this->_publicExponent != NULL_PTR){
+        delete this->_publicExponent;
+    }
+
+    if(this->_d != NULL_PTR){
+        delete this->_d;
+    }
+
+    if(this->_p != NULL_PTR){
+        delete this->_p;
+    }
+
+    if(this->_q != NULL_PTR){
+        delete this->_q;
+    }
+
+    if(this->_dp != NULL_PTR){
+        delete this->_dp;
+    }
+
+    if(this->_dq != NULL_PTR){
+        delete this->_dq;
+    }
+
+    if(this->_inverseQ != NULL_PTR){
+        delete this->_inverseQ;
+    }
+}
+
+CK_BBOOL RSAPrivateKeyObject ::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+
+        case CKA_MODULUS:
+            return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PUBLIC_EXPONENT:
+            return Util::CompareU1Arrays(this->_publicExponent,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PRIVATE_EXPONENT:
+            return Util::CompareU1Arrays(this->_d,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PRIME_1:
+            return Util::CompareU1Arrays(this->_p,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_PRIME_2:
+            return Util::CompareU1Arrays(this->_q,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_EXPONENT_1:
+            return Util::CompareU1Arrays(this->_dp,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_EXPONENT_2:
+            return Util::CompareU1Arrays(this->_dq,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_COEFFICIENT:
+            return Util::CompareU1Arrays(this->_inverseQ,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return PrivateKeyObject::Compare(attribute);
+    }
+}
+
+CK_RV RSAPrivateKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_PUBLIC_EXPONENT:
+            case CKA_MODULUS:
+            case CKA_PRIVATE_EXPONENT:
+            case CKA_PRIME_1:
+            case CKA_PRIME_2:
+            case CKA_EXPONENT_1:
+            case CKA_EXPONENT_2:
+            case CKA_COEFFICIENT:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+
+         case CKA_MODULUS:
+            if(this->_modulus != NULL_PTR){
+                delete this->_modulus;
+            }
+            this->_modulus = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         case CKA_PUBLIC_EXPONENT:
+            if(this->_publicExponent != NULL_PTR){
+                delete this->_publicExponent;
+            }
+            this->_publicExponent = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         case CKA_PRIVATE_EXPONENT:
+            if(this->_d != NULL_PTR){
+                delete this->_d;
+            }
+            this->_d = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         case CKA_EXPONENT_1:
+            if(this->_dp != NULL_PTR){
+                delete this->_dp;
+            }
+            this->_dp = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_EXPONENT_2:
+            if(this->_dq != NULL_PTR){
+                delete this->_dq;
+            }
+            this->_dq = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_PRIME_1:
+            if(this->_p != NULL_PTR){
+                delete this->_p;
+            }
+            this->_p = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_PRIME_2:
+            if(this->_q != NULL_PTR){
+                delete this->_q;
+            }
+            this->_q = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+
+         case CKA_COEFFICIENT:
+            if( this->_inverseQ != NULL_PTR )
+            {
+                delete this->_inverseQ;
+            }
+            this->_inverseQ = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+         default:
+             return PrivateKeyObject::SetAttribute(attribute,objCreation);
+
+    }
+
+    return CKR_OK;
+}
+
+CK_RV RSAPrivateKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type){
+
+        case CKA_MODULUS:
+            return StorageObject::PutU1ArrayInAttribute(this->_modulus,attribute);
+
+        case CKA_PUBLIC_EXPONENT:
+            return StorageObject::PutU1ArrayInAttribute(this->_publicExponent,attribute);
+
+        case CKA_PRIVATE_EXPONENT:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_d,attribute);
+
+        case CKA_PRIME_1:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_p,attribute);
+
+        case CKA_PRIME_2:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_q,attribute);
+
+        case CKA_EXPONENT_1:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_dp,attribute);
+
+        case CKA_EXPONENT_2:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_dq,attribute);
+
+        case CKA_COEFFICIENT:
+            if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+                attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+                return CKR_ATTRIBUTE_SENSITIVE;
+            }
+            return StorageObject::PutU1ArrayInAttribute(this->_inverseQ,attribute);
+
+        default:
+            return PrivateKeyObject::GetAttribute(attribute);
+    }
+}
+
+void RSAPrivateKeyObject::Serialize(std::vector<u1> *to)
+{
+    PrivateKeyObject::Serialize(to);
+
+    // since keys will reside in the key container we are not going
+    // to marshal the key values except modulus and public exponent
+
+    Util::PushByteArrayInVector(to,this->_modulus);
+
+    Util::PushByteArrayInVector(to,this->_publicExponent);
+}
+
+void RSAPrivateKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    PrivateKeyObject::Deserialize(from,idx);
+
+    this->_modulus = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_publicExponent = Util::ReadByteArrayFromVector(from,idx);
+}
+
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_rsaprivatekeyobject_h
+#define _include_rsaprivatekeyobject_h
+
+#include "privatekeyobject.h"
+
+class RSAPrivateKeyObject : public PrivateKeyObject
+{
+
+public:
+    u1Array*    _publicExponent;
+    u1Array*    _modulus;
+    u1Array*    _d;
+    u1Array*    _p;
+    u1Array*    _q;
+    u1Array*    _dp;
+    u1Array*    _dq;
+    u1Array*    _inverseQ;
+
+public:
+     RSAPrivateKeyObject();
+    virtual ~RSAPrivateKeyObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,152 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "rsapublickeyobject.h"
+
+RSAPublicKeyObject :: RSAPublicKeyObject() : PublicKeyObject()
+{
+   this->_modulus    = NULL_PTR;
+   this->_modulusLen = 0;
+   this->_exponent   = NULL_PTR;
+
+   this->_keyType        = CKK_RSA;
+}
+
+RSAPublicKeyObject :: ~RSAPublicKeyObject()
+{
+   if(this->_modulus != NULL_PTR)
+      delete this->_modulus;
+
+   if(this->_exponent != NULL_PTR)
+      delete this->_exponent;
+}
+
+CK_BBOOL RSAPublicKeyObject ::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_MODULUS:
+           return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_MODULUS_BITS:
+           return (this->_modulusLen == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_PUBLIC_EXPONENT:
+           return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+        default:
+           return PublicKeyObject::Compare(attribute);
+   }
+}
+
+CK_RV RSAPublicKeyObject ::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type){
+
+        case CKA_MODULUS:
+           return StorageObject::PutU1ArrayInAttribute(this->_modulus,attribute);
+
+        case CKA_MODULUS_BITS:
+           return StorageObject::PutULongInAttribute(this->_modulusLen,attribute);
+
+        case CKA_PUBLIC_EXPONENT:
+           return StorageObject::PutU1ArrayInAttribute(this->_exponent,attribute);
+
+        default:
+           return PublicKeyObject::GetAttribute(attribute);
+   }
+}
+
+CK_RV RSAPublicKeyObject ::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+   if(objCreation == CK_FALSE){
+      switch(attribute.type){
+            case CKA_PUBLIC_EXPONENT:
+            case CKA_MODULUS:
+            case CKA_MODULUS_BITS:
+               return CKR_ATTRIBUTE_READ_ONLY;
+      }
+   }
+
+   switch(attribute.type){
+
+        case CKA_MODULUS:
+           if(this->_modulus != NULL_PTR){
+              delete this->_modulus;
+           }
+           this->_modulus = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           this->_modulusLen = _modulus->GetLength()*8;
+           break;
+
+        case CKA_PUBLIC_EXPONENT:
+           if(this->_exponent != NULL_PTR){
+              delete this->_exponent;
+           }
+           this->_exponent = StorageObject::ReadU1ArrayFromAttribute(attribute);
+           break;
+
+        case CKA_MODULUS_BITS:
+           {
+              CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+              if(rv == CKR_OK){ this->_modulusLen = utemp;}
+           }
+           break;
+
+        default:
+           return PublicKeyObject::SetAttribute(attribute,objCreation);
+   }
+
+   return rv;
+}
+
+void RSAPublicKeyObject ::Serialize(std::vector<u1> *to)
+{
+   PublicKeyObject::Serialize(to);
+
+   Util::PushByteArrayInVector(to,this->_modulus);
+
+   Util::PushByteArrayInVector(to,this->_exponent);
+
+   Util::PushULongInVector(to,this->_modulusLen);
+}
+
+void RSAPublicKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   PublicKeyObject::Deserialize(from,idx);
+
+   this->_modulus = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_exponent = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_modulusLen = Util::ReadULongFromVector(from,idx);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,49 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_rsapublickeyobject_h
+#define _include_rsapublickeyobject_h
+
+#include "publickeyobject.h"
+
+class RSAPublicKeyObject : public PublicKeyObject
+{
+
+public:
+    u1Array*    _modulus;
+    CK_ULONG    _modulusLen;
+    u1Array*    _exponent;
+
+public:
+    RSAPublicKeyObject();
+    virtual ~RSAPublicKeyObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,4667 @@
+
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include <winscard.h>
+#include <stdexcept>
+#include "cardmoduleservice.h"
+#include <Except.h>
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <memory>
+#include "session.h"
+#include "symmalgo.h"
+#include "tdes.h"
+#include "util.h"
+#include "zlib.h"
+#include "x509cert.h"
+#include "attrcert.h"
+#include "dataobject.h"
+#include "secretkeyobject.h"
+#include "transaction.h"
+#include "cardcache.h"
+#include "error.h"
+#include "timer.h"
+#include "md5.h"
+#include "log.h"
+
+
+#ifdef WIN32
+#include "BioMan.h"
+#else
+#define SCARD_CTL_CODE(code) (0x42000000 + (code))
+#endif
+
+// Helper functions to manage contents of cmapfile
+
+static void CMapFileClear(u1Array & file, u1 index);
+static void CMapFileSetName(u1Array & file, u1 index, string const & name);
+static u1 CMapFileGetFlag(u1Array const & file, u1 index);
+static void CMapFileSetFlag(u1Array & file, u1 index, u1 flag);
+static u2 CMapFileGetSignSize(u1Array const & file, u1 index);
+static void CMapFileSetSignSize(u1Array & file, u1 index, u2 size);
+static u2 CMapFileGetExchSize(u1Array const & file, u1 index);
+static void CMapFileSetExchSize(u1Array & file, u1 index, u2 size);
+
+// software RSA specific inclusion [they would be refined once I go and re-factor RSA algo as per Cryptoki naming convention]
+//#include "crypto_public.h"
+//#include "cr_rsa.h"
+
+#include "sctoken.h"
+
+#define BITS_0_7(l)  ((BYTE)(l & 0xff))
+#define BITS_8_15(l) ((BYTE)(((WORD)l & 0xff00) >> 8))
+
+#define MAX_RETRY 2
+
+#define CARD_PROPERTY_PIN_INFO_EX 0x87
+#define CARD_PROPERTY_PIN_INFO 0x07
+#define CARD_PROPERTY_EXTERNAL_PIN 0x01
+#define CARD_ROLE_USER 0x01
+
+#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
+//#define FEATURE_VERIFY_PIN_START 0x01
+//#define FEATURE_VERIFY_PIN_FINISH 0x02
+//#define FEATURE_MODIFY_PIN_START 0x03
+//#define FEATURE_MODIFY_PIN_FINISH 0x04
+//#define FEATURE_GET_KEY_PRESSED 0x05
+#define FEATURE_VERIFY_PIN_DIRECT 0x06
+//#define FEATURE_MODIFY_PIN_DIRECT 0x07
+//#define FEATURE_MCT_READERDIRECT 0x08
+//#define FEATURE_MCT_UNIVERSAL 0x09
+//#define FEATURE_IFD_PIN_PROP 0x0A
+//#define FEATURE_ABORT 0x0B
+
+#define UVM_PIN_ONLY 1
+#define UVM_FP_ONLY 2
+#define UVM_PIN_OR_FP 3
+#define UVM_PIN_AND_FP 4
+
+#define PIN_TYPE_REGULAR 0
+#define PIN_TYPE_EXTERNAL 1
+
+#define AUTHENTICATE_ERROR 0
+#define AUTHENTICATE_REGULAR 1
+#define AUTHENTICATE_PINPAD 2
+#define AUTHENTICATE_BIO 3
+
+
+#pragma pack(push, mdnet, 1)
+
+typedef struct PIN_VERIFY_STRUCTURE
+{
+   BYTE bTimerOut;                  /* timeout is seconds (00 means use default timeout) */
+   BYTE bTimerOut2;                 /* timeout in seconds after first key stroke */
+   BYTE bmFormatString;             /* formatting options */
+   BYTE bmPINBlockString;           /* bits 7-4 bit size of PIN length in APDU,
+                                    * bits 3-0 PIN block size in bytes after
+                                    * justification and formatting */
+   BYTE bmPINLengthFormat;          /* bits 7-5 RFU,
+                                    * bit 4 set if system units are bytes, clear if
+                                    * system units are bits,
+                                    * bits 3-0 PIN length position in system units
+                                    */
+   BYTE bPINMaxExtraDigit1;         /* Max PIN size*/
+   BYTE bPINMaxExtraDigit2;         /* Min PIN size*/
+   BYTE bEntryValidationCondition;  /* Conditions under which PIN entry should
+                                    * be considered complete */
+   BYTE bNumberMessage;             /* Number of messages to display for PIN
+                                    verification */
+   USHORT wLangId;                  /* Language for messages */
+   BYTE bMsgIndex;                  /* Message index (should be 00) */
+   BYTE bTeoPrologue[3];            /* T=1 block prologue field to use (fill with 00) */
+   ULONG ulDataLength;              /* length of Data to be sent to the ICC */
+   BYTE abData[13];                 /* Data to send to the ICC */
+} PIN_VERIFY_STRUCTURE;
+
+#pragma pack(pop, mdnet)
+
+// Try/catch macros for all public methods
+#define TOKEN_TRY try
+#define TOKEN_CATCH(rv) \
+   catch(CkError & err) { rv = err.Error(); } \
+   catch(PcscError & ) { rv = CKR_FUNCTION_FAILED; } \
+   catch(Marshaller::Exception & exc) { rv = CkError::CheckMarshallerException(exc); } \
+   catch(...) { rv = CKR_GENERAL_ERROR; } \
+   if(rv==CKR_USER_NOT_LOGGED_IN || rv==CKR_PIN_INCORRECT || rv==CKR_PIN_LOCKED) \
+   _roleLogged = CKU_NONE; \
+
+namespace {
+   class CardTransaction
+   {
+   private:
+      Token * _token;
+
+   public:
+      CardTransaction(Token * token) : _token(token)
+      {
+         _token->CardBeginTransaction();
+      }
+
+      ~CardTransaction() throw()
+      {
+         try
+         {
+            _token->CardEndTransaction();
+         }
+         catch(...) {}
+      }
+   };
+}
+
+Token :: Token(std::string* reader) : _mscm(0),
+_supportGarbageCollection(true),
+_cardCache(0),
+_fPinChanged(false),
+_fContainerChanged(false),
+_fFileChanged(false),
+_version(0)
+{
+   //Log::begin( "Token::Token" );
+
+   m_dwIoctlVerifyPIN = 0;
+
+   m_sReaderName = "";
+   if( NULL != reader )
+   {
+      m_sReaderName = (*reader).c_str( );
+   }
+
+   //Log::log( "Token::Token - new CardModuleService..." );
+   std::string svcname("MSCM");
+   _mscm = new CardModuleService( reader, 5, &svcname );
+   //Log::log( "Token::Token - new CardModuleService ok" );
+
+   _mscm->DoSCardTransact(false);  // Turn off transaction handling since it is performed at application level
+
+   // Transact card
+   //Log::log( "Token::Token - CardTransaction..." );
+   CardTransaction ct(this);
+   //Log::log( "Token::Token - CardTransaction ok" );
+
+   //Log::log( "Token::Token - new CardCache..." );
+   _cardCache = new CardCache(_mscm);
+   //Log::log( "Token::Token - new CardCache ok" );
+
+   // Get seed for RNG from card. This is the first command to
+   // card. If it fails, assume the card is not a .NET card.
+   try
+   {
+      //Log::log( "Token::Token - GetChallenge ..." );
+      auto_ptr<u1Array> challange(_mscm->GetChallenge());
+      //Log::log( "Token::Token - GetChallenge ok" );
+
+      Util::SeedRandom(*challange);
+   }
+   catch(...)
+   {
+      Log::error( "Token::Token", "GetChallenge - CKR_TOKEN_NOT_RECOGNIZED" );
+      throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+   }
+
+   this->_roleLogged   = CKU_NONE;
+
+   // flush TokenInfo
+   memset(&this->_tokenInfo, 0x00, sizeof(this->_tokenInfo));
+
+   this->_tokenInfo.ulMaxSessionCount      = CK_EFFECTIVELY_INFINITE;
+   this->_tokenInfo.ulSessionCount         = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulMaxRwSessionCount    = CK_EFFECTIVELY_INFINITE;
+   this->_tokenInfo.ulRwSessionCount       = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulMaxPinLen            = MAX_PIN_LEN;
+   this->_tokenInfo.ulMinPinLen            = MIN_PIN_LEN;
+
+   this->_tokenInfo.ulTotalPublicMemory    = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulTotalPrivateMemory   = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulFreePrivateMemory    = CK_UNAVAILABLE_INFORMATION;
+   this->_tokenInfo.ulFreePublicMemory     = CK_UNAVAILABLE_INFORMATION;
+
+   // Version of the Card Operating system
+   this->_tokenInfo.hardwareVersion.major  = 2;
+   this->_tokenInfo.hardwareVersion.minor  = 0;
+
+   // (TBD) Version of Card Module application
+   // there is mess which have been created by reading it from file etc ?
+   this->_tokenInfo.firmwareVersion.major  = 2;
+   this->_tokenInfo.firmwareVersion.minor  = 0;
+
+   this->_tokenInfo.flags  = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED;
+
+   // Check if the smart card is in SSO mode
+   if( ( true == this->isSSO( ) ) && ( true == this->isAuthenticated( ) ) )
+   {
+      this->_tokenInfo.flags &= ~CKF_LOGIN_REQUIRED;
+   }
+   /*else
+   {
+   this->_tokenInfo.flags |= CKF_LOGIN_REQUIRED;
+   }*/
+
+
+   // Check if the CKF_PROTECTED_AUTHENTICATION_PATH flag must be raised
+   m_isPinPadSupported = isPinPadSupported( );
+   //m_isPinExternal = isPinExternalSupported( );
+   BYTE bCardMode = UVM_PIN_ONLY;
+   BYTE bTypePIN = PIN_TYPE_REGULAR;
+   getCardConfiguration( bCardMode, bTypePIN );
+   Log::log( "Token::Token - PIN type <%ld> (0 = regular ; 1 = external)", bTypePIN );
+   Log::log( "Token::Token - Card mode <%ld> (1 = pin only ; 2 = fp only ; 3 = fp or pin ; 4 = fp and pin)", bCardMode );
+   if( ( bTypePIN == PIN_TYPE_EXTERNAL ) && ( ( ( bCardMode == UVM_PIN_ONLY ) && m_isPinPadSupported ) || ( bCardMode != UVM_PIN_ONLY ) ) )
+   {
+      Log::log( "Token::Token - Enable CKF_PROTECTED_AUTHENTICATION_PATH" );
+      this->_tokenInfo.flags  |= CKF_PROTECTED_AUTHENTICATION_PATH;
+   }
+
+   // we need to check if token is initialized or not.
+   // Initialization would essentially mean that we create
+   // the necessary file structure.
+
+   // Get current value of \cardcf file
+   std::string sCardcf("cardcf");
+
+   //Log::log( "Token::Token - ReadFile ..." );
+   auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardcf,0));
+   //Log::log( "Token::Token - ReadFile ..." );
+
+   if(fileData->GetLength() < 6)
+   {
+      Log::error( "Token::Token", " (fileData->GetLength() < 6) - CKR_TOKEN_NOT_RECOGNIZED" );
+      throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+   }
+   CK_ULONG cardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+
+   this->_initialized  = this->IsInitialized();
+
+   if(_initialized)
+   {
+      //Log::log( "Token::Token - DeserializeTokenInfo ..." );
+      this->DeserializeTokenInfo();
+      //Log::log( "Token::Token - DeserializeTokenInfo ok" );
+   }
+   else
+   {
+      //Log::log( "Token::Token - PopulateDefaultTokenInfo ..." );
+      // fill up the tokenInfo
+      this->PopulateDefaultTokenInfo();
+      //Log::log( "Token::Token - PopulateDefaultTokenInfo ok" );
+   }
+
+   // Set current values unequal to the stored to force the initial syncronization
+   _cardCfTimer = 0;
+   _cardCf = cardCf;
+   _publCardCf = ~cardCf;
+   _privCardCf = ~cardCf;
+   _cacheCardCf = ~cardCf;
+
+   //Log::end( "Token::Token" );
+}
+
+Token :: ~Token()
+{
+   delete _cardCache;
+   delete this->_mscm;
+
+   Clear();
+}
+
+
+
+void Token::ManageGC()
+{
+   if(!_supportGarbageCollection)
+      return;
+   try
+   {
+      s4 freeMemory = _mscm->GetMemory();
+      if (freeMemory < 6000)
+      {
+         Log::log( "Token::ManageGC - ForceGarbageCollector" );
+         _mscm->ForceGarbageCollector( );
+      }
+   }
+   catch(...)
+   {
+      _supportGarbageCollection = false;
+   }
+}
+
+
+void Token::Clear()
+{
+   for(size_t i=0;i<_objects.size();i++)
+      delete _objects[i];
+   _objects.clear();
+}
+
+
+void Token::BeginTransaction()
+{
+   // To improve performance, avoid checking cardcf unless there could possibly
+   // have been an update by external application, based on the time it was last
+   // known to be up-do-date, which means at end of previous transaction.
+
+   static const unsigned long maximumCardCfCheckInterval = 100;  // 100 milliseconds.
+
+   CardBeginTransaction();
+   try
+   {
+      _fPinChanged = false;
+      _fContainerChanged = false;
+      _fFileChanged = false;
+
+      unsigned long tick = CTimer::ClockTicks();
+
+      // First check d.t possible timer wrap around every ~50 days.
+      if(_cardCfTimer > tick || _cardCfTimer + maximumCardCfCheckInterval < tick)
+      {
+         // Read cache file.
+         std::string sCardcf("cardcf");
+         ManageGC( );
+         auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardcf,0));
+         if(fileData->GetLength() < 6)
+            throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+
+         _cardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+      }
+
+      if((_publCardCf != _cardCf) ||
+         ((_privCardCf != _cardCf) && (_roleLogged == CKU_USER)))
+      {
+         // Card changed, so re-synchronize
+         Resynchronize();
+      }
+   }
+   catch(...)
+   {
+      CardEndTransaction();
+      throw;
+   }
+}
+
+void Token::EndTransaction( )
+{
+   try
+   {
+      // Update \cardcf if card has changed.
+      if(_fPinChanged || _fContainerChanged || _fFileChanged)
+      {
+         //  cardcf format:
+         //  typedef struct _CARD_CACHE_FILE_FORMAT
+         //  {
+         //      BYTE bVersion;
+         //      BYTE bPinsFreshness;
+         //      WORD wContainersFreshness;
+         //      WORD wFilesFreshness;
+         //  } CARD_CACHE_FILE_FORMAT, *PCARD_CACHE_FILE_FORMAT;
+
+         //  Read cache file.
+         std::string sCardCf("cardcf");
+         auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardCf,0));
+
+         BYTE bPinsFreshness = fileData->ReadU1At(1);
+         WORD wContainersFreshness = LittleEndianToInt<WORD>(fileData->GetBuffer(),2);
+         WORD wFilesFreshness = LittleEndianToInt<WORD>(fileData->GetBuffer(),4);
+
+         if(_fPinChanged)
+            bPinsFreshness++;
+         if(_fContainerChanged)
+            wContainersFreshness++;
+         if(_fFileChanged)
+            wFilesFreshness++;
+
+         fileData->SetU1At(1, bPinsFreshness);
+         IntToLittleEndian<WORD>(wContainersFreshness, fileData->GetBuffer(),2);
+         IntToLittleEndian<WORD>(wFilesFreshness, fileData->GetBuffer(),4);
+
+         ManageGC( );
+
+         // Write cache file back
+         _mscm->WriteFile(&sCardCf, fileData.get());
+
+         // As a result of own update, our own cache is still valid
+         // as long as it was valid before.
+         CK_ULONG newCardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+
+         if(_publCardCf == _cardCf)
+            _publCardCf = newCardCf;
+         if(_privCardCf == _cardCf)
+            _privCardCf = newCardCf;
+         if(_cacheCardCf == _cardCf)
+            _cacheCardCf = newCardCf;
+
+         _cardCf = newCardCf;
+         _cardCfTimer = CTimer::ClockTicks();
+      }
+      else
+         _cardCfTimer = CTimer::ClockTicks();
+   }
+   catch( CkError x )
+   {
+      CK_RV rv = x.Error( );
+      Log::log( "## Error ## Token::EndTransaction - WriteFile failed <%ld>\n", rv );
+   }
+   catch( ... )
+   {
+   }
+
+   CardEndTransaction( );
+}
+
+void Token::Resynchronize()
+{
+   // To be called at initial creation and also whenever
+   // it is detected that card has been changed.
+   // When re-sync, one have to maintain the object handles
+   // of the objects that have not been deleted. Therefore,
+   // build a new object list and compare with the existing.
+
+   if(_cacheCardCf != _cardCf)
+   {
+      _cardCache->ClearAll();
+      _cacheCardCf = _cardCf;
+   }
+
+   map<int, ContainerInfo> contMap;
+   BuildContainerInfoMap(contMap);
+
+   vector<StorageObject*> newObjects;
+   vector<string> toDelete;
+
+   SynchronizePublicObjects(newObjects, toDelete, contMap);
+   SynchronizeCertificates(newObjects, contMap);
+
+   _publCardCf = _cardCf;
+
+   if(_roleLogged == CKU_USER)
+   {
+      CK_RV rv = CKR_OK;
+      TOKEN_TRY
+      {
+         SynchronizePrivateObjects(newObjects, toDelete, contMap);
+         SynchronizePrivateKeys(newObjects, contMap);
+         _privCardCf = _cardCf;
+      }
+      TOKEN_CATCH(rv);
+   }
+
+   // Build the new list with new objects occupying the
+   // position as the old objects. StorageObject::IsEqual
+   // is used to compare two objects.
+   vector<StorageObject*> objects(_objects.size(), 0);
+   for(size_t iobj = 0; iobj<_objects.size(); ++iobj)
+   {
+      if(!_objects[iobj])
+         continue;
+      for(size_t inew = 0; inew < newObjects.size(); ++inew)
+      {
+         if(newObjects[inew] && newObjects[inew]->IsEqual(_objects[iobj]))
+         {
+            // Transfer ownership
+            objects[iobj] = newObjects[inew];
+            newObjects[inew] = 0;
+            break;
+         }
+      }
+   }
+
+   // Add the potential new objects, which are those left in
+   // newObjects. Add them to the end of the list
+   for(size_t inew = 0; inew < newObjects.size(); ++inew)
+   {
+      if(newObjects[inew])
+         objects.push_back(newObjects[inew]);
+   }
+
+   // Delete the objects in the old object list
+   for(size_t iobj = 0; iobj<_objects.size(); ++iobj)
+      delete _objects[iobj];
+
+   // Store the new list as current
+   _objects = objects;
+
+   // Store the list of files to delete, then delete these if logged in.
+   _toDelete = toDelete;
+
+   if(_roleLogged == CKU_USER)
+      PerformDeferredDelete();
+
+}
+
+u1Array* Token::ComputeCryptogram(u1Array* challenge,u1Array* pin)
+{
+
+   // time to prepare the master key.
+   // Only accept correct length, otherwise
+   // return a zero valued response that is
+   // sure to fail authentication.
+
+   CK_BYTE expectedCryptogram[8];
+   memset(expectedCryptogram,0x00,8);  // Default
+
+   if(pin->GetLength() == 24)
+   {
+      // compute the response
+      CK_BYTE iv[8];
+      memset(iv,0,8);
+
+      CTripleDES tdes;
+
+      tdes.SetEncryptMode(ENCRYPT);
+      tdes.SetIV(iv);
+      tdes.SetCipherMode(CIPHER_MODE_ECB);
+      tdes.SetPaddingMode(PADDING_MODE_NONE);
+      tdes.SetKey(pin->GetBuffer(),24);
+      tdes.TransformFinalBlock(challenge->GetBuffer(),0,8,expectedCryptogram,0);
+   }
+   u1Array* response = new u1Array(8);
+   response->SetBuffer(expectedCryptogram);
+
+   return response;
+}
+
+CK_RV Token::DoPINValidityChecks(u1Array* pin, bool fCheckCharaceters){
+
+   if((pin->GetLength() < MIN_PIN_LEN) || (pin->GetLength() > MAX_PIN_LEN)){
+      return CKR_PIN_LEN_RANGE;
+   }
+
+   if(fCheckCharaceters)
+   {
+      // check if pin is valid
+      for (u4 i = 0; i < pin->GetLength(); i++){
+         if ((pin->GetBuffer()[i] < 0x20) ||
+            (pin->GetBuffer()[i] > 0x7D) ||
+            (pin->GetBuffer()[i] == 0x24)||
+            (pin->GetBuffer()[i] == 0x40)||
+            (pin->GetBuffer()[i] == 0x60))
+         {
+            return CKR_PIN_INVALID;
+         }
+      }
+   }
+   return CKR_OK;
+}
+
+CK_RV Token::InitPIN(u1Array* soPIN,u1Array* userPIN)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      rv = Token::DoPINValidityChecks(userPIN);
+
+      if(rv != CKR_OK){
+         throw CkError(rv);
+      }
+
+      auto_ptr<u1Array> challenge(_mscm->GetChallenge());
+      auto_ptr<u1Array> cryptogram(ComputeCryptogram(challenge.get(), soPIN));
+
+      try{
+
+         this->_mscm->ChangeReferenceData(MODE_UNBLOCK_PIN,CARD_ROLE_USER,cryptogram.get(),userPIN,MAX_USER_PIN_TRIES);
+         this->RegisterPinUpdate();
+
+         // Log in user to update token info
+         this->_mscm->VerifyPin(CARD_ROLE_USER, userPIN);
+
+         if(_initialized)
+            DeserializeTokenInfo();
+         else
+            Initialize();
+
+         // Save User PIN Initialized flag, the other PIN flags are not stored
+         this->_tokenInfo.flags |= CKF_USER_PIN_INITIALIZED;
+         SerializeTokenInfo();
+         this->_mscm->LogOut(CARD_ROLE_USER);
+
+         // Reset some User PIN flags
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+
+      }
+      catch(Marshaller::RemotingException&){
+         rv = CKR_TOKEN_NOT_PRESENT;
+      }
+      catch(Marshaller::UnauthorizedAccessException&){
+
+         // incorrect pin
+         s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+         // blocked
+         if(triesRemaining == 0){
+            // update tokeninfo flahs
+            this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+         }else if(triesRemaining == 1){
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+            this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+         }else if(triesRemaining < MAX_SO_PIN_TRIES){
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+            this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+            this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+         }
+
+         rv = CKR_PIN_INCORRECT;
+
+      }
+      catch(std::runtime_error&){
+         rv = CKR_DEVICE_ERROR;
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::SetPIN(u1Array* oldPIN,u1Array* newPIN)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+
+      bool fCheckCharacters = (_roleLogged != CKU_SO);
+      rv = Token::DoPINValidityChecks(newPIN, fCheckCharacters);
+
+      if(rv != CKR_OK){
+         throw CkError(rv);
+      }
+
+      CK_BYTE  role       = 0;
+      s4 maxTries         = 0;
+
+      auto_ptr<u1Array> oldPINTemp;
+      auto_ptr<u1Array> newPINTemp;
+
+      if(this->_roleLogged == CKU_SO){
+
+         role = CARD_ROLE_ADMIN;
+         maxTries = MAX_SO_PIN_TRIES;
+
+         u1Array* challenge = this->_mscm->GetChallenge();
+
+         oldPINTemp = auto_ptr<u1Array>(this->ComputeCryptogram(challenge,oldPIN));
+
+         delete challenge;
+
+         // new PIN has to be 24 bytes
+         // if not we just pad rest of bytes as zeros
+         newPINTemp = auto_ptr<u1Array>(new u1Array(24));
+         memset(newPINTemp->GetBuffer(),0,24);
+         memcpy(newPINTemp->GetBuffer(),newPIN->GetBuffer(),newPIN->GetLength());
+
+      }else{
+
+         role = CARD_ROLE_USER;
+         maxTries = MAX_USER_PIN_TRIES;
+
+         oldPINTemp = auto_ptr<u1Array>(new u1Array(oldPIN->GetLength()));
+         oldPINTemp->SetBuffer(oldPIN->GetBuffer());
+
+         newPINTemp = auto_ptr<u1Array>(new u1Array(newPIN->GetLength()));
+         newPINTemp->SetBuffer(newPIN->GetBuffer());
+      }
+
+      try{
+         this->_mscm->ChangeReferenceData(MODE_CHANGE_PIN,role,oldPINTemp.get(),newPINTemp.get(),maxTries);
+         this->RegisterPinUpdate();
+      }
+      catch(Marshaller::RemotingException&){
+         rv = CKR_TOKEN_NOT_PRESENT;
+      }
+      catch(Marshaller::UnauthorizedAccessException&){
+
+         // incorrect pin
+         s4 triesRemaining = this->_mscm->GetTriesRemaining(role);
+
+         if(role == CARD_ROLE_ADMIN){
+
+            // blocked
+            if(triesRemaining == 0){
+               // update tokeninfo flahs
+               this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+            }else if(triesRemaining == 1){
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+               this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+            }else if(triesRemaining < MAX_SO_PIN_TRIES){
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+               this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+            }
+
+         }else{
+
+            // blocked
+            if(triesRemaining == 0){
+               // update tokeninfo flahs
+               this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+            }else if(triesRemaining == 1){
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+               this->_tokenInfo.flags |= CKF_USER_PIN_FINAL_TRY;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+            }else if(triesRemaining < MAX_USER_PIN_TRIES){
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+               this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+               this->_tokenInfo.flags |= CKF_USER_PIN_COUNT_LOW;
+            }
+         }
+
+         rv = triesRemaining ? CKR_PIN_INCORRECT : CKR_PIN_LOCKED;
+
+
+      }
+      catch(std::runtime_error&){
+         rv = CKR_DEVICE_ERROR;
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::InitToken(u1Array* pin,u1Array* label)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+
+      // Check that label does not contain null-characters
+      PKCS11_ASSERT(label->GetLength() == 32);
+      for(u4 i = 0; i<label->GetLength(); ++i)
+      {
+         if(!label->ReadU1At(i))
+            throw CkError(CKR_ARGUMENTS_BAD);
+      }
+
+      // first check if pin is locked or not
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+      // blocked
+      if(triesRemaining == 0){
+         throw CkError(CKR_PIN_LOCKED);
+      }
+
+      // Change User PIN to random
+      R_RANDOM_STRUCT & randomStruc = Util::RandomStruct();
+      u1Array randomPin(MAX_PIN_LEN);
+      R_GenerateBytes(randomPin.GetBuffer(), MAX_PIN_LEN, &randomStruc);
+      // Make a number to comply with rules in DoPINValidityChecks
+      for(u4 i = 0; i < MAX_PIN_LEN; ++i)
+         randomPin.SetU1At(i, '0' + randomPin.ReadU1At(i)%10);   // Not 100% random any more....
+
+      rv = InitPIN(pin, &randomPin);
+      if(rv != CKR_OK)
+         throw CkError(rv);
+
+      // actual authentication
+      rv = this->AuthenticateAdmin(pin);
+      if(rv != CKR_OK){
+         throw CkError(rv);
+      }
+
+      // this seems strange the reason,
+      // I am doing this is to use DeleteObject
+      // method which expects the user to be logged
+      // in
+      this->_roleLogged = CKU_USER;
+
+      // TODO: InitToken should not care to do the regular token initialization
+      // in particular if it needs to clean up a token that will not load.....
+      // It should delete files directly as well as containers.
+      BeginTransaction();
+      try
+      {
+         if(!_initialized)
+            Initialize();
+
+         //Log::log("Deleting all token objects....");
+
+         // destroy all the token objects
+         for(size_t t=0; t<_objects.size(); t++){
+            if(this->_objects[t] != NULL_PTR){
+               // what if DeleteObject has failed for any reason ?
+               this->DeleteObject(CO_TOKEN_OBJECT | static_cast<CK_OBJECT_HANDLE>(t+1));
+            }
+         }
+
+         // Update the token's label and flags attribute.
+         // Re-fetch first to be sure _tokenInfo is valid
+         DeserializeTokenInfo();
+         _tokenInfo.flags |= CKF_TOKEN_INITIALIZED;
+         _tokenInfo.flags &= ~CKF_USER_PIN_INITIALIZED;
+         memcpy(_tokenInfo.label, label->GetBuffer(), 32);
+         SerializeTokenInfo();
+
+         _mscm->LogOut(CARD_ROLE_ADMIN);
+         _roleLogged = CKU_NONE;
+      }
+      catch(...)
+      {
+         _roleLogged = CKU_NONE;
+         try { _mscm->LogOut(CARD_ROLE_ADMIN); } catch(...) {}
+         EndTransaction();
+         throw;
+      }
+      EndTransaction();
+
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+bool Token::IsInitialized()
+{
+   bool result = false;
+
+   // the way we determine that token is not initialized
+   // is to check for the existence of p11 directory in the root
+   // since GetFiles() does not return directory I have base my judgement
+   // on the IOException or DirectoryNotFoundException for tinfo
+   std::string tinfo("p11\\tinfo");
+
+   try{
+      //ManageGC( );
+      _cardCache->ReadFile(tinfo);
+      result = true;
+   }
+   catch(...){}
+
+   return result;
+
+}
+
+void Token::CreateDirIfNotPresent(std::string* /*parent*/,std::string* dir,u1Array* acls)
+{
+
+   try{
+      this->_mscm->CreateDirectory(dir,acls);
+   }
+   catch(std::runtime_error&){
+      // ignore the exception as the directory may already be present
+      // TBD : May it more robust
+   }
+}
+
+void Token::Initialize()
+{
+   PKCS11_ASSERT(!_initialized);
+
+   std::string root("");
+   std::string p11("p11");
+
+   u1Array acls(3);
+   acls.GetBuffer()[0] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+   acls.GetBuffer()[1] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+   acls.GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+   // create p11 directory
+   this->CreateDirIfNotPresent(&root,&p11,&acls);
+
+   // create token info
+   std::string tinfo("p11\\tinfo");
+   _cardCache->ClearFileList("p11");
+   this->_mscm->CreateFile(&tinfo,&acls,0);
+
+   // Serialize default token Info
+   this->SerializeTokenInfo();
+
+   this->RegisterFileUpdate();
+
+   this->_initialized = true;
+
+}
+
+void Token::ReadAndPopulateObjects(vector<StorageObject*> & objects, vector<string> & toDelete,
+                                   string const & prefix, map<int, ContainerInfo> & contMap)
+{
+
+   CK_ULONG cls;
+
+   vector<string> files(_cardCache->FileList("p11"));
+
+   for(u4 i=0;i<files.size();i++)
+   {
+      std::string aFile(files[i]);
+
+      if(aFile.find(prefix) != 0) // Must start with <prefix>
+         continue;
+
+      std::string filePath("p11\\");
+
+      filePath.append(aFile);
+      const u1Array & fileData = _cardCache->ReadFile(filePath);
+
+      if (aFile.substr(prefix.size(), 3) == "dat")
+      {
+         cls = CKO_DATA;
+      }
+      //else if (aFile.substr(prefix.size(), 3) == "cer")
+      //{
+      //    cls = CKO_CERTIFICATE;
+      //}
+      else if (aFile.substr(prefix.size(), 3) == "kxc")
+      {
+         cls = CKO_CERTIFICATE;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "ksc")
+      {
+         cls = CKO_CERTIFICATE;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "puk")
+      {
+         cls = CKO_PUBLIC_KEY;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "prk")
+      {
+         cls = CKO_PRIVATE_KEY;
+      }
+      else if (aFile.substr(prefix.size(), 3) == "sec")
+      {
+         cls = CKO_SECRET_KEY;
+      }
+      else
+      {
+         cls = CKO_VENDOR_DEFINED;
+      }
+
+      StorageObject* object = NULL_PTR;
+
+      switch(cls){
+
+            case CKO_DATA:
+               object = new DataObject();
+               break;
+
+            case CKO_PUBLIC_KEY:
+               object = new RSAPublicKeyObject();
+               break;
+
+            case CKO_PRIVATE_KEY:
+               object = new RSAPrivateKeyObject();
+               break;
+
+            case CKO_SECRET_KEY:
+               object = new SecretKeyObject();
+               break;
+
+            case CKO_CERTIFICATE:
+               object = new X509PubKeyCertObject();
+               ((X509PubKeyCertObject*)object)->_certName = aFile.substr(prefix.size(), aFile.size()-prefix.size());
+               break;
+
+            default:
+               continue;
+      }
+
+      vector<u1> from;
+      for(u4 u=0;u<fileData.GetLength();u++){
+         from.push_back(fileData.GetBuffer()[u]);
+      }
+
+      CK_ULONG idx = 0;
+
+      object->Deserialize(from,&idx);
+
+      // put the fileName for the object
+      // as it is not deserialized
+      object->_fileName = filePath;
+
+      bool fAddObject = true;
+
+      // For CKO_PRIVATE_KEY and CKO_CERTIFICATE, check that the objects
+      // actually exists in the container. If they don't, flag that the
+      // file shall be deleted.
+      if(cls == CKO_PRIVATE_KEY)
+      {
+         PrivateKeyObject * privKey = static_cast<PrivateKeyObject*>(object);
+         map<int, ContainerInfo>::iterator icont = contMap.find(privKey->_ctrIndex);
+         if(icont != contMap.end() && icont->second._cmapEntry)
+         {
+            KeyPair & keyPair = (privKey->_keySpec == KEYSPEC_KEYEXCHANGE) ?
+               icont->second._exchKP : icont->second._signKP;
+            if(keyPair._checkValue == privKey->_checkValue)
+            {
+               // Object exist in the container. Flag that there exists a P11 private
+               // key for this key pair so that it will not be instantiated twice.
+               keyPair._fP11PrivKeyExists = true;
+            }
+            else
+               fAddObject = false;
+         }
+         else
+            fAddObject = false;
+      }
+      else if(cls == CKO_CERTIFICATE)
+      {
+         X509PubKeyCertObject * cert = static_cast<X509PubKeyCertObject*>(object);
+         map<int, ContainerInfo>::iterator icont = contMap.find(cert->_ctrIndex);
+         if(icont != contMap.end() && icont->second._cmapEntry)
+         {
+            u1Array certValue;
+            KeyPair & keyPair = (cert->_keySpec == KEYSPEC_KEYEXCHANGE) ?
+               icont->second._exchKP : icont->second._signKP;
+
+            certValue = keyPair._cert;
+            if(certValue.GetLength())
+            {
+               u8 checkValue = 0;
+               try
+               {
+                  X509Cert x509cert(certValue.GetBuffer(), certValue.GetLength());
+                  BEROctet::Blob modulus(x509cert.Modulus());
+                  checkValue = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+                  if(cert->_checkValue == checkValue)
+                  {
+                     // Correct certificate! Assign the value and register it.
+                     // Flag that there exists a P11 certificate object for this
+                     // key pair so that it will not be instantiated twice.
+                     cert->_value = new u1Array();
+                     *cert->_value = certValue;
+                     keyPair._fP11CertExists = true;
+                  }
+                  else
+                     fAddObject = false;
+               }
+               catch(...)
+               {
+                  // Not valid X509 certificate, ignore it.
+                  fAddObject = false;
+               }
+            }
+            else
+               fAddObject = false;
+         }
+         else
+            fAddObject = false;
+      }
+
+      if(fAddObject)
+         objects.push_back(object);
+      else
+      {
+         delete object;
+         toDelete.push_back(filePath);
+      }
+   }
+}
+
+void Token::SynchronizePublicObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchrnoizing Public Objects...");
+
+   if(!_initialized){
+      //Log::log("Token not initialized, hence no objects.");
+      return;
+   }
+
+   ReadAndPopulateObjects(objects, toDelete, "pub", contMap);
+   //ManageGC();
+}
+
+void Token::SynchronizePrivateObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchronizing Private Objects...");
+
+   if(!_initialized){
+      //Log::log("Token not initialized, hence no objects.");
+      return;
+   }
+
+   ReadAndPopulateObjects(objects, toDelete, "pri", contMap);
+   //ManageGC();
+}
+
+void Token::BuildContainerInfoMap(map<int, ContainerInfo> & contMap)
+{
+   contMap.clear();
+
+   // Step 1: Populate map from existence of files named mscp\kxc## and mscp\ksc##
+   string mscpDir("mscp");
+   vector<string> mscpFiles(_cardCache->FileList(mscpDir));
+
+   for(u4 ifile = 0; ifile < mscpFiles.size(); ++ifile)
+   {
+      std::string aFile(mscpFiles[ifile]);
+      if(aFile.size() != 5 || aFile[0] != 'k' || aFile[2] != 'c')
+         continue;
+
+      u1 keySpec;
+      if(aFile[1] == 'x')
+         keySpec = KEYSPEC_KEYEXCHANGE;
+      else if(aFile[1] == 's')
+         keySpec = KEYSPEC_SIGNATURE;
+      else
+         continue;
+
+      int ctrIndex;
+      if(sscanf(aFile.substr(3, 2).c_str(), "%d", &ctrIndex) != 1)
+         continue;
+      if(ctrIndex <0)
+         continue;
+
+      // Read certificate file
+
+      std::string aFilePath = mscpDir + "\\" + aFile;
+
+      auto_ptr<u1Array> value(ReadCertificateFile(aFilePath));
+
+      if(keySpec == KEYSPEC_SIGNATURE)
+      {
+         contMap[ctrIndex]._signKP._cert = *value;
+         contMap[ctrIndex]._signKP._certName = aFile;
+      }
+      else
+      {
+         contMap[ctrIndex]._exchKP._cert = *value;
+         contMap[ctrIndex]._exchKP._certName = aFile;
+      }
+   }
+
+   // Step 2: Update map from valid cmapfile entries
+
+   std::string nameCMapFile("mscp\\cmapfile");
+   const u1Array & fileData = _cardCache->ReadFile(nameCMapFile);
+   u4 contentLen = fileData.GetLength();
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   vector<ContainerInfo> vContInfo;
+   for(int ctrIndex = 0; ctrIndex < entries; ++ctrIndex)
+   {
+      if(!(CMapFileGetFlag(fileData, ctrIndex) & 0x01))
+         continue;       // Skip not valid containers.
+
+      // Valid cmapfile entry for this ctrIndex
+      contMap[ctrIndex]._cmapEntry = true;
+
+      if(CMapFileGetSignSize(fileData, ctrIndex) || CMapFileGetExchSize(fileData, ctrIndex))
+      {
+         // Exchange
+         const CardCache::Container & cont = _cardCache->ReadContainer(ctrIndex);
+         u4 modulusLength = cont.exchModulus.GetLength();
+         if(modulusLength && CMapFileGetExchSize(fileData, ctrIndex) == modulusLength*8)
+         {
+            contMap[ctrIndex]._exchKP._modulus = cont.exchModulus;
+            contMap[ctrIndex]._exchKP._publicExponent = cont.exchPublicExponent;
+            contMap[ctrIndex]._exchKP._checkValue = Util::MakeCheckValue(cont.exchModulus.GetBuffer(), modulusLength);
+         }
+
+         // Signature
+         modulusLength = cont.signModulus.GetLength();
+         if(modulusLength && CMapFileGetSignSize(fileData, ctrIndex) == modulusLength*8)
+         {
+            contMap[ctrIndex]._signKP._modulus = cont.signModulus;
+            contMap[ctrIndex]._signKP._publicExponent = cont.signPublicExponent;
+            contMap[ctrIndex]._signKP._checkValue = Util::MakeCheckValue(cont.signModulus.GetBuffer(), modulusLength);
+         }
+      }
+   }
+}
+
+void Token::SynchronizeCertificates(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchronizing  Certificates...");
+
+   // Look for certificates in mscp that are not represented by P11 objects
+   for(map<int, ContainerInfo>::const_iterator icont = contMap.begin(); icont != contMap.end(); ++icont)
+   {
+      if(!icont->second._cmapEntry)
+         continue;   // Not corresponding to a valid cmapfile entry, ignore it.
+
+      u1 ctrIndex = static_cast<u1>(icont->first);
+
+      for(int ikeySpec = 0; ikeySpec < 2; ++ikeySpec)
+      {
+         u1 keySpec = (ikeySpec == 0) ? KEYSPEC_KEYEXCHANGE : KEYSPEC_SIGNATURE;
+         const KeyPair & keyPair = (ikeySpec == 0) ? icont->second._exchKP : icont->second._signKP;
+
+         // Certificates that have already been represented by object
+         // stored under p11 directory shall not be instantiated again.
+         if(keyPair._fP11CertExists)
+            continue;
+
+         if(keyPair._cert.GetLength())
+         {
+            if(!FindCertificate(objects, ctrIndex, keySpec))
+            {
+               //Log::log("Handling enrollement done from CSP...");
+
+               u8 checkValue = 0;
+               string strLabel;
+               BEROctet::Blob blId;
+               try
+               {
+                  CAttributedCertificate attrCert(keyPair._cert.GetBuffer(), keyPair._cert.GetLength());
+
+                  strLabel = attrCert.DerivedName();
+                  blId = attrCert.DerivedId();
+
+                  BEROctet::Blob modulus(attrCert.Modulus());
+                  checkValue = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+               }
+               catch(...)
+               {
+                  // Not valid X509 certificate, ignore it
+                  continue;
+               }
+
+               X509PubKeyCertObject* cert = new X509PubKeyCertObject();
+               cert->_value = new u1Array();
+               *cert->_value = keyPair._cert;
+               cert->_checkValue = checkValue;
+               cert->_certName = keyPair._certName;
+               cert->_keySpec = keySpec;
+               cert->_ctrIndex = ctrIndex;
+
+               cert->_tokenObject = CK_TRUE;
+               cert->_private = CK_FALSE;
+
+               cert->_label = new u1Array(static_cast<s4>(strLabel.size()));
+               cert->_label->SetBuffer(reinterpret_cast<const u1*>(strLabel.c_str()));
+
+               // If there is already a corresponding private key, assign
+               // the same id attribute, otherwise use the one derived from cert.
+               RSAPrivateKeyObject * priv = static_cast<RSAPrivateKeyObject*>(FindPrivateKey(objects, ctrIndex, keySpec));
+               if(priv && priv->_id->GetLength())
+               {
+                  cert->_id = new u1Array();
+                  *cert->_id = *priv->_id;
+               }
+               else
+               {
+                  cert->_id = new u1Array(static_cast<s4>(blId.size()));
+                  cert->_id->SetBuffer(reinterpret_cast<const u1*>(blId.c_str()));
+               }
+
+               // prepare object attributes from the parsed certificate
+               this->PrepareCertAttributesFromRawData(cert);
+
+               // Register this object
+               objects.push_back(cert);
+            }
+         }
+      }
+   }
+}
+
+void Token::SynchronizePrivateKeys(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap)
+{
+   //Log::log("Synchronizing  Private Keys...");
+
+   // Look for private keys in cmapfile that are not represented by P11 objects
+   for(map<int, ContainerInfo>::const_iterator icont = contMap.begin(); icont != contMap.end(); ++icont)
+   {
+      if(!icont->second._cmapEntry)
+         continue;   // Not corresponding to a valid cmapfile entry, ignore it.
+
+      u1 ctrIndex = static_cast<u1>(icont->first);
+
+      for(int ikeySpec = 0; ikeySpec < 2; ++ikeySpec)
+      {
+         u1 keySpec = (ikeySpec == 0) ? KEYSPEC_KEYEXCHANGE : KEYSPEC_SIGNATURE;
+         const KeyPair & keyPair = (ikeySpec == 0) ? icont->second._exchKP :  icont->second._signKP;
+
+         // Private keys that have already been represented by object
+         // stored under p11 directory shall not be instantiated again.
+         if(keyPair._fP11PrivKeyExists)
+            continue;
+
+         if(keyPair._checkValue)
+         {
+            if(!FindPrivateKey(objects, ctrIndex, keySpec))
+            {
+               //Log::log("Handling enrollement done from CSP...");
+
+               RSAPrivateKeyObject* priv = new RSAPrivateKeyObject();
+
+               // If there is a corresponding certificate, use its label, id and subject attribute
+
+               // TODO: Should check type before cast, however since there
+               // are no other certificate types than X509 here, this is safe
+               X509PubKeyCertObject * cert = static_cast<X509PubKeyCertObject*>(FindCertificate(objects, ctrIndex, keySpec));
+               if(cert)
+               {
+                  // If cert exist, inherit label and id from cert
+                  priv->_label = new u1Array();
+                  *priv->_label = *cert->_label;
+                  priv->_id = new u1Array();
+                  *priv->_id = *cert->_id;
+                  priv->_subject = new u1Array();
+                  *priv->_subject = *cert->_subject;
+               }
+               else
+               {
+                  BEROctet::Blob blId(CAttributedCertificate::DerivedId(keyPair._modulus.GetBuffer(),
+                     keyPair._modulus.GetLength()));
+                  priv->_id = new u1Array(static_cast<s4>(blId.size()));
+                  priv->_id->SetBuffer(blId.c_str());
+               }
+
+               priv->_ctrIndex = ctrIndex;
+               priv->_keySpec  = keySpec;
+               priv->_tokenObject = CK_TRUE;
+               priv->_private = CK_TRUE;
+               priv->_decrypt = CK_TRUE;
+               priv->_unwrap = CK_TRUE;
+               priv->_derive = CK_FALSE;
+               priv->_sign = CK_TRUE;
+               priv->_signRecover = CK_FALSE;
+               priv->_publicExponent = new u1Array();
+               *priv->_publicExponent = keyPair._publicExponent;
+               priv->_modulus = new u1Array();
+               *priv->_modulus = keyPair._modulus;
+               priv->_checkValue = keyPair._checkValue;
+
+               // add this in the token object list
+               objects.push_back(priv);
+            }
+         }
+      }
+   }
+}
+
+void Token::PrepareCertAttributesFromRawData(X509PubKeyCertObject* certObject)
+{
+
+   u1*           pCertValue = NULL;
+   unsigned long dwCertLen = 0;
+   u1Array*      sernbP = NULL;
+   u1Array*      issuerP = NULL;
+   u1Array*      subjectP = NULL;
+
+   pCertValue = certObject->_value->GetBuffer();
+   dwCertLen  = certObject->_value->GetLength();
+
+   // Parse Certifcate to extract SerNB, Issuer & Subject
+   // Create check value from modulus
+
+   try {
+      X509Cert x509cert(pCertValue, dwCertLen);
+
+      BEROctet::Blob blSerNum(x509cert.SerialNumber());
+      BEROctet::Blob blIssuer(x509cert.Issuer());
+      BEROctet::Blob blSubject(x509cert.Subject());
+      BEROctet::Blob modulus(x509cert.Modulus());
+
+      sernbP   = new u1Array(static_cast<s4>(blSerNum.size()));
+      sernbP->SetBuffer(const_cast<u1*>(blSerNum.data()));
+
+      issuerP  = new u1Array(static_cast<s4>(blIssuer.size()));
+      issuerP->SetBuffer(const_cast<u1*>(blIssuer.data()));
+
+      subjectP = new u1Array(static_cast<s4>(blSubject.size()));
+      subjectP->SetBuffer(const_cast<u1*>(blSubject.data()));
+
+      certObject->_serialNumber = sernbP;
+      certObject->_issuer       = issuerP;
+      certObject->_subject      = subjectP;
+   }
+   catch(...) {} // On parse error, these attributes can't be set.
+
+}
+
+
+CK_RV Token::AuthenticateUser(Marshaller::u1Array *pin)
+{
+   CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;
+
+   try
+   {
+      // first check if pin is locked or not
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_USER);
+
+      // blocked
+      if(triesRemaining == 0)
+      {
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+
+         return CKR_PIN_LOCKED;
+      }
+
+      int iCase = howToAuthenticate( pin->GetLength( ) );
+      switch( iCase )
+      {
+      case AUTHENTICATE_REGULAR:
+         Log::log( "Token::AuthenticateUser - Normal login" );
+         this->_mscm->VerifyPin( CARD_ROLE_USER, pin );
+         rv = CKR_OK;
+         break;
+
+      case AUTHENTICATE_PINPAD:
+         Log::log( "Token::AuthenticateUser - PinPad" );
+         rv = verifyPinWithPinPad( );
+         break;
+
+      case AUTHENTICATE_BIO:
+#ifdef WIN32
+         Log::log( "Token::AuthenticateUser - BIO" );
+         rv = verifyPinWithBio( /*pin*/ );
+#else
+      Log::log( "Token::AuthenticateUser - BIO not supported !!" );
+      rv = CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+         break;
+
+      default:
+         Log::log( "Token::AuthenticateUser - Unknown !!" );
+         rv = CKR_FUNCTION_NOT_SUPPORTED;
+         break;
+      }
+   }
+   catch(Marshaller::RemotingException&)
+   {
+      rv = CKR_TOKEN_NOT_PRESENT;
+   }
+   catch(Marshaller::UnauthorizedAccessException&)
+   {
+      rv = CKR_PIN_INCORRECT;
+   }
+   catch(std::runtime_error&)
+   {
+      rv = CKR_DEVICE_ERROR;
+   }
+
+   if( CKR_OK == rv )
+   {
+      this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+      this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+      this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+      this->_roleLogged = CKU_USER;
+   }
+   else
+   {
+      // incorrect pin
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_USER);
+
+      // blocked
+      if(triesRemaining == 0)
+      {
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+      }
+      else if(triesRemaining == 1)
+      {
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags |= CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+      }
+      else if(triesRemaining < MAX_USER_PIN_TRIES)
+      {
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+         this->_tokenInfo.flags |= CKF_USER_PIN_COUNT_LOW;
+      }
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+BYTE Token::howToAuthenticate( BYTE bPinLen )
+{
+   BYTE bRet = AUTHENTICATE_REGULAR;
+
+   // Get the card mode (1=PIN, 2=FingerPrint, 3=PIN or FP, 4=PIN and FP)
+   // The default mode is PIN
+   BYTE bCardMode = UVM_PIN_ONLY;
+   BYTE bTypePIN = PIN_TYPE_REGULAR;
+   getCardConfiguration( bCardMode, bTypePIN );
+   Log::log( "Token::AuthenticateUser - PIN type <%ld> (0 = regular ; 1 = external)", bTypePIN );
+   Log::log( "Token::AuthenticateUser - Card mode <%ld> (1 = pin only ; 2 = fp only ; 3 = fp or pin ; 4 = fp and pin)", bCardMode );
+   Log::log( "Token::AuthenticateUser - PIN len <%ld>", bPinLen );
+
+   if( PIN_TYPE_EXTERNAL == bTypePIN )
+   {
+      if( UVM_PIN_ONLY == bCardMode )
+      {
+         if( true == m_isPinPadSupported )
+         {
+            if( 0 == bPinLen )
+            {
+               Log::log( "Token::AuthenticateUser - External PIN && UVM1 && PINpad support && null len -> PIN pad" );
+               bRet = AUTHENTICATE_PINPAD;
+            }
+            else
+            {
+               Log::log( "Token::AuthenticateUser - External PIN && UVM1 && PINpad support && valid len -> PIN normal" );
+               bRet = AUTHENTICATE_REGULAR;
+            }
+         }
+         else
+         {
+            Log::log( "Token::AuthenticateUser - External PIN && UVM1 && NO PINpad support -> ERROR !!!" );
+            bRet = AUTHENTICATE_ERROR;
+         }
+      }
+      else
+      {
+         Log::log( "Token::AuthenticateUser - External PIN && (UVM2 || UVM3 || UVM4) -> Bio" );
+         bRet = AUTHENTICATE_BIO;
+      }
+   }
+   else
+   {
+      if( ( 0 != bPinLen ) && ( ( UVM_PIN_ONLY == bCardMode ) || ( UVM_PIN_OR_FP == bCardMode ) ) )
+      {
+         Log::log( "Token::AuthenticateUser - Regular PIN && (UVM1 || UVM3)  && valid len -> PIN normal" );
+         bRet = AUTHENTICATE_REGULAR;
+      }
+      else
+      {
+         Log::log( "Token::AuthenticateUser - Regular PIN && (UVM2 || UVM4)  && NO valid len -> ERROR !!!" );
+         bRet = AUTHENTICATE_ERROR;
+      }
+   }
+
+   return bRet;
+}
+
+
+CK_RV Token::AuthenticateAdmin(Marshaller::u1Array *pin)
+{
+   //Log::log("Logging as Admin...");
+
+   CK_RV rv = CKR_OK;
+
+   u1Array* challenge = NULL_PTR;
+   u1Array* response = NULL_PTR;
+
+   try{
+
+      // first check if pin is locked or not
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+      // blocked
+      if(triesRemaining == 0){
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+
+         return CKR_PIN_LOCKED;
+      }
+
+      challenge = this->_mscm->GetChallenge();
+
+      response = this->ComputeCryptogram(challenge,pin);
+
+      this->_mscm->ExternalAuthenticate(response);
+
+      this->_roleLogged = CKU_SO;
+   }
+   catch(Marshaller::RemotingException&){
+      rv = CKR_TOKEN_NOT_PRESENT;
+   }
+   catch(Marshaller::UnauthorizedAccessException&){
+
+      // incorrect pin
+      s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+      // blocked
+      if(triesRemaining == 0){
+         // update tokeninfo flahs
+         this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+      }else if(triesRemaining == 1){
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+      }else if(triesRemaining < MAX_SO_PIN_TRIES){
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+         this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+         this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+      }
+
+      return CKR_PIN_INCORRECT;
+
+   }
+   catch(std::runtime_error&)
+   {
+      rv = CKR_DEVICE_ERROR;
+   }
+
+   if(challenge != NULL_PTR)
+      delete challenge;
+
+   if(response != NULL_PTR)
+      delete response;
+
+   return rv;
+}
+
+CK_RV Token::Logout()
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+
+      if(this->_roleLogged == CKU_NONE)
+      {
+         throw CkError(CKR_USER_NOT_LOGGED_IN);
+      }
+
+      u1 role = (this->_roleLogged == CKU_USER) ? CARD_ROLE_USER : CARD_ROLE_ADMIN;
+
+      try
+      {
+         // For the user
+         if( CARD_ROLE_USER == role )
+         {
+            // We log out if the SSO mode is not activated
+            if( false == isSSO( ) )
+            {
+               this->_mscm->LogOut( role );
+            }
+         }
+         // For the admin
+         else
+         {
+            // We always log out
+            this->_mscm->LogOut( role );
+         }
+
+         this->_roleLogged = CKU_NONE;
+      }
+      catch(Marshaller::RemotingException&)
+      {
+         rv = CKR_TOKEN_NOT_PRESENT;
+      }
+      catch(std::runtime_error&)
+      {
+         rv = CKR_DEVICE_ERROR;
+      }
+
+   }
+   TOKEN_CATCH(rv)
+
+      return rv;
+}
+
+CK_RV Token::Login(CK_ULONG userType,u1Array* pin)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      if(userType == CKU_USER){
+         if((this->_tokenInfo.flags & CKF_USER_PIN_INITIALIZED) != CKF_USER_PIN_INITIALIZED){
+            throw CkError(CKR_USER_PIN_NOT_INITIALIZED);
+         }
+
+         if(this->_roleLogged == CKU_SO){
+            throw CkError(CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+         }else if(this->_roleLogged == CKU_USER){
+            throw CkError(CKR_USER_ALREADY_LOGGED_IN);
+         }
+
+         rv =  AuthenticateUser(pin);
+
+      }else if(userType == CKU_SO){
+
+         if(this->_roleLogged == CKU_SO){
+            throw CkError(CKR_USER_ALREADY_LOGGED_IN);
+         }else if(this->_roleLogged == CKU_USER){
+            throw CkError(CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+         }
+
+         rv = AuthenticateAdmin(pin);
+      }
+      else
+         rv = CKR_USER_TYPE_INVALID;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+
+/* SerializeTokenInfo
+*/
+void Token::SerializeTokenInfo()
+{
+
+   vector<u1> dataToSerialize;
+
+   // Version
+   Util::PushBBoolInVector(&dataToSerialize, _version);
+
+   // label
+   u1Array* label = new u1Array(32);
+   label->SetBuffer(this->_tokenInfo.label);
+   Util::PushByteArrayInVector(&dataToSerialize,label);
+   delete label;
+
+   // manufacturerId
+   u1Array* manuId = new u1Array(32);
+   manuId->SetBuffer(this->_tokenInfo.manufacturerID);
+   Util::PushByteArrayInVector(&dataToSerialize,manuId);
+   delete manuId;
+
+   // model
+   u1Array* model = new u1Array(16);
+   model->SetBuffer(this->_tokenInfo.model);
+   Util::PushByteArrayInVector(&dataToSerialize,model);
+   delete model;
+
+   // serial Number
+   u1Array* serialNumber = new u1Array(16);
+   serialNumber->SetBuffer(this->_tokenInfo.serialNumber);
+   Util::PushByteArrayInVector(&dataToSerialize,serialNumber);
+   delete serialNumber;
+
+   // rest of the tokenInfo struct (flags)
+   CK_FLAGS flags;
+
+   flags = this->_tokenInfo.flags;
+   flags &= ~CKF_PROTECTED_AUTHENTICATION_PATH;
+
+   Util::PushULongInVector(&dataToSerialize, flags);
+
+   std::string tinfo("p11\\tinfo");
+
+   u1Array objData((s4)dataToSerialize.size());
+
+   for(u4 i=0;i<dataToSerialize.size();i++){
+      objData.SetU1At(i,dataToSerialize.at(i));
+   }
+
+   //ManageGC( );
+
+   try
+   {
+      _cardCache->WriteFile(tinfo,objData);
+      RegisterFileUpdate();
+   }
+   catch( CkError x )
+   {
+      CK_RV rv = x.Error( );
+      Log::log( "## Error ## Token::SerializeTokenInfo - WriteFile failed <%ld>\n", rv );
+      throw;
+   }
+}
+
+void Token::DeserializeTokenInfo()
+{
+   std::string tinfo("p11\\tinfo");
+
+   const u1Array & fileData = this->_cardCache->ReadFile(tinfo);
+
+   vector<u1> from;
+   for(u4 u=0;u<fileData.GetLength();u++){
+      from.push_back(fileData.GetBuffer()[u]);
+   }
+
+   CK_ULONG idx = 0;
+
+   // Format version. Shall be 0 for this version
+   _version = Util::ReadBBoolFromVector(from,&idx);
+
+   // label
+   u1Array* label = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.label,label->GetBuffer(),label->GetLength());
+   delete label;
+
+   // manuid
+   u1Array* manuId = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.manufacturerID,manuId->GetBuffer(),manuId->GetLength());
+   delete manuId;
+
+   // model
+   u1Array* model = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.model,model->GetBuffer(),model->GetLength());
+   delete model;
+
+   // serial number
+   u1Array* serialNum = Util::ReadByteArrayFromVector(from,&idx);
+   memcpy(this->_tokenInfo.serialNumber,serialNum->GetBuffer(),serialNum->GetLength());
+   delete serialNum;
+
+   // Check MSCM's serial number. If this is larger than 8 bytes, do not
+   // use stored value since serial number may already have been truncated
+   // if the card was P11 enabled prior to this fix in revision 548361.
+   auto_ptr<u1Array> serialNumber(_mscm->get_SerialNumber());
+   if(serialNumber->GetLength() > 8)
+   {
+      CMD5 md5;
+      CK_BYTE hash[16];
+      md5.HashCore(serialNumber->GetBuffer(), 0, serialNumber->GetLength());
+      md5.HashFinal(hash);
+      Util::ConvAscii(hash, 8, _tokenInfo.serialNumber);
+   }
+
+   // flags
+   CK_FLAGS flags;
+
+   flags = this->_tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH;
+
+   this->_tokenInfo.flags = Util::ReadULongFromVector(from,&idx);
+
+   this->_tokenInfo.flags |= flags;
+}
+
+void Token::PopulateDefaultTokenInfo()
+{
+   CK_ULONG idx;
+
+   // initialize the token information
+
+   this->_version = 0;
+
+   for(idx=0;idx<32;idx++){
+      this->_tokenInfo.label[idx] = ' ';
+   }
+
+   this->_tokenInfo.label[0] = 'C';
+   this->_tokenInfo.label[1] = 'F';
+   this->_tokenInfo.label[2] = '.';
+   this->_tokenInfo.label[3] = 'N';
+   this->_tokenInfo.label[4] = 'E';
+   this->_tokenInfo.label[5] = 'T';
+   this->_tokenInfo.label[6] = ' ';
+   this->_tokenInfo.label[7] = 'P';
+   this->_tokenInfo.label[8] = '1';
+   this->_tokenInfo.label[9] = '1';
+
+   this->_tokenInfo.manufacturerID[0] = 'G';
+   this->_tokenInfo.manufacturerID[1] = 'e';
+   this->_tokenInfo.manufacturerID[2] = 'm';
+   this->_tokenInfo.manufacturerID[3] = 'a';
+   this->_tokenInfo.manufacturerID[4] = 'l';
+   this->_tokenInfo.manufacturerID[5] = 't';
+   this->_tokenInfo.manufacturerID[6] = 'o';
+
+   for(idx=7;idx<32;idx++){
+      this->_tokenInfo.manufacturerID[idx] = ' ';
+   }
+
+   this->_tokenInfo.model[0] = '.';
+   this->_tokenInfo.model[1] = 'N';
+   this->_tokenInfo.model[2] = 'E';
+   this->_tokenInfo.model[3] = 'T';
+   this->_tokenInfo.model[4] = ' ';
+   this->_tokenInfo.model[5] = 'C';
+   this->_tokenInfo.model[6] = 'a';
+   this->_tokenInfo.model[7] = 'r';
+   this->_tokenInfo.model[8] = 'd';
+
+   for(idx=9;idx<16;idx++){
+      this->_tokenInfo.model[idx] = ' ';
+   }
+
+   for(idx=0;idx<16;idx++){
+      this->_tokenInfo.serialNumber[idx] = ' ';
+   }
+
+   // If serial number length is too big to fit in 16 (hex) digit field,
+   // then use the 8 first bytes of MD5 hash of the original serial number.
+   auto_ptr<u1Array> serialNumber(_mscm->get_SerialNumber());
+   if(serialNumber->GetLength() > 8)
+   {
+      CMD5 md5;
+      CK_BYTE hash[16];
+      md5.HashCore(serialNumber->GetBuffer(), 0, serialNumber->GetLength());
+      md5.HashFinal(hash);
+      Util::ConvAscii(hash, 8, _tokenInfo.serialNumber);
+   }
+   else
+      Util::ConvAscii(serialNumber->GetBuffer(),serialNumber->GetLength(),this->_tokenInfo.serialNumber);
+
+}
+
+CK_RV Token::GenerateRandom(CK_BYTE_PTR randomData,CK_ULONG len)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      // usng the challenge as the random data
+      u1Array* random = NULL_PTR;
+
+      random = this->_mscm->GetChallenge();
+
+      // now requested length can be more or less than the
+      // 8 bytes which challenge generates.
+      CK_ULONG minLen = len < 8 ? len : 8;
+      memcpy(randomData,random->GetBuffer(),minLen);
+
+      // lets put soft ramdom as the rest of the bytes
+      unsigned int uSeed;
+
+      memcpy((BYTE *)&uSeed, random->GetBuffer(), sizeof(unsigned int));
+      srand(uSeed);
+
+      if(len > 8)
+      {
+         for(u4 i=8;i<len;i++)
+         {
+            randomData[i] = (BYTE)(rand() % RAND_MAX);
+         }
+      }
+
+      delete random;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_ULONG Token::FindObjects(Session* session,CK_OBJECT_HANDLE_PTR phObject,
+                            CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount)
+{
+   CK_RV rv = CKR_OK;
+   CK_ULONG idx = 0;
+   TOKEN_TRY
+   {
+
+      for(s4 i=0;(i < static_cast<s4>(_objects.size())) && (idx < ulMaxObjectCount);i++){
+
+         if(this->_objects[i] == NULL_PTR){
+            continue;
+         }
+
+         if(session->_tokenObjectsReturnedInSearch[i+1]){
+            continue;
+         }
+
+         if((this->_objects[i]->_private == CK_TRUE) &&
+            (this->_roleLogged != CKU_USER))
+         {
+            continue;
+         }
+
+         if(session->_searchTempl == NULL_PTR){
+            phObject[idx++] = CO_TOKEN_OBJECT | (i+1);
+            *pulObjectCount = *pulObjectCount + 1;
+            session->_tokenObjectsReturnedInSearch[i+1] = true;
+         }
+         else{
+            CK_BBOOL match = CK_TRUE;
+
+            vector<CK_ATTRIBUTE> attributes = session->_searchTempl->_attributes;
+            for(CK_ULONG a=0;a<attributes.size();a++){
+               if(this->_objects[i]->Compare(attributes.at(a)) == CK_FALSE){
+                  match = CK_FALSE;
+                  break;
+               }
+            }
+
+            if(match == CK_TRUE){
+               phObject[idx++] = CO_TOKEN_OBJECT | (i+1);
+               *pulObjectCount = *pulObjectCount + 1;
+               session->_tokenObjectsReturnedInSearch[i+1] = true;
+            }
+         }
+      }
+   }
+   TOKEN_CATCH(rv)
+      return idx;
+}
+
+
+string Token::FindFreeFileName(StorageObject* object)
+{
+   std::string fileName(object->_private ? "pri" : "pub");
+
+   switch(object->_class){
+        case CKO_DATA:
+           fileName.append("dat");
+           break;
+
+        case CKO_PUBLIC_KEY:
+           fileName.append("puk");
+           break;
+
+        case CKO_PRIVATE_KEY:
+           fileName.append("prk");
+           break;
+
+        case CKO_CERTIFICATE:
+           fileName.append(((X509PubKeyCertObject*)object)->_certName);
+           break;
+
+        case CKO_SECRET_KEY:
+           fileName.append("sec");
+           break;
+
+        default:
+           throw CkError(CKR_FUNCTION_FAILED);
+   }
+
+   if(object->_class != CKO_CERTIFICATE)
+   {
+
+
+      // Find free name
+      map<CK_LONG, bool> occupied;
+
+      if(_initialized)
+      {
+         // get the file names in above dir
+         vector<string> files(_cardCache->FileList("p11"));
+
+         for(u4 i=0;i<files.size();i++)
+         {
+            std::string fn(files[i]);
+            if(fn.find(fileName) == 0)
+            {
+               CK_LONG idx = atoi(fn.substr(fileName.size(), 2).c_str());
+               occupied[idx] = true;
+            }
+         }
+      }
+
+      s4 i = 0;
+      while(occupied.find(i) != occupied.end())
+         i++;
+      fileName.append(Util::MakeIntString(i, 2));
+   }
+
+   return fileName;
+
+}
+
+
+/* WriteObject
+*/
+CK_RV Token::WriteObject( StorageObject* object )
+{
+   //ManageGC( );
+
+   CK_RV rv = CKR_OK;
+
+   std::string fileName( "p11\\" + FindFreeFileName( object ) );
+
+   // This object is stored under p11 directory, assign a unique ID for future identification.
+   object->_uniqueId = Util::MakeUniqueId( );
+
+   vector<u1> to;
+   object->Serialize( &to );
+
+   u1Array objData( (s4)to.size( ) );
+   for( u4 i = 0 ; i < to.size( ) ; i++ )
+   {
+      objData.SetU1At( i, to.at( i ) );
+   }
+
+   u1Array acls( 3 );
+   acls.GetBuffer( )[ 0 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+   acls.GetBuffer( )[ 1 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+
+   if( object->_private )
+   {
+      acls.GetBuffer( )[ 2 ] = 0; // everyone acl
+   }
+   else
+   {
+      // public objects can be written or read by everyone provide the session is correct
+
+      // NOTE: Breaking PKCS#11 Compliance
+      // In the card you can not create public objects unless you are logged in
+      // even for R/W Pulblic session
+
+      acls.GetBuffer( )[ 2 ] = CARD_PERMISSION_READ; // everyone acl
+   }
+
+   if( !_initialized )
+   {
+      Initialize( );
+   }
+
+   _cardCache->ClearFileList( "p11" );
+
+   // No try/catch. It is managed by the calling method.
+   //ManageGC( );
+   this->_mscm->CreateFile( &fileName, &acls, 0 );
+
+   try
+   {
+      //ManageGC( );
+      this->_cardCache->WriteFile( fileName, objData );
+
+      RegisterFileUpdate( );
+      object->_fileName = fileName;
+   }
+   catch( CkError x )
+   {
+      rv = x.Error( );
+      Log::log( "## ERROR ## Token::WriteObject - WriteFile failed <%ld>\n", rv );
+   }
+
+   if( CKR_OK != rv )
+   {
+      try
+      {
+         _mscm->DeleteFile( &fileName );
+      }
+      catch( ... )
+      {
+         Log::log( "## ERROR ## Token::WriteObject - DeleteFile failed\n" );
+      }
+   }
+
+   return rv;
+}
+
+
+CK_RV Token::AddObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject)
+{
+   //ManageGC();
+
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      // from the class field we will be able to determine proper type
+      // and hence the corresponding file
+      //CheckAvailableSpace( );
+
+      CK_RV rv = WriteObject(stobj.get());
+      if(rv == CKR_OK)
+      {
+         *phObject = CO_TOKEN_OBJECT | RegisterStorageObject(stobj.get());
+         stobj.release();
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+
+/* AddPrivateKeyObject
+*/
+CK_RV Token::AddPrivateKeyObject( auto_ptr< StorageObject > &stobj, CK_OBJECT_HANDLE_PTR phObject )
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPrivateKeyObject *object = static_cast< RSAPrivateKeyObject* >( stobj.get( ) );
+      if( !object->_private )
+      {
+         throw CkError( CKR_ATTRIBUTE_VALUE_INVALID );
+      }
+
+      // Public key modulus is mandatory, so unless provided by the template,
+      // see if there is a public key with matching CKA_ID. Otherwise return
+      // CKR_TEMPLATE_INCOMPLETE.
+
+      RSAPublicKeyObject* rsaPub = NULL_PTR;
+      if( !object->_modulus )
+      {
+         // Search for corresponding public key to make criteria that is used here is to match the CKA_ID
+         CK_BBOOL foundPub = CK_FALSE;
+         for( s4 i = 0 ; i < static_cast< s4 >( _objects.size( ) ) ; i++ )
+         {
+            if( this->_objects[ i ] != NULL_PTR )
+            {
+               if( this->_objects[ i ]->_class == CKO_PUBLIC_KEY )
+               {
+                  rsaPub = (RSAPublicKeyObject*)this->_objects[ i ];
+                  foundPub = Util::CompareByteArrays( rsaPub->_id->GetBuffer( ), object->_id->GetBuffer( ), rsaPub->_id->GetLength( ) );
+                  if( foundPub == CK_TRUE )
+                  {
+                     break;
+                  }
+               }
+            }
+         }
+
+         if( !foundPub )
+         {
+            throw CkError(CKR_TEMPLATE_INCOMPLETE); // Sorry, now other choice...
+         }
+      }
+
+      u1Array publExp;
+      u4 modLength = 0;
+      if( object->_modulus != NULL_PTR )
+      {
+         publExp = *object->_publicExponent;
+         modLength = object->_modulus->GetLength( );
+         object->_checkValue = Util::MakeCheckValue( object->_modulus->GetBuffer( ), modLength );
+      }
+      else
+      {
+         PKCS11_ASSERT( rsaPub );
+         publExp = *rsaPub->_exponent;
+         modLength = rsaPub->_modulus->GetLength();
+         object->_checkValue = Util::MakeCheckValue(rsaPub->_modulus->GetBuffer(), modLength);
+      }
+      if(publExp.GetLength() < 1 || publExp.GetLength() > 4)
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      if( (modLength*8 < RSA_KEY_MIN_LENGTH) ||
+         (modLength*8 > RSA_KEY_MAX_LENGTH) )
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      if(publExp.GetLength() < 4)
+      {
+         // Pad with zeros in the front since big endian
+         u1Array exp(4);
+         memset(exp.GetBuffer(), 0, exp.GetLength());
+         size_t i = 4 - publExp.GetLength();
+         memcpy(exp.GetBuffer()+i, publExp.GetBuffer(), publExp.GetLength());
+         publExp = exp;
+      }
+
+      // Look for existing matching certificate
+      // First, read the container map record file
+      std::string  nameCMapFile("mscp\\cmapfile");
+      const u1Array & fileData(_cardCache->ReadFile(nameCMapFile));
+
+      object->_keySpec = KEYSPEC_KEYEXCHANGE;   // Default
+
+      // NOTE: If it finds a matching certificate, the keySpec
+      // will be modified to match that of the certificate.
+      CK_BYTE ctrIdx = GetContainerForPrivateKey(fileData, object->_checkValue, &object->_keySpec);
+      if(ctrIdx > 99)
+      {
+         Log::error( "Token::AddPrivateKeyObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+         throw CkError(CKR_DEVICE_MEMORY);
+      }
+      object->_ctrIndex = ctrIdx;
+
+      auto_ptr<u1Array> keyValue;
+
+      //
+      /*
+      if( object->_modulus->GetLength( ) != object->_d->GetLength( ) )
+      {
+      }
+      if( ( object->_modulus->GetLength( ) / 2 ) != object->_p->GetLength( ) )
+      {
+      }
+      if( ( object->_modulus->GetLength( ) / 2 ) != object->_q->GetLength( ) )
+      {
+      }
+      if( ( object->_modulus->GetLength( ) / 2 ) != object->_dp->GetLength( ) )
+      {
+      }
+      if( ( object->_modulus->GetLength( ) / 2 ) != object->_dq->GetLength( ) )
+      {
+      }
+      */
+      if( ( object->_modulus->GetLength( ) / 2 ) != object->_inverseQ->GetLength( ) )
+      {
+         // Pad with zeros in the front since big endian
+         u1Array val( (s4)( object->_modulus->GetLength( ) / 2 ) );
+         memset( val.GetBuffer( ), 0, val.GetLength( ) );
+         size_t i = val.GetLength( )- object->_inverseQ->GetLength( );
+         memcpy( val.GetBuffer( ) + i, object->_inverseQ->GetBuffer(), object->_inverseQ->GetLength( ) );
+         *(object->_inverseQ) = val;
+         /*
+         // Create a new buffer with the a correct size
+         u1Array val( (s4)( object->_modulus->GetLength( ) / 2 ) );
+         //auto_ptr<u1Array> val = auto_ptr<u1Array>(new u1Array(keyLength));
+
+         // Fill the buffer with zero
+         for( size_t i = 0; i < val.GetLength( ) ; i++ )
+         {
+         val.SetU1At( i, 0 );
+         }
+
+         // Fill the buffer with the old value
+         u4 j = 0;
+         for( size_t i = ( val.GetLength( )- object->_inverseQ->GetLength( ) ) ; i < object->_inverseQ->GetLength( ) ; i++ )
+         {
+         val.SetU1At( i, object->_inverseQ->ReadU1At( j ) );
+         j++;
+         }
+
+         object->_inverseQ = &val;
+         */
+      }
+
+      // compute the total length;
+      s4 keyLength = object->_p->GetLength() +
+         object->_q->GetLength() +
+         object->_inverseQ->GetLength() +
+         object->_dp->GetLength() +
+         object->_dq->GetLength() +
+         object->_d->GetLength();
+
+      if(object->_modulus != NULL_PTR){
+         keyLength += object->_modulus->GetLength();
+         //keyLength += object->_publicExponent->GetLength();
+         keyLength += 4; // public exponent expected by card is on 4 bytes
+      }else{
+         keyLength += rsaPub->_modulus->GetLength();
+         //keyLength += rsaPub->_exponent->GetLength();
+         keyLength += 4; // public exponent expected by card is on 4 bytes
+      }
+
+      s4 offset = 0;
+
+      // Prepare the keyValue
+      keyValue = auto_ptr<u1Array>(new u1Array(keyLength));
+      memset(keyValue->GetBuffer(),0,keyValue->GetLength()); // let's zeroed it
+
+      memcpy(keyValue->GetBuffer(),object->_p->GetBuffer(),object->_p->GetLength());
+
+      offset += object->_p->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_q->GetBuffer(),object->_q->GetLength());
+
+      offset += object->_q->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_inverseQ->GetBuffer(),object->_inverseQ->GetLength());
+
+      offset += object->_inverseQ->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_dp->GetBuffer(),object->_dp->GetLength());
+
+      offset += object->_dp->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_dq->GetBuffer(),object->_dq->GetLength());
+
+      offset += object->_dq->GetLength();
+
+      memcpy((u1*)&keyValue->GetBuffer()[offset],object->_d->GetBuffer(),object->_d->GetLength());
+
+      offset += object->_d->GetLength();
+
+      u4 modulusLen = 0;
+
+      string contName;
+      if(object->_modulus != NULL_PTR){
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],object->_modulus->GetBuffer(),object->_modulus->GetLength());
+
+         offset += object->_modulus->GetLength();
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],publExp.GetBuffer(),publExp.GetLength());
+
+         modulusLen = object->_modulus->GetLength();
+
+         contName = CAttributedCertificate::DerivedUniqueName(object->_modulus->GetBuffer(),
+            object->_modulus->GetLength());
+
+      }else{
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],rsaPub->_modulus->GetBuffer(),rsaPub->_modulus->GetLength());
+
+         offset += rsaPub->_modulus->GetLength();
+
+         memcpy((u1*)&keyValue->GetBuffer()[offset],publExp.GetBuffer(),publExp.GetLength());
+
+         modulusLen = rsaPub->_modulus->GetLength();
+
+         contName = CAttributedCertificate::DerivedUniqueName(rsaPub->_modulus->GetBuffer(),
+            rsaPub->_modulus->GetLength());
+
+      }
+
+      //try
+      //{
+      this->_cardCache->ClearContainer(ctrIdx);  // Invalidate cache
+      //this->_mscm->CreateCAPIContainer(ctrIdx,CK_TRUE,object->_keySpec,(modulusLen*8),keyValue.get());
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ManageGC( );
+            ntry++;
+            this->_mscm->CreateCAPIContainer(ctrIdx,CK_TRUE,object->_keySpec,(modulusLen*8),keyValue.get());
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::AddPrivateKeyObject", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  Log::error( "Token::AddPrivateKeyObject", "Throw Exception CKR_DEVICE_MEMORY" );
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+      this->RegisterContainerUpdate();
+      /*}
+      catch(...)
+      {
+      Log::error( "Token::AddPrivateKeyObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+
+      throw CkError(CKR_DEVICE_MEMORY);
+      }*/
+
+      object->_ctrIndex = ctrIdx;
+
+      rv = this->AddObject(stobj,phObject);
+      if(rv == CKR_OK)
+      {
+         try
+         {
+            auto_ptr<u1Array> newCMap( UpdateCMap( ctrIdx, fileData, (modulusLen*8), object->_keySpec, CK_TRUE, contName ) );
+            this->_cardCache->WriteFile( nameCMapFile, *newCMap );
+            this->RegisterFileUpdate( );
+         }
+         catch( CkError x )
+         {
+            rv = x.Error( );
+            Log::log( "## Error ## Token::AddPrivateKeyObject - WriteFile <%ld>\n", rv );
+
+            try
+            {
+               DeleteObject( *phObject );
+            }
+            catch( ... )
+            {
+            }
+
+            throw CkError( rv );
+         }
+      }
+   }
+   TOKEN_CATCH( rv )
+
+      return rv;
+}
+
+
+/* DeleteCMapRecord
+*/
+void Token::DeleteCMapRecord( CK_BYTE ctrIndex )
+{
+   // Read the container map record file
+   std::string nameCMapFile( "mscp\\cmapfile" );
+
+   try
+   {
+      u1Array fileData( _cardCache->ReadFile( nameCMapFile ) );
+
+      s4 entries = ( fileData.GetLength( ) / SIZE_CONTAINERMAPRECORD );
+      if( ctrIndex >= entries )
+      {
+         return; // Silently ignore if doesn't exist
+      }
+
+      // Nullify the entries at ctrIndex
+      CMapFileClear( fileData, ctrIndex );
+
+      // Set default container
+      SetDefaultContainer( fileData, 0xFF );
+
+      //ManageGC( );
+
+      // Write the updated content back to cmap
+      this->_cardCache->WriteFile( nameCMapFile, fileData );
+      this->RegisterFileUpdate( );
+   }
+   catch( CkError x )
+   {
+      /*CK_RV rv =*/ x.Error( );
+      Log::error( "Token::DeleteCMapRecord", "WriteFile failed" );
+      throw;
+   }
+   /*
+   catch(Marshaller::RemotingException&){
+   // TBD
+   }
+   catch(Marshaller::UnauthorizedAccessException&){
+   // TBD
+   }
+   catch(std::runtime_error&){
+   // TBD
+   }
+   */
+}
+
+void Token::RemoveKeyFromCMapRecord(CK_BYTE ctrIndex, u1 keySpec)
+{
+
+   try{
+      // read the container map record file
+      std::string nameCMapFile("mscp\\cmapfile");
+      u1Array fileData(_cardCache->ReadFile(nameCMapFile));
+
+      s4 entries = (fileData.GetLength() / SIZE_CONTAINERMAPRECORD);
+      if(ctrIndex >= entries)
+      {
+         PKCS11_ASSERT(0);
+         return; // Silently ignore if doesn't exist
+      }
+
+      // Clear the key size corresponding to keyspec
+      if(keySpec == KEYSPEC_KEYEXCHANGE)
+         CMapFileSetExchSize(fileData, ctrIndex, 0);
+      else if(keySpec == KEYSPEC_SIGNATURE)
+         CMapFileSetSignSize(fileData, ctrIndex, 0);
+      else
+         return;  // unknown key spec
+
+      //ManageGC();
+
+      // now write the updated content back to cmap
+      this->_cardCache->WriteFile(nameCMapFile,fileData);
+      this->RegisterFileUpdate();
+
+   }
+   catch( CkError x )
+   {
+      /*CK_RV rv =*/ x.Error( );
+      Log::error( "Token::RemoveKeyFromCMapRecord", "WriteFile failed" );
+   }
+   /*
+   catch(Marshaller::RemotingException&){
+   // TBD
+   }
+   catch(Marshaller::UnauthorizedAccessException&){
+   // TBD
+   }
+   catch(std::runtime_error&){
+   // TBD
+   }
+   */
+}
+
+void Token::SetDefaultContainer(u1Array & contents, CK_BYTE ctrIndex)
+{
+
+   s4 entries = (contents.GetLength() / SIZE_CONTAINERMAPRECORD);
+
+   if(ctrIndex == 0xFF)
+   {
+      for (s4 i=0;i<entries;i++)
+      {
+         if((CMapFileGetFlag(contents, i) & 0x03) == 0x03)
+            return;  // A valid container already default, finished
+      }
+
+      // Find first best suitable. Look for one with keys
+      for (s4 i=0;i<entries;i++)
+      {
+         u1 flags = CMapFileGetFlag(contents, i);
+         if((flags & 0x01) && (CMapFileGetExchSize(contents, i) || CMapFileGetSignSize(contents, i)))
+         {
+            CMapFileSetFlag(contents, i, (flags | 0x02));
+            return;
+         }
+      }
+
+      // If no container with keys, then assign any valid container as default
+      for (s4 i=0;i<entries;i++)
+      {
+         u1 flags = CMapFileGetFlag(contents, i);
+         if(flags & 0x01)
+         {
+            CMapFileSetFlag(contents, i, (flags | 0x02));
+            return;
+         }
+      }
+   }
+   else
+   {
+      // Assign specific container as default
+      PKCS11_ASSERT(ctrIndex < entries);
+      if(ctrIndex >= entries)
+         return;
+      // Remove existing default container
+      for (s4 i=0;i<entries;i++)
+      {
+         u1 flags = CMapFileGetFlag(contents, i);
+         CMapFileSetFlag(contents, i, (flags & ~0x02));
+      }
+      CMapFileSetFlag(contents, ctrIndex, CMapFileGetFlag(contents, ctrIndex) | 0x02);
+   }
+}
+
+CK_RV Token::AddCertificateObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      X509PubKeyCertObject * object = static_cast<X509PubKeyCertObject*>(stobj.get());
+
+      if(object->_private)
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      //CheckAvailableSpace();
+
+      // Make check value and look for possibly existing private key(s)
+
+      BEROctet::Blob modulus;
+      try
+      {
+         X509Cert x509cert(object->_value->GetBuffer(), object->_value->GetLength());
+         modulus =x509cert.Modulus();
+      }
+      catch(...)
+      {
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+      }
+
+      object->_checkValue   = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+      string contName(CAttributedCertificate::DerivedUniqueName(modulus));
+
+      std::string nameCMapFile("mscp\\cmapfile");
+      const u1Array & fileData(_cardCache->ReadFile(nameCMapFile));
+
+      object->_keySpec = KEYSPEC_KEYEXCHANGE;   // Default
+
+      // NOTE: If it finds a matching private key, the keySpec
+      // will be modified to match that of the private key.
+      CK_BYTE ctrIdx = GetContainerForCert(fileData, object->_checkValue, &object->_keySpec);
+      if(ctrIdx > 99)
+      {
+         Log::error( "Token::AddCertificateObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+
+         throw CkError(CKR_DEVICE_MEMORY);
+      }
+      object->_ctrIndex = ctrIdx;
+
+      if(object->_keySpec == KEYSPEC_KEYEXCHANGE)
+         object->_certName = "kxc";
+      else
+         object->_certName = "ksc";
+      object->_certName.append(Util::MakeIntString(ctrIdx, 2));
+
+      string fileName("mscp\\");
+      fileName.append(object->_certName);
+
+      unsigned long ccLen = object->_value->GetLength();
+      autoarray<u1> cc(new u1[ccLen+4]);
+
+      cc[0] = 0x01;
+      cc[1] = 0x00;
+      cc[2] = BITS_0_7(ccLen);
+      cc[3] = BITS_8_15(ccLen);
+
+      // compress the certificate
+      //         compress((u1*)&cc[4],&ccLen,object->_value->GetBuffer(),ccLen);
+      compress2((u1*)&cc[4],&ccLen,object->_value->GetBuffer(),ccLen, 6); // Set level=6, same as Minidriver
+
+      auto_ptr<u1Array> compressedCert(new u1Array((ccLen + 4)));
+      compressedCert->SetBuffer(cc.get());
+
+      auto_ptr<u1Array> acls(new u1Array(3));
+      acls->GetBuffer()[0] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+      acls->GetBuffer()[1] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+      acls->GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+      //ManageGC();
+
+      _cardCache->ClearFileList("mscp");
+      this->_mscm->CreateFile(&fileName,acls.get(),0);
+      try
+      {
+         this->_cardCache->WriteFile(fileName,*compressedCert);
+         this->RegisterFileUpdate();
+      }
+      catch( CkError x )
+      {
+         rv = x.Error( );
+         Log::error( "Token::AddCertificateObject", "WriteFile failed" );
+      }
+
+      if( CKR_OK != rv )
+      {
+         try
+         {
+            _mscm->DeleteFile( &fileName );
+         }
+         catch( ... )
+         {
+         }
+
+         throw CkError( rv );
+      }
+
+      rv = AddObject(stobj ,phObject);
+      if(rv == CKR_OK)
+      {
+         //ManageGC();
+
+         try
+         {
+            auto_ptr<u1Array> newCMap(UpdateCMap(ctrIdx,fileData, contName));
+            _cardCache->WriteFile(nameCMapFile,*newCMap);
+            RegisterFileUpdate();
+         }
+         catch( CkError x )
+         {
+            rv = x.Error( );
+            Log::error( "Token::AddCertificateObject", "WriteFile 2 failed" );
+         }
+
+         if( CKR_OK != rv )
+         {
+            try
+            {
+               _mscm->DeleteFile( &fileName );
+            }
+            catch( ... )
+            {
+            }
+
+            try
+            {
+               DeleteObject( *phObject );
+            }
+            catch( ... )
+            {
+            }
+
+            throw CkError( rv );
+         }
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::DeleteObject( CK_OBJECT_HANDLE hObject )
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      StorageObject * obj = GetObject(hObject);
+
+      // some more checks
+      if((this->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+         throw CkError(CKR_USER_NOT_LOGGED_IN);
+      }
+
+      if(obj->_class == CKO_CERTIFICATE){
+
+         //Log::log("Deleting the certificate.");
+
+         CertificateObject * cert = static_cast<CertificateObject*>(obj);
+         CK_BYTE ctrIdx = cert->_ctrIndex;
+
+         if(ctrIdx != 0xFF){
+
+            // Delete the file under mscp
+
+            string fileName("mscp\\");
+            fileName.append(cert->_certName);
+            _cardCache->ClearFile(fileName);
+            try
+            {
+               _cardCache->ClearFileList("mscp");
+               _mscm->DeleteFile(&fileName);
+               RegisterFileUpdate();
+            }
+            catch(FileNotFoundException &) {}
+
+            // Check if there exist private key(s) or other
+            // certificate (with different key spec) in the container
+            u1 otherKeySpec = (cert->_keySpec == KEYSPEC_KEYEXCHANGE) ? KEYSPEC_SIGNATURE : KEYSPEC_KEYEXCHANGE;
+
+            bool fOtherCertExist = (FindCertificate(_objects, ctrIdx, otherKeySpec) != 0);
+
+            bool fPrivKeysExist = false;
+            if(FindPrivateKey(_objects, ctrIdx, KEYSPEC_KEYEXCHANGE) || FindPrivateKey(_objects, ctrIdx, KEYSPEC_SIGNATURE))
+               fPrivKeysExist = true;
+
+            // If there are no longer any objects associated with this
+            // container, then free this CMap record
+            if(!fOtherCertExist && !fPrivKeysExist)
+            {
+               //Log::log("Deleting container ",ctrIdx);
+               DeleteCMapRecord(ctrIdx);
+            }
+         }
+      }
+      if(obj->_class == CKO_PRIVATE_KEY){
+
+         //Log::log("Deleting the private key.");
+
+         RSAPrivateKeyObject * privKey = static_cast<RSAPrivateKeyObject*>(obj);
+         CK_BYTE ctrIdx = privKey->_ctrIndex;
+
+         if(ctrIdx != 0xFF){
+
+
+            // Check if there exist certificate(s) or other
+            // private key (with different key spec) in the container
+            u1 otherKeySpec = (privKey->_keySpec == KEYSPEC_KEYEXCHANGE) ? KEYSPEC_SIGNATURE : KEYSPEC_KEYEXCHANGE;
+
+            bool fOtherKeyExist = (FindPrivateKey(_objects, ctrIdx, otherKeySpec) != 0);
+
+            bool fCertsExist = false;
+            if(FindCertificate(_objects, ctrIdx, KEYSPEC_KEYEXCHANGE) || FindCertificate(_objects, ctrIdx, KEYSPEC_SIGNATURE))
+               fCertsExist = true;
+
+            if(fOtherKeyExist)
+            {
+               // To not delete the other key, overwrite this one with dummy data
+               // TODO
+               // this->_mscm->CreateCAPIContainer(ctrIdx,.....);
+               RegisterContainerUpdate();
+            }
+            else
+            {
+               _cardCache->ClearContainer(ctrIdx);   // Invalidate cache
+               _mscm->DeleteCAPIContainer(ctrIdx);
+               RegisterContainerUpdate();
+            }
+
+            // Check if the record in cmapfile shall be cleared,
+            // depending on if there are other keys in it.
+            // empty the corresponding record in cmapfile
+
+            if(fOtherKeyExist || fCertsExist)
+            {
+               //Log::log("Removing key from container ",ctrIdx);
+               RemoveKeyFromCMapRecord(ctrIdx, privKey->_keySpec);
+            }
+            else
+            {
+               //Log::log("Deleting container ",ctrIdx);
+               DeleteCMapRecord(ctrIdx);
+            }
+         }
+      }
+
+      // delete the file from card
+      if(!obj->_fileName.empty())
+      {
+         _cardCache->ClearFile(obj->_fileName);
+         try
+         {
+            _cardCache->ClearFileList("p11");
+            this->_mscm->DeleteFile(&obj->_fileName);
+            this->RegisterFileUpdate();
+         }
+         catch(FileNotFoundException &) {}
+      }
+
+      UnregisterStorageObject(obj);
+      delete obj;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::GetAttributeValue(CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount)
+{
+   CK_RV rv  = CKR_OK;
+   CK_RV arv = CKR_OK;
+   TOKEN_TRY
+   {
+
+      //Log::log("Get Attributes of token object..");
+
+      StorageObject * obj = GetObject(hObject);
+
+      if((this->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+         for(u4 i=0;i<ulCount;i++){
+            pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+         }
+         throw CkError(CKR_USER_NOT_LOGGED_IN);
+      }
+
+      for(u4 i=0;i<ulCount;i++){
+         rv = obj->GetAttribute(&pTemplate[i]);
+         if(rv != CKR_OK){
+            arv = rv;
+         }
+      }
+   }
+   TOKEN_CATCH(arv)
+      return arv;
+}
+
+
+CK_RV Token::SetAttributeValue( CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+{
+   CK_RV rv = CKR_OK;
+   CK_RV arv = CKR_OK;
+   TOKEN_TRY
+   {
+      StorageObject* pObj = GetObject( hObject );
+      // ??? pObj == NULL_PTR
+
+      // Check if we have a proper session
+      if( ( this->_roleLogged != CKU_USER ) && ( pObj->_private == CK_TRUE ) )
+      {
+         throw CkError( CKR_USER_NOT_LOGGED_IN );
+      }
+
+      if( pObj->_modifiable == CK_FALSE )
+      {
+         throw CkError(CKR_ATTRIBUTE_READ_ONLY);
+      }
+
+      for( u4 i = 0 ; i < ulCount ; i++ )
+      {
+         rv = pObj->SetAttribute( pTemplate[ i ], CK_FALSE );
+         if( rv != CKR_OK )
+         {
+            arv = rv;
+         }
+      }
+
+      if( arv == CKR_OK )
+      {
+         // If the object is not yet represented by a file under
+         // "p11" directory, this file must be created first.
+
+         bool fCreate = false;
+
+         // The object is represented by a P11 file if and only if
+         // the _uniqueId has been assigned a value.
+         if( pObj->_uniqueId == 0 )
+         {
+            fCreate = true;
+            if(!_initialized)
+               Initialize();
+
+            u1Array acls(3);
+            acls.GetBuffer( )[ 0 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // admin acl
+            acls.GetBuffer( )[ 1 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE;  // usr acl
+
+            if(pObj->_private)
+               acls.GetBuffer()[2] = 0; // everyone acl
+            else
+               acls.GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+            string fileName("p11\\" + FindFreeFileName(pObj));
+            _cardCache->ClearFileList("p11");
+            _mscm->CreateFile(&fileName,&acls,0);
+            RegisterFileUpdate();
+            pObj->_fileName = fileName;
+            pObj->_uniqueId = Util::MakeUniqueId();
+         }
+
+         // marshall this object back to the card
+         vector<u1> to;
+         pObj->Serialize(&to);
+
+         u1Array objData((s4)to.size());
+
+         for(u4 i=0;i<to.size();i++){
+            objData.SetU1At(i,to.at(i));
+         }
+
+         //ManageGC();
+
+         try
+         {
+            this->_cardCache->WriteFile(pObj->_fileName,objData);
+            this->RegisterFileUpdate();
+         }
+         catch( CkError x )
+         {
+            arv = x.Error( );
+            Log::error( "Token::SetAttributeValue", "WriteFile failed" );
+         }
+
+         if( CKR_OK != arv )
+         {
+            /*try
+            {
+            _mscm->DeleteFile(&obj->_fileName);
+            }
+            catch( ... )
+            {
+            }*/
+
+            if(fCreate)   // Restore state of object prior to update attempt.
+            {
+               pObj->_fileName.clear();
+               pObj->_uniqueId = 0;
+            }
+         }
+      }
+   }
+   TOKEN_CATCH(arv)
+      return arv;
+}
+
+
+CK_BYTE Token::GetAvailableContainerIndex(u1Array const & cmapContents)
+{
+   u4  contentLen = cmapContents.GetLength();
+
+   // cmap file does not contain anything
+   // so index is 0
+   if(contentLen == 0){
+      return 0;
+   }
+
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   for(s4 i=0;i<entries;i++){
+      // lets find out which entry has all zeros
+      // which denotes available index
+
+      // as per minidriver specification
+      // if bit 0 of flags should be set for it to be
+      // a valid entry
+      if((CMapFileGetFlag(cmapContents, i) & 0x01) != 0x01){
+         return i;
+      }
+   }
+
+   // reaching here means that cmap file has entries
+   // which are all occupied, in that the available
+   // index would be entries
+   return entries;
+}
+
+CK_BYTE Token::GetContainerForCert(u1Array const & cmapContents, u8 checkValue, u1 * keySpec)
+{
+   // Look for existing matching private key
+   vector <PrivateKeyObject*> vPriv(FindPrivateKeys(_objects, checkValue));
+   for(size_t ipriv = 0; ipriv < vPriv.size(); ++ipriv)
+   {
+      // See it the corresponding container/keyspec is already occupied by a certificate.
+      // If it isn't, this is free for use.
+      if(!FindCertificate(_objects, vPriv[ipriv]->_ctrIndex, vPriv[ipriv]->_keySpec))
+      {
+         *keySpec = vPriv[ipriv]->_keySpec;
+         return vPriv[ipriv]->_ctrIndex;
+      }
+   }
+   // No matching private key, find new container
+
+   return GetAvailableContainerIndex(cmapContents);
+}
+
+CK_BYTE Token::GetContainerForPrivateKey(u1Array const & cmapContents, u8 checkValue, u1 * keySpec)
+{
+   // Look for existing matching certificate
+   vector <CertificateObject*> vCert(FindCertificates(_objects, checkValue));
+   for(size_t icert = 0; icert < vCert.size(); ++icert)
+   {
+      // See it the corresponding container/keyspec is already occupied by a key.
+      // If it isn't, this is free for use.
+      if(!FindPrivateKey(_objects, vCert[icert]->_ctrIndex, vCert[icert]->_keySpec))
+      {
+         *keySpec = vCert[icert]->_keySpec;
+         return vCert[icert]->_ctrIndex;
+      }
+   }
+   // No matching certificate, find new container
+
+   return GetAvailableContainerIndex(cmapContents);
+}
+
+auto_ptr<u1Array> Token::UpdateCMap(CK_BYTE ctrIdx, u1Array const & contents, string const & contName )
+{
+   u4  contentLen = contents.GetLength();
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   u4 newCMapSize = SIZE_CONTAINERMAPRECORD * entries;
+
+   if(ctrIdx >= entries){
+      entries = ctrIdx + 1;
+      newCMapSize = entries * SIZE_CONTAINERMAPRECORD;
+   }
+
+   //autoarray<u1> updatedContents(new u1[newCMapSize]);
+
+   auto_ptr<u1Array> updatedContents(new u1Array(newCMapSize));
+
+   memset(updatedContents->GetBuffer(), 0, newCMapSize);
+   memcpy(updatedContents->GetBuffer(), contents.GetBuffer(), contentLen);
+
+   u1 flags = CMapFileGetFlag(*updatedContents, ctrIdx);
+   if(!(flags & 0x01))
+   {
+      // Container record is new, set container Name (UNICODE string)
+      CMapFileSetName(*updatedContents, ctrIdx, contName);
+      CMapFileSetFlag(*updatedContents, ctrIdx, flags | 0x01);
+   }
+
+   SetDefaultContainer(*updatedContents, 0xFF);
+
+   return updatedContents;
+}
+
+auto_ptr<u1Array> Token::UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,u4 keySize,u1 keySpec,CK_BBOOL isDefault, string const & contName)
+{
+   u4  contentLen = contents.GetLength();
+   s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+   u4 newCMapSize = SIZE_CONTAINERMAPRECORD * entries;
+
+   if(ctrIdx >= entries){
+      entries = ctrIdx + 1;
+      newCMapSize = entries * SIZE_CONTAINERMAPRECORD;
+   }
+
+   auto_ptr<u1Array> updatedContents(new u1Array(newCMapSize));
+
+   memset(updatedContents->GetBuffer(), 0, newCMapSize);
+   memcpy(updatedContents->GetBuffer(), contents.GetBuffer(), contentLen);
+
+   u1 flags = CMapFileGetFlag(*updatedContents, ctrIdx);
+   if(!(flags & 0x01))
+   {
+      // Container record is new, set container Name (UNICODE string)
+      CMapFileSetName(*updatedContents, ctrIdx, contName);
+      CMapFileSetFlag(*updatedContents, ctrIdx, flags | 0x01);
+   }
+
+   // Default container
+   SetDefaultContainer(*updatedContents, isDefault ? ctrIdx : 0xFF);
+
+   // Container Key Size
+   if (keySpec == KEYSPEC_SIGNATURE){
+      CMapFileSetSignSize(*updatedContents, ctrIdx, keySize);
+   }else{
+      CMapFileSetExchSize(*updatedContents, ctrIdx, keySize);
+   }
+
+   return updatedContents;
+}
+
+vector <PrivateKeyObject*> Token::FindPrivateKeys(vector<StorageObject*> const & objects, u8 checkValue)
+{
+   // checkValue is derived from the modulus and is sufficiently
+   // long (8 bytes) to be a unique handle to the key pair / certificate
+   vector <PrivateKeyObject*> vPriv;
+
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++){
+      if(objects[i] && objects[i]->_class == CKO_PRIVATE_KEY){
+         PrivateKeyObject * privObject = (PrivateKeyObject*)objects[i];
+         if(privObject->_checkValue == checkValue)
+            vPriv.push_back(privObject);
+      }
+   }
+   return vPriv;
+}
+
+PrivateKeyObject * Token::FindPrivateKey(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec)
+{
+   vector <PrivateKeyObject*> vPriv;
+
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+   {
+      if(objects[i] && objects[i]->_class == CKO_PRIVATE_KEY)
+      {
+         PrivateKeyObject * privObject = (PrivateKeyObject*)objects[i];
+         if(privObject->_ctrIndex == ctrdIdx && privObject->_keySpec == keySpec)
+            return privObject;  // Is supposed to be only one.
+      }
+   }
+   return 0;
+}
+
+vector <CertificateObject*> Token::FindCertificates(vector<StorageObject*> const & objects, u8 checkValue)
+{
+   // checkValue is derived from the modulus and is sufficiently
+   // long (8 bytes) to be a unique handle to the key pair / certificate
+   vector <CertificateObject*> vCert;
+
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+   {
+      if(objects[i] && objects[i]->_class == CKO_CERTIFICATE)
+      {
+         CertificateObject * certObject = (CertificateObject*)objects[i];
+         if(certObject->_checkValue == checkValue)
+            vCert.push_back(certObject);
+      }
+   }
+   return vCert;
+}
+
+CertificateObject * Token::FindCertificate(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec)
+{
+   for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+   {
+      if(objects[i] && objects[i]->_class == CKO_CERTIFICATE)
+      {
+         CertificateObject * certObject = (CertificateObject*)objects[i];
+         if(certObject->_ctrIndex == ctrdIdx && certObject->_keySpec == keySpec)
+            return certObject;
+      }
+   }
+   return 0;
+}
+
+CK_RV Token::GenerateKeyPair(auto_ptr<StorageObject> & stobjRsaPub, auto_ptr<StorageObject> & stobjRsaPriv,
+                             CK_OBJECT_HANDLE_PTR phPubKey,CK_OBJECT_HANDLE_PTR phPrivKey)
+{
+
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPublicKeyObject * rsaPubObject = static_cast<RSAPublicKeyObject*>(stobjRsaPub.get());
+      RSAPrivateKeyObject * rsaPrivObject = static_cast<RSAPrivateKeyObject*>(stobjRsaPriv.get());
+
+      if( (rsaPubObject->_modulusLen < RSA_KEY_MIN_LENGTH) ||
+         (rsaPubObject->_modulusLen > RSA_KEY_MAX_LENGTH) )
+         throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+      //CheckAvailableSpace(); // HACK !!
+
+      //Log::log("Generating KeyPair on the smartcard...");
+
+      std::string nameCMapFile;
+
+      // TBD (Start a pc/sc transaction here)
+
+      // let's first read the container record file to
+      // see which container is available.
+      // No need to search for matching certificate,
+      // since this can not exist one yet!! ;)
+      nameCMapFile = "mscp\\cmapfile";
+      const u1Array & fileData = this->_cardCache->ReadFile(nameCMapFile);
+
+      CK_BYTE ctrIdx = this->GetAvailableContainerIndex(fileData);
+      if(ctrIdx == 0xFF)
+         throw CkError(CKR_DEVICE_MEMORY);
+
+      // create a capi container.
+      // KEYSPEC_KEYEXCHANGE by default.
+      this->_cardCache->ClearContainer(ctrIdx);   // Invalidate cache
+      //this->_mscm->CreateCAPIContainer(ctrIdx,CK_FALSE,KEYSPEC_KEYEXCHANGE,rsaPubObject->_modulusLen,NULL_PTR);
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ManageGC( );
+            ntry++;
+            this->_mscm->CreateCAPIContainer(ctrIdx,CK_FALSE,KEYSPEC_KEYEXCHANGE,rsaPubObject->_modulusLen,NULL_PTR);
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::GenerateKeyPair", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  Log::error( "Token::GenerateKeyPair", "Throw Exception CKR_DEVICE_MEMORY" );
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+      this->RegisterContainerUpdate();
+
+      rsaPubObject->_ctrIndex = ctrIdx;
+      rsaPubObject->_keySpec = KEYSPEC_KEYEXCHANGE;
+
+      rsaPrivObject->_ctrIndex = ctrIdx;
+      rsaPrivObject->_keySpec = KEYSPEC_KEYEXCHANGE;
+
+      // populate these objects with the key material
+      const CardCache::Container & cont = _cardCache->ReadContainer(ctrIdx);
+
+      rsaPubObject->_exponent = new u1Array();
+      *rsaPubObject->_exponent = cont.exchPublicExponent;
+      rsaPubObject->_modulus = new u1Array();
+      *rsaPubObject->_modulus = cont.exchModulus;
+      rsaPubObject->_local = CK_TRUE;
+
+
+      // Copy these modulus and exponent in the private key component also
+      rsaPrivObject->_publicExponent = new u1Array();
+      *rsaPrivObject->_publicExponent = cont.exchPublicExponent;
+
+      rsaPrivObject->_modulus = new u1Array();
+      *rsaPrivObject->_modulus = cont.exchModulus;
+      rsaPrivObject->_checkValue = Util::MakeCheckValue(cont.exchModulus.GetBuffer(),
+         cont.exchModulus.GetLength());
+      rsaPrivObject->_local = CK_TRUE;
+
+      string contName(CAttributedCertificate::DerivedUniqueName(cont.exchModulus.GetBuffer(),
+         cont.exchModulus.GetLength()));
+
+      // now its time to add the corresponding objects to
+      // the card (as files)
+
+      // The public key may be a session object, in that case, don't save it.
+
+      if( rsaPubObject->_tokenObject )
+      {
+         rv = this->AddObject( stobjRsaPub, phPubKey );
+      }
+
+      if( CKR_OK == rv )
+      {
+         rv = this->AddObject( stobjRsaPriv, phPrivKey );
+
+         if( CKR_OK == rv )
+         {
+            try
+            {
+               auto_ptr<u1Array> newCMap( UpdateCMap( ctrIdx, fileData, rsaPubObject->_modulusLen, KEYSPEC_KEYEXCHANGE, CK_TRUE, contName ) );
+               _cardCache->WriteFile( nameCMapFile, *newCMap );
+               RegisterFileUpdate( );
+            }
+            catch( CkError x )
+            {
+               rv = x.Error( );
+               Log::error( "Token::SetAttributeValue", "WriteFile failed" );
+            }
+
+            if( CKR_OK != rv )
+            {
+               if( rsaPubObject->_tokenObject )
+               {
+                  DeleteObject( *phPubKey );
+                  // ???
+               }
+               DeleteObject( *phPrivKey );
+
+               throw CkError( rv );
+            }
+         }
+         else if( rsaPubObject->_tokenObject )
+         {
+            DeleteObject( *phPubKey );
+         }
+      }
+   }
+   TOKEN_CATCH(rv)
+
+      return rv;
+}
+
+
+CK_RV Token::GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      *object = GetObject(hObject);
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::Encrypt(StorageObject* pubObj,u1Array* dataToEncrypt,CK_ULONG mechanism,CK_BYTE_PTR pEncryptedData)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPublicKeyObject* object = (RSAPublicKeyObject*)pubObj;
+
+      if(mechanism == CKM_RSA_PKCS){
+         // first do the length checks
+         if(dataToEncrypt->GetLength() > (object->_modulus->GetLength() - 11)){
+            throw CkError(CKR_DATA_LEN_RANGE);
+         }
+
+         rsaPublicKey_t key;
+
+         key.modulus = object->_modulus->GetBuffer() ;
+         key.modulusLength = object->_modulus->GetLength() * 8 ;
+         key.publicExponent = object->_exponent->GetBuffer();
+         key.publicExponentLength =  object->_exponent->GetLength() * 8;
+
+         u4 outLength = object->_modulus->GetLength();
+
+         DWORD rv ;
+         DWORD size ;
+         DWORD pubSize ;
+         R_RSA_PUBLIC_KEY	rsaKeyPublic ;
+
+         rsaKeyPublic.bits = key.modulusLength ;
+
+         size = (key.modulusLength + 7) / 8 ;
+         memcpy(rsaKeyPublic.modulus, key.modulus, size) ;
+
+         pubSize = (key.publicExponentLength + 7) / 8 ;
+         memset(rsaKeyPublic.exponent, 0, size) ;
+         memcpy(&rsaKeyPublic.exponent[size - pubSize], key.publicExponent, pubSize) ;
+
+         R_RANDOM_STRUCT & randomStruct = Util::RandomStruct();
+
+         rv = RSAPublicEncrypt(
+            pEncryptedData,
+            &outLength,
+            dataToEncrypt->GetBuffer(),
+            dataToEncrypt->GetLength(),
+            &rsaKeyPublic,
+            &randomStruct);
+
+      }else{
+
+         u4 modulusLen = object->_modulus->GetLength();
+
+         if(dataToEncrypt->GetLength() > (modulusLen)){
+            throw CkError(CKR_DATA_LEN_RANGE);
+         }
+
+         // pre-pad with zeros
+         u1Array* messageToEncrypt = new u1Array(modulusLen);
+         memset(messageToEncrypt->GetBuffer(),0,modulusLen);
+
+         s4 offsetMsgToEncrypt = modulusLen - dataToEncrypt->GetLength();
+
+         for(u4 i=0,j=offsetMsgToEncrypt;i<dataToEncrypt->GetLength();i++,j++){
+            messageToEncrypt->GetBuffer()[j] = dataToEncrypt->GetBuffer()[i];
+         }
+
+         // just block transform now
+         s4 size ;
+         s4 pubSize ;
+         R_RSA_PUBLIC_KEY	rsaKeyPublic ;
+
+         //Build the RSA public key context
+         rsaKeyPublic.bits = object->_modulus->GetLength() * 8;
+
+         size = (rsaKeyPublic.bits  + 7) / 8 ;
+         memcpy(rsaKeyPublic.modulus,object->_modulus->GetBuffer(),size) ;
+
+         pubSize = ((object->_exponent->GetLength() * 8) + 7) / 8 ;
+         memset(rsaKeyPublic.exponent, 0, size) ;
+         memcpy(&rsaKeyPublic.exponent[size - pubSize], object->_exponent->GetBuffer(), pubSize) ;
+
+         u4 outputLen = size;
+
+         rv = RSAPublicBlock(pEncryptedData,&outputLen,messageToEncrypt->GetBuffer(),size,&rsaKeyPublic);
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::Decrypt(StorageObject* privObj,u1Array* dataToDecrypt,CK_ULONG mechanism,CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      u1Array* data = NULL_PTR;
+
+      RSAPrivateKeyObject * rsaKey = static_cast<RSAPrivateKeyObject*>(privObj);
+
+      //data = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, dataToDecrypt);
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ManageGC( );
+            ntry++;
+            data = this->_mscm->PrivateKeyDecrypt( rsaKey->_ctrIndex, rsaKey->_keySpec, dataToDecrypt );
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::Decrypt", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+
+
+
+
+      if(mechanism == CKM_RSA_PKCS){
+
+         u1* decryptedMessage = (u1*)data->GetBuffer();
+
+#define PKCS_EMEV15_PADDING_TAG   0x2
+
+         if ((decryptedMessage[0] != 0x00) || (decryptedMessage[1] != PKCS_EMEV15_PADDING_TAG))
+         {
+            // TBD: Lookup correct error message
+            // invalid message padding
+            rv = CKR_ENCRYPTED_DATA_INVALID;
+         }else{
+
+            // seach message padding separator
+            u4 mPos = 2 + 8;
+            while ((decryptedMessage[mPos] != 0x00) && (mPos < data->GetLength()))
+            {
+               mPos++;
+            }
+
+            // point on message itself.
+            mPos++;
+            u1Array* finalDecryptedMessage = new u1Array(data->GetLength() - mPos);
+            memcpy(finalDecryptedMessage->GetBuffer(),(u1*)&decryptedMessage[mPos],finalDecryptedMessage->GetLength());
+
+            delete data;
+
+            data = finalDecryptedMessage;
+         }
+      }
+      // else... CKM_RSA_X_509: Ignore padding
+
+      if(data){
+         if(*pulDataLen >= data->GetLength())
+            memcpy(pData,data->GetBuffer(),data->GetLength());
+         else
+            rv = CKR_BUFFER_TOO_SMALL;
+         *pulDataLen = data->GetLength();
+         delete data;
+      }
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::Verify(StorageObject* pubObj,u1Array* dataToVerify,CK_ULONG mechanism,u1Array* signature)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      RSAPublicKeyObject* object = (RSAPublicKeyObject*)pubObj;
+
+      if(((mechanism == CKM_RSA_PKCS) && (dataToVerify->GetLength() > (object->_modulus->GetLength() - 11))) ||
+         ((mechanism == CKM_RSA_X_509) && (dataToVerify->GetLength() > object->_modulus->GetLength())))
+      {
+         throw CkError(CKR_DATA_LEN_RANGE);
+      }
+
+      if(signature->GetLength() != object->_modulus->GetLength()){
+         throw CkError(CKR_SIGNATURE_LEN_RANGE);
+      }
+
+      s4 size ;
+      s4 pubSize ;
+      R_RSA_PUBLIC_KEY	rsaKeyPublic ;
+
+      //Build the RSA public key context
+      rsaKeyPublic.bits = object->_modulus->GetLength() * 8;
+
+      size = (rsaKeyPublic.bits  + 7) / 8 ;
+      memcpy(rsaKeyPublic.modulus,object->_modulus->GetBuffer(),size) ;
+
+      pubSize = ((object->_exponent->GetLength() * 8) + 7) / 8 ;
+      memset(rsaKeyPublic.exponent, 0, size) ;
+      memcpy(&rsaKeyPublic.exponent[size - pubSize], object->_exponent->GetBuffer(), pubSize) ;
+
+      u4 messageToVerifyLen = size;
+      u1Array* messageToVerify = new u1Array(messageToVerifyLen);
+
+      RSAPublicBlock(messageToVerify->GetBuffer(),&messageToVerifyLen,signature->GetBuffer(),size,&rsaKeyPublic);
+
+      switch(mechanism){
+
+            case CKM_RSA_PKCS:
+               rv = VerifyRSAPKCS1v15(messageToVerify,dataToVerify,size);
+               break;
+
+            case CKM_RSA_X_509:
+               rv = VerifyRSAX509(messageToVerify,dataToVerify,size);
+               break;
+
+
+            case CKM_SHA1_RSA_PKCS:
+               rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_SHA_1);
+               break;
+
+            case CKM_SHA256_RSA_PKCS:
+               rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_SHA256);
+               break;
+
+            case CKM_MD5_RSA_PKCS:
+               rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_MD5);
+               break;
+
+            default:
+               PKCS11_ASSERT(CK_FALSE);
+               rv = CKR_GENERAL_ERROR;
+               break;
+      }
+
+      delete messageToVerify;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+CK_RV Token::VerifyHash(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen,CK_ULONG hashAlgo)
+{
+   u1 DER_SHA1_Encoding[]   = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
+   u1 DER_SHA256_Encoding[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+   u1 DER_MD5_Encoding[]    = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
+
+   s4  DER_Encoding_Len = 0;
+
+   switch(hashAlgo){
+        case CKM_SHA_1:
+           DER_Encoding_Len = sizeof(DER_SHA1_Encoding);
+           break;
+
+        case CKM_SHA256:
+           DER_Encoding_Len = sizeof(DER_SHA256_Encoding);
+           break;
+
+        case CKM_MD5:
+           DER_Encoding_Len = sizeof(DER_MD5_Encoding);
+           break;
+
+   }
+
+   u1* msg  = messageToVerify->GetBuffer();
+   u1* hash = dataToVerify->GetBuffer();
+
+   // Check the decoded value against the expected data.
+   if ((msg[0] != 0x00) || (msg[1] != 0x01)){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   s4 posn = modulusLen - DER_Encoding_Len - dataToVerify->GetLength();
+
+   for(s4 i = 2; i < (posn - 1); i++)
+   {
+      if(msg[i] != 0xFF){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   if(msg[posn - 1] != 0x00){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   for (u4 i = 0; i < dataToVerify->GetLength(); i++){
+      if (msg[posn + i + DER_Encoding_Len] != hash[i]){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   return CKR_OK;
+}
+
+CK_RV Token::VerifyRSAX509(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen)
+{
+   // reach the first non-zero bytes in decrypted signature
+   // and data
+   u4 pos1=0;
+   u4 pos2=0;
+
+   for(;pos1<dataToVerify->GetLength();pos1++){
+      if(dataToVerify->GetBuffer()[pos1] != 0)
+         break;
+   }
+
+   for(;pos2<messageToVerify->GetLength();pos2++){
+      if(messageToVerify->GetBuffer()[pos2] != 0)
+         break;
+   }
+
+   if((dataToVerify->GetLength() - pos1) != (modulusLen - pos2)){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   for(u4 i=pos1,j=pos2;i<(modulusLen - pos2);i++,j++){
+      if(dataToVerify->GetBuffer()[i] != messageToVerify->GetBuffer()[j]){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   return CKR_OK;
+}
+
+CK_RV Token::VerifyRSAPKCS1v15(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen)
+{
+   // skip past the pkcs block formatting data
+   u4 pos = 2;
+   for(;pos<modulusLen;pos++)
+   {
+      if(messageToVerify->GetBuffer()[pos] == 0x00)
+      {
+         pos++;
+         break;
+      }
+   }
+
+   if(dataToVerify->GetLength() != (modulusLen - pos)){
+      return CKR_SIGNATURE_INVALID;
+   }
+
+   for(u4 i=0, j=pos;i< (modulusLen - pos); i++,j++){
+      if(dataToVerify->GetBuffer()[i] != messageToVerify->GetBuffer()[j]){
+         return CKR_SIGNATURE_INVALID;
+      }
+   }
+
+   return CKR_OK;
+}
+
+
+CK_RV Token::Sign(StorageObject* privObj,u1Array* dataToSign,CK_ULONG mechanism,CK_BYTE_PTR pSignature)
+{
+   CK_RV rv = CKR_OK;
+   TOKEN_TRY
+   {
+      u1Array* messageToSign = NULL_PTR;
+
+      // TODO: Should check if cast is safe
+      RSAPrivateKeyObject * rsaKey = static_cast<RSAPrivateKeyObject*>(privObj);
+      CK_ULONG modulusLen = rsaKey->_modulus->GetLength();
+
+      if(((mechanism == CKM_RSA_PKCS) && (dataToSign->GetLength() > modulusLen - 11)) ||
+         ((mechanism == CKM_RSA_X_509) && (dataToSign->GetLength() > modulusLen)))
+      {
+         throw CkError(CKR_DATA_LEN_RANGE);
+      }
+
+      switch(mechanism){
+
+            case CKM_RSA_PKCS:
+               messageToSign = PadRSAPKCS1v15(dataToSign,modulusLen);
+               break;
+
+            case CKM_RSA_X_509:
+               messageToSign = PadRSAX509(dataToSign,modulusLen);
+               break;
+
+            case CKM_SHA1_RSA_PKCS:
+               messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_SHA_1);
+               break;
+
+            case CKM_SHA256_RSA_PKCS:
+               messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_SHA256);
+               break;
+
+            case CKM_MD5_RSA_PKCS:
+               messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_MD5);
+               break;
+      }
+
+      u1Array* signatureData = NULL_PTR;
+
+      //signatureData = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, messageToSign);
+
+      int ntry = 0;
+      while( ntry < MAX_RETRY )
+      {
+         try
+         {
+            ManageGC( );
+            ntry++;
+            signatureData = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, messageToSign);
+            break;
+         }
+         catch( Marshaller::Exception & x )
+         {
+            CK_RV rv = CkError::CheckMarshallerException( x );
+            if( CKR_DEVICE_MEMORY == rv )
+            {
+               Log::error( "Token::Sign", "ForceGarbageCollector" );
+               _mscm->ForceGarbageCollector( );
+               if( ntry >= MAX_RETRY )
+               {
+                  throw CkError( rv );
+               }
+            }
+            else
+            {
+               throw CkError( rv );
+            }
+         }
+      }
+
+      memcpy(pSignature,signatureData->GetBuffer(),signatureData->GetLength());
+
+      delete signatureData;
+      delete messageToSign;
+   }
+   TOKEN_CATCH(rv)
+      return rv;
+}
+
+// these methods should be moved to rsa library
+// once we have it
+u1Array* Token::PadRSAPKCS1v15(u1Array* dataToSign,CK_ULONG modulusLen)
+{
+   u1Array* messageToSign = new u1Array(modulusLen);
+   memset(messageToSign->GetBuffer(),0,modulusLen);
+
+   messageToSign->SetU1At(1,1);
+
+   s4 offsetMessageToSign = modulusLen - dataToSign->GetLength() - 3;
+
+   for(s4 i=0;i<offsetMessageToSign;i++){
+      messageToSign->SetU1At(2+i,0xFF);
+   }
+
+   offsetMessageToSign += 3;
+
+   memcpy((u1*)&messageToSign->GetBuffer()[offsetMessageToSign],dataToSign->GetBuffer(),dataToSign->GetLength());
+
+   return messageToSign;
+}
+
+u1Array* Token::PadRSAX509(u1Array* dataToSign,CK_ULONG modulusLen)
+{
+
+   u1Array* messageToSign = new u1Array(modulusLen);
+   memset(messageToSign->GetBuffer(),0,modulusLen);
+
+   s4 offsetMessageToSign = modulusLen - dataToSign->GetLength();
+
+   memcpy((u1*)&messageToSign->GetBuffer()[offsetMessageToSign],dataToSign->GetBuffer(),dataToSign->GetLength());
+
+   return messageToSign;
+}
+
+u1Array* Token::EncodeHashForSigning(u1Array* hashedData,CK_ULONG modulusLen,CK_ULONG hashAlgo)
+{
+   u1 DER_SHA1_Encoding[]   = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
+   u1 DER_SHA256_Encoding[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+   u1 DER_MD5_Encoding[]    = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
+
+   u1* DER_Encoding = NULL_PTR;
+   s4  DER_Encoding_Len = 0;
+
+   switch(hashAlgo){
+        case CKM_SHA_1:
+           DER_Encoding_Len = sizeof(DER_SHA1_Encoding);
+           DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+           memcpy(DER_Encoding,DER_SHA1_Encoding,DER_Encoding_Len);
+           break;
+
+        case CKM_SHA256:
+           DER_Encoding_Len = sizeof(DER_SHA256_Encoding);
+           DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+           memcpy(DER_Encoding,DER_SHA256_Encoding,DER_Encoding_Len);
+           break;
+
+        case CKM_MD5:
+           DER_Encoding_Len = sizeof(DER_MD5_Encoding);
+           DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+           memcpy(DER_Encoding,DER_MD5_Encoding,DER_Encoding_Len);
+           break;
+
+   }
+
+   u1Array* messageToSign = new u1Array(modulusLen);
+   memset(messageToSign->GetBuffer(),0,modulusLen);
+
+   messageToSign->SetU1At(1,1);
+
+   // caluclate pos
+   s4 pos = modulusLen - DER_Encoding_Len - hashedData->GetLength();
+
+   for(s4 i=2;i<(pos - 1);i++){
+      messageToSign->SetU1At(i,0xFF);
+   }
+
+   memcpy((u1*)&messageToSign->GetBuffer()[pos],DER_Encoding,DER_Encoding_Len);
+   memcpy((u1*)&messageToSign->GetBuffer()[pos+DER_Encoding_Len],hashedData->GetBuffer(),hashedData->GetLength());
+
+   delete DER_Encoding;
+
+   return messageToSign;
+}
+
+bool Token::PerformDeferredDelete()
+{
+   bool fSync = true;
+   PKCS11_ASSERT(this->_roleLogged != CKU_NONE);
+
+   if(_toDelete.empty())
+      return fSync;
+
+   _cardCache->ClearFileList("mscp");
+   _cardCache->ClearFileList("p11");
+
+   // Delete files that are pending to be deleted
+   vector<string>::iterator ifile = _toDelete.begin();
+   while(ifile != _toDelete.end())
+   {
+      try
+      {
+         _cardCache->ClearFile(*ifile);
+         _mscm->DeleteFile(&(*ifile));
+         RegisterFileUpdate();
+         ifile = _toDelete.erase(ifile);
+      }
+      catch(FileNotFoundException &)
+      {
+         ifile = _toDelete.erase(ifile);
+      }
+      catch(...)
+      {
+         // Failed to delete, keep it in the list.
+         fSync = false;
+         ++ifile;
+      }
+   }
+   return fSync;
+}
+
+s4 Token::RegisterStorageObject(StorageObject * object)
+{
+   // add this in the token object list
+
+   for(size_t k = 0; k<_objects.size(); k++)
+   {
+      PKCS11_ASSERT(_objects[k] != object);
+   }
+
+
+   size_t t = 0;
+   while(t < _objects.size())
+   {
+      if(!_objects[t])
+      {
+         _objects[t] = object;
+         return static_cast<s4>(t+1);
+      }
+      ++t;
+   }
+   // Expand list
+   _objects.push_back(object);
+   return static_cast<s4>(_objects.size());
+}
+
+void Token::UnregisterStorageObject(StorageObject * object)
+{
+   size_t t = 0;
+   while(t<_objects.size())
+   {
+      if(_objects[t] == object)
+      {
+         _objects[t] = 0;
+         break;
+      }
+      ++t;
+   }
+}
+
+auto_ptr<u1Array> Token::ReadCertificateFile(string const & path)
+{
+   // Read certificate file
+
+   const u1Array & compressedCert = _cardCache->ReadFile(path);
+
+   // Decompress
+   unsigned long origLen = compressedCert.ReadU1At(3) * 256 + compressedCert.ReadU1At(2);
+   autoarray<u1> origData(new u1[origLen]);
+   auto_ptr<u1Array> value(new u1Array(origLen));
+   uncompress(value->GetBuffer(), &origLen, compressedCert.GetBuffer()+4, compressedCert.GetLength() - 4);
+   return value;
+
+}
+
+void Token::RegisterPinUpdate()
+{
+   _fPinChanged = true;
+}
+
+void Token::RegisterContainerUpdate()
+{
+   _fContainerChanged = true;
+}
+
+void Token::RegisterFileUpdate()
+{
+   _fFileChanged = true;
+}
+
+//void Token::CheckAvailableSpace()
+//{
+//   return;
+//
+//   //u4 highWaterMark = 20000;
+//   //auto_ptr<u4Array> freeSpace(_mscm->QueryFreeSpace());
+//
+//   //u4 availSpace = freeSpace->ReadU4At(2);
+//   //if(availSpace < highWaterMark)
+//   //    throw CkError(CKR_DEVICE_MEMORY);
+//
+//}
+
+
+/*
+*/
+bool Token::isAuthenticated( void )
+{
+   bool bRet = false;
+   try
+   {
+      bRet = (bool)(_mscm->IsAuthenticated( CARD_ROLE_USER ));
+   }
+   catch( ... )
+   {
+      Log::error( "Token::isAuthenticated",  "isAuthenticated" );
+      bRet = false;
+   }
+   return bRet;
+}
+
+
+/*
+*/
+bool Token::isSSO( void )
+{
+   bool bRet = false;
+   u1Array* ba = 0;
+   try
+   {
+      ba = _mscm->GetCardProperty( 0x80, 0 );
+   }
+   catch( ... )
+   {
+      //Log::error( "Token::isSSO",  "GetCardProperty" );
+      Log::log( "Token::isSSO - GetCardProperty failed !" );
+      bRet = false;
+   }
+   if( 0 != ba )
+   {
+      bRet = (bool)(ba->GetBuffer( )[9]);
+
+      /*
+      log2( "Max Attempts <%d>", ba->GetBuffer( )[0] );
+      log2( "Min Length <%d>", ba->GetBuffer( )[1] );
+      log2( "Max Length <%d>", ba->GetBuffer( )[2] );
+      log2( "Char Set <0x%02X>", ba->GetBuffer( )[3] );
+      log2( "Complexity rule 1 <%d>", ba->GetBuffer( )[4] );
+      log2( "Complexity rule 2 <%d>", ba->GetBuffer( )[5] );
+      log2( "Adjacent allowed <%s>", ba->GetBuffer( )[6] ? "Yes" : "No" );
+      log2( "History <%d>", ba->GetBuffer( )[7] );
+      log2( "Unblock allowed <%s>", ba->GetBuffer( )[8] ? "Yes" : "No" );
+      log2( "SSO allowed <%s>", ba->GetBuffer( )[9] ? "Yes" : "No" );
+
+      std::string s6 = ba->GetBuffer( )[6] ? "YES" : "NO";
+      std::string s8 = ba->GetBuffer( )[8] ? "YES" : "NO";
+      std::string s9 = ba->GetBuffer( )[9] ? "YES" : "NO";
+      std::string s3 = "";
+      translateToHex( ba->GetBuffer( )[3], s3 );
+
+      if( ( ba->GetBuffer( )[0] != m_iMaxAttemps )
+      || ( ba->GetBuffer( )[1] != m_iMinLength )
+      || ( ba->GetBuffer( )[2] != m_iMaxLength )
+      || ( s3 != m_stCharSet )
+      || ( ba->GetBuffer( )[4] != m_iComplexityRule1 )
+      || ( ba->GetBuffer( )[5] != m_iComplexityRule2 )
+      || ( s6 != m_stAdjacentAllowed )
+      || ( ba->GetBuffer( )[7] != m_iHistory )
+      || ( s8 != m_stAllowUnblock )
+      || ( s9 != m_stAllowSSO ) )
+      {
+      bRet = false;
+      error( "check pin policy" );
+      }
+      */
+
+      delete ba;
+   }
+   return bRet;
+}
+
+
+/*
+*/
+void Token::CardBeginTransaction( )
+{
+   //Log::begin( "Token::CardBeginTransaction" );
+
+   //Log::log( "Token::CardBeginTransaction - _mscm->GetPcscCardHandle..." );
+   SCARDHANDLE hCard = _mscm->GetPcscCardHandle( );
+   //Log::log( "Token::CardBeginTransaction - hCard <%#02x>", hCard );
+
+   if( !hCard )
+   {
+      Log::error( "Token::CardBeginTransaction",  "CKR_FUNCTION_FAILED" );
+      throw CkError( CKR_FUNCTION_FAILED );
+   }
+
+   LONG hResult = SCardBeginTransaction( hCard );
+   while( SCARD_W_RESET_CARD == hResult )
+   {
+      _roleLogged = CKU_NONE;
+      DWORD dwActiveProtocol;
+
+      //Log::log( "Token::CardBeginTransaction - SCardReconnect..." );
+      LONG hr = SCardReconnect( hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, &dwActiveProtocol );
+      //Log::log( "Token::CardBeginTransaction - hr <%#02x>", hr );
+      if( SCARD_S_SUCCESS == hr )
+      {
+         //Log::log( "Token::CardBeginTransaction - SCardBeginTransaction..." );
+         hResult = SCardBeginTransaction( hCard );
+         //Log::log( "Token::CardBeginTransaction - hResult <%#02x>", hResult );
+      }
+      else
+      {
+         Log::log( "Token::CardBeginTransaction - ## ERROR ## PcscError <%#02x>", hr );
+         Log::error( "Token::CardBeginTransaction",  "PcscError" );
+         throw PcscError( hr );
+      }
+   };
+
+
+   if( hResult != SCARD_S_SUCCESS )
+   {
+      Log::log( "Token::CardBeginTransaction - ## ERROR ## hResult <%#02x>", hResult );
+      Log::error( "Token::CardBeginTransaction",  "PcscError" );
+      throw PcscError( hResult );
+   }
+
+   //Log::end( "Token::CardBeginTransaction" );
+}
+
+
+void Token::CardEndTransaction()
+{
+   //Log::begin( "Token::CardEndTransaction" );
+
+   SCARDHANDLE hCard = _mscm->GetPcscCardHandle( );//_mscm->GetSCardHandle();
+   if(!hCard)
+      throw CkError(CKR_FUNCTION_FAILED);
+
+   LONG hResult = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
+#ifdef __APPLE__
+   while((hResult == SCARD_W_RESET_CARD) || (hResult == SCARD_W_REMOVED_CARD))
+#else
+   while(hResult == SCARD_W_RESET_CARD)
+#endif
+   {
+      _roleLogged = CKU_NONE;
+      DWORD dwActiveProtocol;
+      LONG hr = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,SCARD_LEAVE_CARD,&dwActiveProtocol);
+      if(hr == SCARD_S_SUCCESS)
+         hResult = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
+      else
+         throw PcscError(hr);
+   }
+   if(hResult != SCARD_S_SUCCESS && hResult != SCARD_E_NOT_TRANSACTED) // SCARD_E_NOT_TRANSACTED shouldn't occur, still ignore it.
+      throw PcscError(hResult);
+
+   //Log::end( "Token::CardEndTransaction" );
+}
+
+StorageObject * Token::GetObject(CK_OBJECT_HANDLE hObject)
+{
+   CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+   if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || !_objects[idx-1])
+      throw CkError(CKR_OBJECT_HANDLE_INVALID);
+
+   return _objects[idx-1];
+}
+
+
+void CMapFileClear(u1Array & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD;
+   memset(file.GetBuffer()+idx, 0, SIZE_CONTAINERMAPRECORD);
+}
+
+void CMapFileSetName(u1Array & file, u1 index, string const & name)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_GUID_INFO;
+   memset(file.GetBuffer()+idx, 0, 80);
+   const size_t length = name.size() > 39 ? 39 : name.size();
+   for(size_t i = 0; i<length; i++)
+      file.SetU1At(idx + 2*i, name[i]); // Convert to wchar, little endian.
+}
+
+u1 CMapFileGetFlag(u1Array const & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_FLAGS;
+   return file.ReadU1At(idx);
+}
+
+void CMapFileSetFlag(u1Array & file, u1 index, u1 flag)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_FLAGS;
+   file.SetU1At(idx, flag);
+}
+
+u2 CMapFileGetSignSize(u1Array const & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_SIG_KEY_SIZE;
+   return LittleEndianToInt<u2>(file.GetBuffer(), idx);
+}
+
+void CMapFileSetSignSize(u1Array & file, u1 index, u2 size)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_SIG_KEY_SIZE;
+   IntToLittleEndian<u2>(size, file.GetBuffer(), idx);
+}
+
+u2 CMapFileGetExchSize(u1Array const & file, u1 index)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_EXC_KEY_SIZE;
+   return LittleEndianToInt<u2>(file.GetBuffer(), idx);
+}
+
+void CMapFileSetExchSize(u1Array & file, u1 index, u2 size)
+{
+   u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_EXC_KEY_SIZE;
+   IntToLittleEndian<u2>(size, file.GetBuffer(), idx);
+}
+
+
+/*
+*/
+bool Token::isPinPadSupported( void )
+{
+   // Get Reader Features
+   BYTE  outBuffer[256];
+   memset( outBuffer, 0, sizeof( outBuffer ) );
+   DWORD dwLen = 0;
+   LONG lRet = SCardControl( _mscm->GetPcscCardHandle( ), CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, outBuffer, sizeof(outBuffer), &dwLen );
+
+   // Search IOCTL of Verify PIN feature
+   int i = 0;
+   bool isVerifyPin = false;
+   m_dwIoctlVerifyPIN = 0;
+   if ( ( SCARD_S_SUCCESS == lRet ) && ( dwLen > 0 ) )
+   {
+      while( ( i + 6 ) <= (int)dwLen )
+      {
+         // Search Verify PIN feature Tag
+         if (  (outBuffer[i] == FEATURE_VERIFY_PIN_DIRECT)
+            &&(outBuffer[i+1] == 4)
+            )
+         {
+            m_dwIoctlVerifyPIN += (outBuffer[i+2] << 24);
+            m_dwIoctlVerifyPIN += (outBuffer[i+3] << 16);
+            m_dwIoctlVerifyPIN += (outBuffer[i+4] << 8);
+            m_dwIoctlVerifyPIN += outBuffer[i+5];
+
+            isVerifyPin = true;
+
+            break;
+         }
+         else
+         {
+            i += (outBuffer[i+1] + 2);
+         }
+      }
+   }
+
+   return (isVerifyPin);
+}
+
+
+/*
+*/
+bool Token::isPinExternalSupported( void )
+{
+   bool bIsPinExternalSupported = false;
+
+   u1Array* pinProperties = new u1Array( 0 );
+   try
+   {
+      pinProperties = _mscm->GetCardProperty( CARD_PROPERTY_PIN_INFO, CARD_ROLE_USER );
+
+      if( CARD_PROPERTY_EXTERNAL_PIN == pinProperties->GetBuffer( )[ 0 ] )
+      {
+         bIsPinExternalSupported = true;
+      }
+   }
+   catch( ... )
+   {
+   }
+
+   delete pinProperties;
+
+   return bIsPinExternalSupported;
+}
+
+/*
+*/
+CK_RV Token::verifyPinWithPinPad( void )
+{
+   DWORD PinId = CARD_ROLE_USER;
+   LONG                 lRet;
+   BYTE                 offset;
+   DWORD                dwSendLen;
+   PIN_VERIFY_STRUCTURE pin_verify;
+   BYTE                 inBuffer[256];
+   DWORD                dwInLen = 0;
+   BYTE                 outBuffer[256];
+   DWORD                dwOutLen = 0;
+
+   pin_verify.bTimerOut = 30;                               /* Time out between key stroke = max(bTimerOut, bTimerOut2). Must be between 15 and 40 sec.*/
+   pin_verify.bTimerOut2 = 00;
+
+   pin_verify.bmFormatString = 0x82;                        /* Padding V2=0x82 */
+
+   pin_verify.bmPINBlockString = 0x06;
+   pin_verify.bmPINLengthFormat = 0x00;
+   pin_verify.bPINMaxExtraDigit1 = 0x08;                    /* Max */
+   pin_verify.bPINMaxExtraDigit2 = 0x04;                    /* Min */
+   pin_verify.bEntryValidationCondition = 0x02;             /* validation key pressed */
+   pin_verify.bNumberMessage = 0x01;
+   pin_verify.wLangId = 0x0904;
+   pin_verify.bMsgIndex = 0x00;
+   pin_verify.bTeoPrologue[0] = 0x00;
+   pin_verify.bTeoPrologue[1] = 0x00;
+   pin_verify.bTeoPrologue[2] = 0x00;                       /* pin_verify.ulDataLength = 0x00; we don't know the size yet */
+
+   offset = 0;
+   pin_verify.abData[offset++] = 0x00;                      /* CLA */ /*********************************/
+   pin_verify.abData[offset++] = 0x20;                      /* INS: VERIFY */
+   pin_verify.abData[offset++] = 0x00;                      /* P1: always 0 */
+   pin_verify.abData[offset++] = (BYTE)PinId;               /* P2: PIN reference */
+   pin_verify.abData[offset++] = 0x08;                      /* Lc: 8 data bytes */
+
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+   pin_verify.abData[offset++] = 0xFF;                      /* 'FF' */
+
+   pin_verify.ulDataLength = offset;                        /* APDU size */
+   dwSendLen = sizeof(PIN_VERIFY_STRUCTURE);
+
+   // Select MSCM Application
+   inBuffer[0] = 0x00;   //CLA
+   inBuffer[1] = 0xA4;   //INS
+   inBuffer[2] = 0x04;   //P1
+   inBuffer[3] = 0x00;   //P2
+   inBuffer[4] = 0x04;   //Li
+
+   memcpy(&inBuffer[5], "MSCM", 4);
+
+   dwInLen = 5 + inBuffer[4];
+
+   dwOutLen = sizeof(outBuffer);
+   memset(outBuffer, 0x00, sizeof(outBuffer));
+
+   lRet = SCardTransmit(_mscm->GetPcscCardHandle(),
+      SCARD_PCI_T0,
+      inBuffer,
+      dwInLen,
+      NULL,
+      outBuffer,
+      &dwOutLen
+      );
+
+   // Send Verify command to the reader
+   dwOutLen = 0;
+   memset(outBuffer, 0x00, sizeof(outBuffer));
+
+   lRet = SCardControl(_mscm->GetPcscCardHandle(),
+      m_dwIoctlVerifyPIN,
+      (BYTE *)&pin_verify,
+      dwSendLen,
+      outBuffer,
+      sizeof(outBuffer),
+      &dwOutLen
+      );
+
+   Log::log( "Token::verifyPinWithPinPad - sw <%#02x %#02x>", outBuffer[ 0 ], outBuffer[ 1 ] );
+
+   CK_RV rv = CKR_FUNCTION_FAILED;
+   if( ( 0x90 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+   {
+      //this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+      //this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+      //this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+      //this->_roleLogged = CKU_USER;
+      rv = CKR_OK;
+   }
+   else if( ( 0x63 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+   {
+      rv = CKR_PIN_INCORRECT;
+   }
+   // operation was cancelled by the \x91Cancel\x92 button
+   else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x01 == outBuffer[ 1 ] ) )
+   {
+      //return SCARD_W_CANCELLED_BY_USER;
+      rv = CKR_FUNCTION_CANCELED;
+   }
+   // operation timed out
+   else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+   {
+      //return SCARD_E_TIMEOUT;
+      rv = CKR_FUNCTION_CANCELED;
+   }
+   // operation timed out
+   else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x03 == outBuffer[ 1 ] ) )
+   {
+      //return SCARD_E_TIMEOUT;
+      rv = CKR_PIN_INCORRECT;
+   }
+
+   Log::log( "Token::verifyPinWithPinPad - rv <%#02x>", rv );
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Token::verifyPinWithBio( void /*Marshaller::u1Array *pin*/ )
+{
+   Log::log( "Token::verifyPinWithBio - <BEGIN>" );
+
+   CK_RV rv = CKR_GENERAL_ERROR;
+
+#ifdef WIN32
+   // Get the current OS version
+   OSVERSIONINFO osvi;
+   memset( &osvi, 0, sizeof( OSVERSIONINFO ) );
+   osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+   GetVersionEx(&osvi);
+   // Check if the Os is W7 or W2K8R2
+   if( ( 6 == osvi.dwMajorVersion ) && ( osvi.dwMinorVersion >= 1 ) )
+   {
+      Log::log( "Token::verifyPinWithBio - Os is W7 or W2K8R2" );
+
+      CardEndTransaction( );
+
+      // The OS is W7 or W2K8R2
+      HMODULE hDll = NULL;
+      LRESULT lRes = GSC_OK;
+      LRESULT (WINAPI *ptr_SetUITitles) (WCHAR*, WCHAR*);
+      LRESULT (WINAPI *ptr_AuthenticateUserCard) ();
+
+      // Load DLL
+      hDll = LoadLibraryA("GemSelCert.dll");
+      Log::log( "Token::verifyPinWithBio - load lib" );
+
+      if( 0 != hDll )
+      {
+         // Set UI Titles
+         ptr_SetUITitles = (LRESULT (WINAPI *) (WCHAR*, WCHAR*))GetProcAddress(hDll,"SetUITitles");
+         if( NULL != ptr_SetUITitles )
+         {
+            ptr_SetUITitles(L"Smartcard Security", L"User authentication");
+            Log::log( "Token::verifyPinWithBio - ptr_SetUITitles" );
+
+            // Authenticate Card User
+            ptr_AuthenticateUserCard = (LRESULT (WINAPI *)())GetProcAddress(hDll,"AuthenticateUserCard");
+            if( NULL != ptr_AuthenticateUserCard )
+            {
+               lRes = ptr_AuthenticateUserCard();
+               Log::log( "Token::verifyPinWithBio - ptr_AuthenticateUserCard" );
+
+               switch(lRes)
+               {
+               case GSC_OK:
+                  rv = CKR_OK;
+                  Log::log( "Token::verifyPinWithBio - CKR_OK" );
+                  break;
+
+               case GSC_CANCEL:
+                  rv = CKR_FUNCTION_CANCELED;
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_CANCELED" );
+                  break;
+
+               case GSC_NO_CERT:
+                  rv = CKR_KEY_NEEDED;
+                  Log::log( "Token::verifyPinWithBio - CKR_KEY_NEEDED" );
+                  break;
+
+               case GSC_NO_CARD:
+                  rv = CKR_TOKEN_NOT_RECOGNIZED;
+                  Log::log( "Token::verifyPinWithBio - CKR_TOKEN_NOT_RECOGNIZED" );
+                  break;
+
+               case GSC_WRONG_PIN:
+                  rv = CKR_PIN_INCORRECT;
+                  Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+                  break;
+
+               case GSC_READ_CARD:
+                  rv = CKR_FUNCTION_FAILED;
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+                  break;
+
+               case GSC_WRITE_CARD:
+                  rv = CKR_FUNCTION_FAILED;
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+                  break;
+
+               default:
+                  Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+                  rv = CKR_FUNCTION_FAILED;
+                  break;
+               }
+            }
+         }
+
+         // Release DLL
+         FreeLibrary(hDll);
+         Log::log( "Token::verifyPinWithBio - FreeLibrary" );
+      }
+
+      CardBeginTransaction( );
+   }
+   // The OS is Vista or XP
+   else
+   {
+      Log::log( "Token::verifyPinWithBio - Os is Vista or XP" );
+
+      CBioMan* pBioMan = NULL;
+      DWORD dwRes = BIO_ERR_NOT_SUPPORTED;
+
+      // Init BioMan helper
+      pBioMan = new CBioMan( );
+      Log::log( "Token::verifyPinWithBio - new" );
+      pBioMan->Connect( this->_mscm );
+      Log::log( "Token::verifyPinWithBio - connect" );
+
+      // Biometrics Verification
+      dwRes = pBioMan->VerifyBio( );
+      Log::log( "Token::verifyPinWithBio - verify bio" );
+
+      delete pBioMan;
+      Log::log( "Token::verifyPinWithBio - delete" );
+
+      // Error ?
+      switch( dwRes )
+      {
+      case BIO_ERR_SUCCESS:
+         Log::log( "Token::verifyPinWithBio - CKR_OK" );
+         rv = CKR_OK;
+         break;
+
+      case BIO_ERR_NO_CARD:
+         Log::log( "Token::verifyPinWithBio - CKR_TOKEN_NOT_PRESENT" );
+         rv = CKR_TOKEN_NOT_PRESENT;
+         break;
+
+      case BIO_ERR_NOT_SUPPORTED:
+      case BIO_ERR_NO_FINGER:
+         Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_NOT_SUPPORTED" );
+         //this->_mscm->VerifyPin( CARD_ROLE_USER, pin );
+         rv = CKR_FUNCTION_NOT_SUPPORTED; //CKR_OK;
+         break;
+
+      case BIO_ERR_BIO_NOT_CHECKED:
+      case BIO_ERR_PIN_NOT_CHECKED:
+         Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+         rv = CKR_PIN_INCORRECT;
+         break;
+
+      case BIO_ERR_BIO_LAST:
+      case BIO_ERR_PIN_LAST:
+         Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+         rv = CKR_PIN_INCORRECT;
+         break;
+
+      case BIO_ERR_BLOCKED:
+         Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+         rv = CKR_PIN_INCORRECT;
+         break;
+
+      case BIO_ERR_ABORT:
+         Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+         rv = CKR_FUNCTION_FAILED;
+         break;
+
+      default:
+         Log::log( "Token::verifyPinWithBio - CKR_GENERAL_ERROR" );
+         rv = CKR_GENERAL_ERROR;
+         break;
+      }
+   }
+#endif
+
+   Log::log( "Token::verifyPinWithBio - <END>" );
+
+   return rv;
+}
+
+
+/*
+*/
+void Token::getCardConfiguration( BYTE& a_bMode, BYTE &a_bTypePIN )
+{
+   a_bMode = UVM_PIN_ONLY;
+   a_bTypePIN = PIN_TYPE_REGULAR;
+
+   u1Array* ba = new u1Array( 0 );
+
+   try
+   {
+      ba = _mscm->GetCardProperty( CARD_PROPERTY_PIN_INFO_EX, CARD_ROLE_USER );
+
+      DWORD dwFlagsEx = (DWORD)(
+         ba->GetBuffer( )[ 12 ] +
+         ( ( ba->GetBuffer( )[ 13 ] ) << 8 ) +
+         ( ( ba->GetBuffer( )[ 14 ] ) << 16 ) +
+         ( ( ba->GetBuffer( )[ 15 ] ) << 24 )
+         );
+      Log::log( "Token::getCardMode - dwFlagsEx <%#08x>", dwFlagsEx );
+
+      WORD wActiveMode = (WORD)( ba->GetBuffer( )[ 12 ] + ( ( ba->GetBuffer( )[ 13 ] ) << 8 ) );
+      Log::log( "Token::getCardMode - Active mode <%ld>", wActiveMode );
+
+      a_bMode = (BYTE)wActiveMode;
+
+      a_bTypePIN = (BYTE)ba->GetBuffer( )[ 0 ];
+   }
+   catch( ... )
+   {
+      Log::log( "Token::getCardMode - PIN_INFO_EX not supported - Default values used" );
+      a_bMode = UVM_PIN_ONLY;
+      a_bTypePIN = PIN_TYPE_REGULAR;
+   }
+
+   delete ba;
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,251 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_token_h
+#define _include_token_h
+
+#include <memory>
+#include <string>
+#include <list>
+#include <map>
+#include "cardmoduleservice.h"
+#include "rsapublickeyobject.h"
+#include "rsaprivatekeyobject.h"
+#include "x509pubkeycertobject.h"
+#include "cr_rsa.h"
+
+// This class represents the data in the card/token
+
+#define FILE_TYPE_RAW_CERT          0
+#define FILE_TYPE_DATA              1
+#define FILE_TYPE_CERT              2
+#define FILE_TYPE_SECRETKEY         3
+#define FILE_TYPE_PUBLICKEY         4
+#define FILE_TYPE_PRIVATEKEY        5
+
+#define CARD_ROLE_EVERYONE      0x00
+#define CARD_ROLE_USER          0x01
+#define CARD_ROLE_ADMIN         0x02
+
+#define CARD_PERMISSION_READ    0x04
+#define CARD_PERMISSION_WRITE   0x02
+#define CARD_PERMISSION_EXECUTE 0x01
+
+#define KEYSPEC_KEYEXCHANGE  0x01
+#define KEYSPEC_SIGNATURE    0x02
+
+#define KEY_TAG_UNKNOWN         0x00
+#define KEY_TAG_EXPONENT        0x01
+#define KEY_TAG_MODULUS         0x02
+#define KEY_TAG_KEYSPEC         0x03
+#define KEY_TAG_MINBITLEN       0x04
+#define KEY_TAG_MAXBITLEN       0x05
+#define KEY_TAG_DEFAULTBITLEN   0x06
+#define KEY_TAG_INCREMENTBITLEN 0x07
+
+#define MODE_CHANGE_PIN         0x00
+#define MODE_UNBLOCK_PIN        0x01
+
+#define MAX_USER_PIN_TRIES      0x05
+#define MAX_SO_PIN_TRIES        0x05
+
+#define MIN_PIN_LEN             4
+#define MAX_PIN_LEN             24
+
+#define RSA_KEY_MIN_LENGTH 512
+#define RSA_KEY_MAX_LENGTH 2048
+
+// Constants defining layout of the records in cmapfile
+#define SIZE_CONTAINERMAPRECORD 86
+#define IDX_GUID_INFO 0
+#define IDX_FLAGS 80
+#define IDX_SIG_KEY_SIZE 82
+#define IDX_EXC_KEY_SIZE 84
+
+// Helper structs used when sync'ing CAPI containers
+// against P11 data.
+
+struct KeyPair
+{
+    KeyPair() : _checkValue(0), _fP11PrivKeyExists(false), _fP11CertExists(false) {}
+
+    u1Array _publicExponent;
+    u1Array _modulus;
+    u8 _checkValue;
+    u1Array _cert;
+    string _certName;
+    bool _fP11PrivKeyExists;
+    bool _fP11CertExists;
+};
+
+struct ContainerInfo
+{
+    ContainerInfo() : _cmapEntry(false) {}
+
+    bool _cmapEntry;        // True if it represents a valid entry in cmapfile
+    KeyPair _signKP;
+    KeyPair _exchKP;
+};
+
+class CardCache;
+
+class Token {
+
+private:
+    CardModuleService*      _mscm;
+
+    bool                    _initialized;
+    bool                    _supportGarbageCollection;
+    vector<StorageObject*>  _objects;
+    vector<string>          _toDelete;          // List of files to be deleted at next login
+    CardCache *             _cardCache;
+    unsigned long           _cardCfTimer;       // Timer indicating when _cardCf was last known to be up-to-date
+    CK_ULONG                _cardCf;            // Current state from \cardcf
+    CK_ULONG                _publCardCf;        // Reflects state of public cached objects
+    CK_ULONG                _privCardCf;        // Reflects state of private cached objects
+    CK_ULONG                _cacheCardCf;       // Reflects state of card cache (_cardCache)
+
+    bool                    _fPinChanged;
+    bool                    _fContainerChanged;
+    bool                    _fFileChanged;
+
+public:
+    CK_BBOOL                _version;
+    CK_TOKEN_INFO           _tokenInfo;
+    CK_ULONG                _roleLogged;
+    //bool m_isPinExternal;
+    bool m_isPinPadSupported;
+
+public:
+    Token(std::string* reader);
+    ~Token();
+
+    CardModuleService* /*const*/ GetMiniDriverService( void ) { return _mscm; };
+
+    void Clear();
+    void BeginTransaction();
+    void EndTransaction();
+    void CardBeginTransaction();
+    void CardEndTransaction();
+    void ManageGC();
+
+    CK_RV Login(CK_ULONG userType,u1Array* pin);
+    CK_RV Logout();
+    CK_RV GenerateRandom(CK_BYTE_PTR randomData,CK_ULONG len);
+    CK_RV AddObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV AddPrivateKeyObject(auto_ptr<StorageObject> & stobj,CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV AddCertificateObject(auto_ptr<StorageObject> & stobj,CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV DeleteObject(CK_OBJECT_HANDLE hObject);
+    CK_ULONG FindObjects(Session* session,CK_OBJECT_HANDLE_PTR phObject,
+                         CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount);
+
+    CK_RV GetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    CK_RV SetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+
+    CK_RV GenerateKeyPair(auto_ptr<StorageObject> & stobjRsaPub, auto_ptr<StorageObject> & stobjRsaPriv,
+                          CK_OBJECT_HANDLE_PTR phPubKey,CK_OBJECT_HANDLE_PTR phPrivKey);
+
+    CK_RV GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object);
+
+    CK_RV Sign(StorageObject* privObj,u1Array* dataToSign,CK_ULONG mechanism,CK_BYTE_PTR pSignature);
+    CK_RV Decrypt(StorageObject* privObj,u1Array* dataToDecrypt,CK_ULONG mechanism,CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+    CK_RV Verify(StorageObject* pubObj,u1Array* dataToVerify,CK_ULONG mechanism,u1Array* signature);
+    CK_RV Encrypt(StorageObject* pubObj,u1Array* dataToEncrypt,CK_ULONG mechanism,CK_BYTE_PTR pEncryptedData);
+
+    CK_RV InitToken(u1Array* pin,u1Array* label);
+    CK_RV InitPIN(u1Array* soPIN,u1Array* userPIN);
+    CK_RV SetPIN(u1Array* oldPIN,u1Array* newPIN);
+
+    bool isAuthenticated( void );
+    bool isSSO( void );
+
+private:
+
+   void getCardConfiguration( BYTE& a_bMode, BYTE &a_bTypePIN );
+   BYTE howToAuthenticate( BYTE bPinLen );
+   bool isPinPadSupported( void );
+   bool isPinExternalSupported( void );
+   CK_RV verifyPinWithPinPad( void );
+   CK_RV verifyPinWithBio( void /*Marshaller::u1Array *pin*/ );
+   DWORD m_dwIoctlVerifyPIN;
+
+   std::string m_sReaderName;
+    void Initialize();
+    void Resynchronize();
+    CK_RV AuthenticateUser(u1Array* pin);
+    CK_RV AuthenticateAdmin(u1Array* key);
+    void CreateDirIfNotPresent(std::string* parent,std::string* dir,u1Array* acls);
+    bool IsInitialized();
+    void PopulateDefaultTokenInfo();
+    void SerializeTokenInfo();
+    void DeserializeTokenInfo();
+    CK_BYTE GetAvailableContainerIndex(u1Array const & cmapContents);
+    CK_BYTE GetContainerForCert(u1Array const & cmapContents, u8 checkValue, u1 * keySpec);
+    CK_BYTE GetContainerForPrivateKey(u1Array const & cmapContents, u8 checkValue, u1 * keySpec);
+
+    auto_ptr<u1Array> UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,string const & contName);
+    auto_ptr<u1Array> UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,u4 keySize,u1 keySpec,
+                                 CK_BBOOL isDefault, string const & contName);
+
+    vector <PrivateKeyObject*> FindPrivateKeys(vector<StorageObject*> const & objects, u8 checkValue);
+    PrivateKeyObject* FindPrivateKey(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec);
+    vector <CertificateObject*> FindCertificates(vector<StorageObject*> const & objects, u8 checkValue);
+    CertificateObject* FindCertificate(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec);
+
+    u1Array* PadRSAPKCS1v15(u1Array* dataToSign,CK_ULONG modulusLen);
+    u1Array* PadRSAX509(u1Array* dataToSign,CK_ULONG modulusLen);
+    u1Array* EncodeHashForSigning(u1Array* hashedData,CK_ULONG modulusLen,CK_ULONG hashAlgo);
+
+    CK_BBOOL IsSynchronized();
+    void SynchronizeCertificates(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap);
+    void SynchronizePrivateKeys(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap);
+    void PrepareCertAttributesFromRawData(X509PubKeyCertObject* certObject);
+    bool PerformDeferredDelete();
+    string FindFreeFileName(StorageObject* object);
+    CK_RV WriteObject(StorageObject* object);
+
+    void ReadAndPopulateObjects(vector<StorageObject*> & objects, vector<string> & toDelete,
+                                std::string const & prefix, map<int, ContainerInfo> & contMap);
+    void SynchronizePublicObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap);
+    void SynchronizePrivateObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap);
+    void BuildContainerInfoMap(map<int, ContainerInfo> & contMap);
+    void DeleteCMapRecord(CK_BYTE ctrdIdx);
+    void RemoveKeyFromCMapRecord(CK_BYTE ctrIndex, u1 keySpec);
+    void SetDefaultContainer(u1Array & contents, CK_BYTE ctrIndex);
+    u1Array* ComputeCryptogram(u1Array* challenge,u1Array* pin);
+    CK_RV VerifyRSAPKCS1v15(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen);
+    CK_RV VerifyRSAX509(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen);
+    CK_RV VerifyHash(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen,CK_ULONG hashAlgo);
+
+    static CK_RV DoPINValidityChecks(u1Array* pin, bool fCheckCharaceters = true);
+    s4 RegisterStorageObject(StorageObject * object);
+    void UnregisterStorageObject(StorageObject * object);
+    auto_ptr<u1Array> ReadCertificateFile(string const & path);
+    void RegisterPinUpdate();
+    void RegisterContainerUpdate();
+    void RegisterFileUpdate();
+    //void CheckAvailableSpace();
+    StorageObject * GetObject(CK_OBJECT_HANDLE hObject);
+
+};
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,308 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "secretkeyobject.h"
+
+SecretKeyObject::SecretKeyObject() : KeyObject()
+{
+   this->_sensitive        = CK_FALSE;
+   this->_encrypt          = CK_FALSE;
+   this->_decrypt          = CK_FALSE;
+   this->_sign             = CK_FALSE;
+   this->_verify           = CK_FALSE;
+   this->_wrap             = CK_FALSE;
+   this->_unwrap           = CK_FALSE;
+   this->_extractable      = CK_FALSE;
+   this->_alwaysSensitive  = CK_FALSE;
+   this->_neverExtractable = CK_FALSE;
+   this->_checkSum         = NULL_PTR;
+   this->_wrapWithTrusted  = CK_FALSE;
+   this->_trusted          = CK_FALSE;
+
+   this->_value            = NULL_PTR;
+   this->_valueLength      = 0;
+
+   this->_class            = CKO_SECRET_KEY;
+}
+
+SecretKeyObject::~SecretKeyObject(){
+
+   if(this->_value != NULL_PTR){
+      delete this->_value;
+   }
+}
+
+CK_BBOOL SecretKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+   switch(attribute.type){
+
+        case CKA_SENSITIVE:
+           return (this->_sensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ENCRYPT:
+           return (this->_encrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_DECRYPT:
+           return (this->_decrypt == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_SIGN:
+           return (this->_sign == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VERIFY:
+           return (this->_verify == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_UNWRAP:
+           return (this->_unwrap == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_EXTRACTABLE:
+           return (this->_extractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_ALWAYS_SENSITIVE:
+           return (this->_alwaysSensitive == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_NEVER_EXTRACTABLE:
+           return (this->_neverExtractable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_CHECK_VALUE:
+           return Util::CompareU1Arrays(this->_checkSum,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_WRAP_WITH_TRUSTED:
+           return (this->_wrapWithTrusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_TRUSTED:
+           return (this->_trusted == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_VALUE:
+           return Util::CompareU1Arrays(this->_value,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_VALUE_LEN:
+           return (this->_valueLength == *(CK_ULONG*)attribute.pValue);
+
+        default:
+           return KeyObject::Compare(attribute);
+   }
+}
+
+CK_RV SecretKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   switch(attribute->type)
+   {
+   case CKA_SENSITIVE:
+      return StorageObject::PutBBoolInAttribute(this->_sensitive,attribute);
+
+   case CKA_ENCRYPT:
+      return StorageObject::PutBBoolInAttribute(this->_encrypt,attribute);
+
+   case CKA_DECRYPT:
+      return StorageObject::PutBBoolInAttribute(this->_decrypt,attribute);
+
+   case CKA_SIGN:
+      return StorageObject::PutBBoolInAttribute(this->_sign,attribute);
+
+   case CKA_VERIFY:
+      return StorageObject::PutBBoolInAttribute(this->_verify,attribute);
+
+   case CKA_UNWRAP:
+      return StorageObject::PutBBoolInAttribute(this->_unwrap,attribute);
+
+   case CKA_EXTRACTABLE:
+      return StorageObject::PutBBoolInAttribute(this->_extractable,attribute);
+
+   case CKA_ALWAYS_SENSITIVE:
+      return StorageObject::PutBBoolInAttribute(this->_alwaysSensitive,attribute);
+
+   case CKA_NEVER_EXTRACTABLE:
+      return StorageObject::PutBBoolInAttribute(this->_neverExtractable,attribute);
+
+   case CKA_CHECK_VALUE:
+      return StorageObject::PutU1ArrayInAttribute(this->_checkSum,attribute);
+
+   case CKA_WRAP_WITH_TRUSTED:
+      return StorageObject::PutBBoolInAttribute(this->_wrapWithTrusted,attribute);
+
+   case CKA_TRUSTED:
+      return StorageObject::PutBBoolInAttribute(this->_trusted,attribute);
+
+   case CKA_VALUE:
+      if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+         attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+         return CKR_ATTRIBUTE_SENSITIVE;
+      }
+      return StorageObject::PutU1ArrayInAttribute(this->_value,attribute);
+
+   case CKA_VALUE_LEN:
+      return StorageObject::PutULongInAttribute(this->_valueLength,attribute);
+
+   default:
+      return KeyObject::GetAttribute(attribute);
+   }
+}
+
+CK_RV SecretKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   switch(attribute.type)
+   {
+   case CKA_SENSITIVE:
+      this->_sensitive = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_ENCRYPT:
+      this->_encrypt = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_DECRYPT:
+      this->_decrypt = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_SIGN:
+      this->_sign = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_VERIFY:
+      this->_verify = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_UNWRAP:
+      this->_unwrap = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_EXTRACTABLE:
+      this->_extractable = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_ALWAYS_SENSITIVE:
+      this->_alwaysSensitive = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_NEVER_EXTRACTABLE:
+      this->_neverExtractable = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_CHECK_VALUE:
+      if(this->_checkSum != NULL_PTR){
+         delete this->_checkSum;
+      }
+      this->_checkSum = new u1Array(attribute.ulValueLen);
+      memcpy((u1*)this->_checkSum->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_WRAP_WITH_TRUSTED:
+      this->_wrapWithTrusted = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_TRUSTED:
+      this->_trusted = *(CK_BBOOL*)attribute.pValue;
+      break;
+
+   case CKA_VALUE:
+      if(this->_value != NULL_PTR){
+         delete this->_value;
+      }
+      this->_value = new u1Array(attribute.ulValueLen);
+      memcpy((u1*)this->_value->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+      break;
+
+   case CKA_VALUE_LEN:
+      this->_valueLength = *(CK_ULONG*)attribute.pValue;
+      break;
+
+   default:
+      return KeyObject::SetAttribute(attribute,objCreation);
+   }
+
+   return CKR_OK;
+}
+
+void SecretKeyObject::Serialize(std::vector<u1> *to)
+{
+   KeyObject::Serialize(to);
+
+   Util::PushBBoolInVector(to,this->_sensitive);
+
+   Util::PushBBoolInVector(to,this->_encrypt);
+
+   Util::PushBBoolInVector(to,this->_decrypt);
+
+   Util::PushBBoolInVector(to,this->_sign);
+
+   Util::PushBBoolInVector(to,this->_verify);
+
+   Util::PushBBoolInVector(to,this->_unwrap);
+
+   Util::PushBBoolInVector(to,this->_extractable);
+
+   Util::PushBBoolInVector(to,this->_alwaysSensitive);
+
+   Util::PushBBoolInVector(to,this->_neverExtractable);
+
+   Util::PushByteArrayInVector(to,this->_checkSum);
+
+   Util::PushBBoolInVector(to,this->_wrapWithTrusted);
+
+   Util::PushBBoolInVector(to,this->_trusted);
+
+   Util::PushByteArrayInVector(to,this->_value);
+
+   Util::PushULongInVector(to,this->_valueLength);
+}
+
+void SecretKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+   KeyObject::Deserialize(from,idx);
+
+   this->_sensitive = Util::ReadBBoolFromVector(from,idx);
+
+   this->_encrypt = Util::ReadBBoolFromVector(from,idx);
+
+   this->_decrypt = Util::ReadBBoolFromVector(from,idx);
+
+   this->_sign = Util::ReadBBoolFromVector(from,idx);
+
+   this->_verify = Util::ReadBBoolFromVector(from,idx);
+
+   this->_unwrap = Util::ReadBBoolFromVector(from,idx);
+
+   this->_extractable = Util::ReadBBoolFromVector(from,idx);
+
+   this->_alwaysSensitive = Util::ReadBBoolFromVector(from,idx);
+
+   this->_neverExtractable = Util::ReadBBoolFromVector(from,idx);
+
+   this->_checkSum = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_wrapWithTrusted = Util::ReadBBoolFromVector(from,idx);
+
+   this->_trusted = Util::ReadBBoolFromVector(from,idx);
+
+   this->_value = Util::ReadByteArrayFromVector(from,idx);
+
+   this->_valueLength = Util::ReadULongFromVector(from,idx);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,61 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_secretkeyobject_h
+#define _include_secretkeyobject_h
+
+#include "keyobject.h"
+
+class SecretKeyObject : public KeyObject
+{
+
+public:
+    CK_BBOOL    _sensitive;
+    CK_BBOOL    _encrypt;
+    CK_BBOOL    _decrypt;
+    CK_BBOOL    _sign;
+    CK_BBOOL    _verify;
+    CK_BBOOL    _wrap;
+    CK_BBOOL    _unwrap;
+    CK_BBOOL    _extractable;
+    CK_BBOOL    _alwaysSensitive;
+    CK_BBOOL    _neverExtractable;
+    u1Array*    _checkSum;
+    CK_BBOOL    _wrapWithTrusted;
+    CK_BBOOL    _trusted;
+
+    u1Array*    _value;
+    CK_ULONG    _valueLength;
+
+public:
+    SecretKeyObject();
+    ~SecretKeyObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,534 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include <winscard.h>      // inclusion needed for linux
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "template.h"
+#include "session.h"
+#include "slot.h"
+
+Session::Session(CK_BBOOL isReadWrite){
+    this->_isReadWrite    = isReadWrite;
+    this->_searchTempl    = NULL_PTR;
+    this->_isSearchActive = CK_FALSE;
+
+    this->_digest         = NULL_PTR;
+    this->_digestRSA      = NULL_PTR;
+    this->_digestRSAVerification = NULL_PTR;
+
+    this->_isDigestActive = CK_FALSE;
+    this->_isDigestRSAActive = CK_FALSE;
+    this->_isDigestRSAVerificationActive = CK_FALSE;
+
+    this->_signature = NULL_PTR;
+    this->_decryption     = NULL_PTR;
+    this->_encryption     = NULL_PTR;
+    this->_verification   = NULL_PTR;
+
+    this->_soPIN     = NULL_PTR;
+
+    this->_accumulatedDataToSign = NULL_PTR;
+    this->_accumulatedDataToVerify = NULL_PTR;
+
+    _objects.clear();
+    _sessionObjectsReturnedInSearch.clear();
+    _tokenObjectsReturnedInSearch.clear();
+}
+
+Session::~Session(){
+
+    for(size_t i = 0; i < _objects.size(); i++){
+        delete _objects[i];
+        _objects[i] = NULL_PTR;
+    }
+
+    if(this->_digest != NULL_PTR){
+        delete this->_digest;
+    }
+
+    if(this->_digestRSA != NULL_PTR){
+        delete this->_digestRSA;
+    }
+
+    if(this->_digestRSAVerification != NULL_PTR){
+        delete this->_digestRSAVerification;
+    }
+
+    if(this->_signature != NULL_PTR){
+        delete this->_signature;
+    }
+
+    if(this->_decryption != NULL_PTR){
+        delete this->_decryption;
+    }
+
+    if(this->_encryption != NULL_PTR){
+        delete this->_encryption;
+    }
+
+    if(this->_verification != NULL_PTR){
+        delete this->_verification;
+    }
+
+    if(this->_soPIN != NULL_PTR){
+        delete this->_soPIN;
+    }
+
+    if(this->_accumulatedDataToSign != NULL_PTR){
+        delete this->_accumulatedDataToSign;
+    }
+
+    if(this->_accumulatedDataToVerify != NULL_PTR){
+        delete this->_accumulatedDataToVerify;
+    }
+}
+
+void Session::SetSearchTemplate(Template* templ)
+{
+    PKCS11_ASSERT(this->_isSearchActive == CK_FALSE);
+
+    this->_searchTempl = templ;
+    this->_isSearchActive = CK_TRUE;
+
+    _tokenObjectsReturnedInSearch.clear();
+    _sessionObjectsReturnedInSearch.clear();
+}
+
+void Session::RemoveSearchTemplate()
+{
+    if(this->_searchTempl != NULL_PTR){
+        delete this->_searchTempl;
+        this->_searchTempl = NULL_PTR;
+    }
+
+    this->_isSearchActive = CK_FALSE;
+}
+
+void Session::UpdateState(CK_ULONG roleLogged)
+{
+    if(this->_isReadWrite)
+    {
+        switch(roleLogged)
+        {
+            case CKU_NONE:
+                this->_state = CKS_RW_PUBLIC_SESSION;
+                break;
+
+            case CKU_SO:
+                this->_state = CKS_RW_SO_FUNCTIONS;
+                break;
+
+            case CKU_USER:
+                this->_state = CKS_RW_USER_FUNCTIONS;
+                break;
+        }
+    }
+    else
+    {
+        switch(roleLogged)
+        {
+            case CKU_NONE:
+                this->_state = CKS_RO_PUBLIC_SESSION;
+                break;
+
+            case CKU_USER:
+                this->_state = CKS_RO_USER_FUNCTIONS;
+                break;
+        }
+    }
+}
+
+CK_BBOOL Session::IsSearchActive()
+{
+    return this->_isSearchActive;
+}
+
+void Session::SetId(CK_ULONG id)
+{
+    this->_id = id;
+}
+
+void Session::SetSlot(Slot* slot)
+{
+    this->_slot = slot;
+}
+
+CK_ULONG Session::MakeObjectHandle(CK_ULONG idx)
+{
+     CK_ULONG objHandle = CO_SESSION_OBJECT | idx;
+     objHandle = (this->_id << 16) | objHandle;
+
+     return objHandle;
+}
+
+CK_ULONG Session::FindObjects(CK_ULONG idx,CK_OBJECT_HANDLE_PTR phObject,
+                              CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount)
+{
+
+    PKCS11_ASSERT(this->_isSearchActive);
+
+    for(CK_LONG i=0;i<static_cast<CK_LONG>(_objects.size()) && (idx < ulMaxObjectCount);i++){
+
+        if(this->_objects[i] == NULL_PTR){
+            continue;
+        }
+
+        if(this->_sessionObjectsReturnedInSearch[i] == CK_TRUE){
+            continue;
+        }
+
+        if((this->_objects[i]->_private == CK_TRUE) &&
+            (this->_slot->_token->_roleLogged != CKU_USER))
+        {
+            continue;
+        }
+
+        if(this->_searchTempl == NULL_PTR){
+            phObject[idx++] = MakeObjectHandle(i+1);
+            *pulObjectCount = *pulObjectCount + 1;
+            this->_sessionObjectsReturnedInSearch[i] = CK_TRUE;
+        }
+        else{
+            CK_BBOOL match = CK_TRUE;
+
+            vector<CK_ATTRIBUTE> attributes = this->_searchTempl->_attributes;
+            for(CK_ULONG a=0;a<attributes.size();a++){
+                if(this->_objects[i]->Compare(attributes.at(a)) == CK_FALSE){
+                    match = CK_FALSE;
+                    break;
+                }
+            }
+
+            if(match == CK_TRUE){
+                phObject[idx++] = MakeObjectHandle(i+1);
+                *pulObjectCount = *pulObjectCount + 1;
+                this->_sessionObjectsReturnedInSearch[i] = CK_TRUE;
+            }
+
+        }
+    }
+
+    return idx;
+}
+
+CK_RV Session::AddObject(StorageObject* obj,CK_OBJECT_HANDLE_PTR phObject)
+{
+    for(CK_ULONG i = 0; i < static_cast<CK_ULONG>(_objects.size()); i++)
+    {
+        if(this->_objects[i] == NULL_PTR)
+        {
+            this->_objects[i] = obj;
+            *phObject = MakeObjectHandle(i+1);
+
+            return CKR_OK;
+        }
+    }
+
+    _objects.push_back(obj);
+
+    *phObject = MakeObjectHandle(static_cast<CK_ULONG>(_objects.size()));
+
+    return CKR_OK;
+}
+
+CK_RV Session::DeleteObject(CK_OBJECT_HANDLE hObject)
+{
+    // object handle also encodes the session to which it
+    // belongs, it is also possible to delete object of one
+    // session from other
+
+    CK_SESSION_HANDLE encodedSId = ((hObject >> 16) & 0x0000FFFF);
+
+    if ((encodedSId < 1) || (encodedSId >= _slot->_sessions.size())){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    if(this->_slot->_sessions[encodedSId] == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    // determine the index
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+    if(idx < 1 || idx > static_cast<CK_LONG>(_slot->_sessions[encodedSId]->_objects.size()))
+        return CKR_OBJECT_HANDLE_INVALID;
+
+    StorageObject* obj = this->_slot->_sessions[encodedSId]->_objects[idx-1];
+
+    if(obj == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    // if this is a readonly session and
+    // user is not logged then only public session objects
+    // can be created
+    if(this->_isReadWrite == CK_FALSE)
+    {
+        if(obj->_tokenObject)
+            return CKR_SESSION_READ_ONLY;
+    }
+
+    if ((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+        return CKR_USER_NOT_LOGGED_IN;
+    }
+
+    delete obj;
+
+    this->_slot->_sessions[encodedSId]->_objects[idx-1] = NULL_PTR;
+
+    return CKR_OK;
+}
+
+CK_RV Session::GetAttributeValue(CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount)
+{
+    CK_RV rv  = CKR_OK;
+    CK_RV arv = CKR_OK;
+
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+    //  lets see if the object handle provided is a correct handle or not
+    if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || (this->_objects[idx-1] == NULL_PTR)){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    StorageObject* obj = this->_objects[idx-1];
+
+    if((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+        for(u4 i=0;i<ulCount;i++){
+            pTemplate[i].ulValueLen = (CK_ULONG)-1;
+        }
+        return CKR_USER_NOT_LOGGED_IN;
+    }
+
+    for(u4 i=0;i<ulCount;i++){
+        rv = obj->GetAttribute(&pTemplate[i]);
+        if(rv != CKR_OK){
+            arv = rv;
+        }
+    }
+
+    return arv;
+}
+
+CK_RV Session::SetAttributeValue(CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount)
+{
+    CK_RV rv  = CKR_OK;
+    CK_RV arv = CKR_OK;
+
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+    //  lets see if the object handle provided is a correct handle or not
+    if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || (this->_objects[idx-1] == NULL_PTR)){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    StorageObject* obj = this->_objects[idx-1];
+
+    if ((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+        return CKR_USER_NOT_LOGGED_IN;
+    }
+
+    for(u4 i=0;i<ulCount;i++){
+        rv = obj->SetAttribute(pTemplate[i],CK_FALSE);
+        if(rv != CKR_OK){
+            arv = rv;
+        }
+    }
+
+    return arv;
+}
+
+void Session::SetDigest(CDigest *digest)
+{
+    this->_digest = digest;
+    this->_isDigestActive = CK_TRUE;
+}
+
+void Session::RemoveDigest()
+{
+    if(this->_digest != NULL_PTR){
+        delete this->_digest;
+        this->_digest = NULL_PTR;
+    }
+
+    this->_isDigestActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestActive()
+{
+    return this->_isDigestActive;
+}
+
+void Session::SetDigestRSA(CDigest *digest)
+{
+    this->_digestRSA = digest;
+    this->_isDigestRSAActive = CK_TRUE;
+}
+
+void Session::RemoveDigestRSA()
+{
+    if(this->_digestRSA != NULL_PTR){
+        delete this->_digestRSA;
+        this->_digestRSA = NULL_PTR;
+    }
+
+    this->_isDigestRSAActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestRSAActive()
+{
+    return this->_isDigestRSAActive;
+}
+
+void Session::SetDigestRSAVerification(CDigest *digest)
+{
+    this->_digestRSAVerification = digest;
+    this->_isDigestRSAVerificationActive = CK_TRUE;
+}
+
+void Session::RemoveDigestRSAVerification()
+{
+    if(this->_digestRSAVerification != NULL_PTR){
+        delete this->_digestRSAVerification;
+        this->_digestRSAVerification = NULL_PTR;
+    }
+
+    this->_isDigestRSAVerificationActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestRSAVerificationActive()
+{
+    return this->_isDigestRSAVerificationActive;
+}
+
+CK_RV Session::GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object)
+{
+    if(hObject == 0){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    CK_SESSION_HANDLE encodedSId = ((hObject >> 16) & 0x0000FFFF);
+
+    if ((encodedSId < 1) || (encodedSId >= _slot->_sessions.size())){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    if(this->_slot->_sessions[encodedSId] == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    // determine the index
+    CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+    StorageObject* obj = this->_slot->_sessions[encodedSId]->_objects[idx-1];
+
+    if(obj == NULL_PTR){
+        return CKR_OBJECT_HANDLE_INVALID;
+    }
+
+    *object = obj;
+
+    return CKR_OK;
+}
+
+void Session::SetEncryptionOperation(CryptoOperation *encryption)
+{
+    this->_encryption = encryption;
+}
+
+void Session::RemoveEncryptionOperation()
+{
+    if(this->_encryption != NULL_PTR){
+        delete this->_encryption;
+    }
+
+    this->_encryption = NULL_PTR;
+}
+
+CK_BBOOL Session::IsEncryptionActive(){
+
+   return (this->_encryption != NULL_PTR);
+}
+
+void Session::SetVerificationOperation(CryptoOperation *verification)
+{
+    this->_verification = verification;
+}
+
+void Session::RemoveVerificationOperation()
+{
+    if(this->_verification != NULL_PTR){
+        delete this->_verification;
+    }
+
+    this->_verification = NULL_PTR;
+}
+
+CK_BBOOL Session::IsVerificationActive(){
+
+   return (this->_verification != NULL_PTR);
+}
+
+void Session::SetDecryptionOperation(CryptoOperation *decryption)
+{
+    this->_decryption = decryption;
+}
+
+void Session::RemoveDecryptionOperation()
+{
+    if(this->_decryption != NULL_PTR){
+        delete this->_decryption;
+    }
+
+    this->_decryption = NULL_PTR;
+}
+
+CK_BBOOL Session::IsDecryptionActive(){
+
+   return (this->_decryption != NULL_PTR);
+}
+
+void Session::SetSignatureOperation(CryptoOperation* signature)
+{
+    this->_signature = signature;
+}
+
+void Session::RemoveSignatureOperation()
+{
+    if(this->_signature != NULL_PTR){
+        delete this->_signature;
+    }
+
+    this->_signature = NULL_PTR;
+}
+
+CK_BBOOL Session::IsSignatureActive(){
+
+    return (this->_signature != NULL_PTR);
+
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,144 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_session_h
+#define _include_session_h
+
+#include "template.h"
+#include "digest.h"
+#include "storageobject.h"
+#include <map>
+
+class Slot;
+
+class CryptoOperation{
+    CK_ULONG            _mechanism;
+    StorageObject*      _object;
+
+public:
+    CryptoOperation(CK_ULONG mechanism,StorageObject* obj){
+        this->_mechanism = mechanism;
+        this->_object = obj;
+    }
+
+    ~CryptoOperation(){}
+
+public:
+    CK_ULONG    GetMechanism() { return this->_mechanism;}
+    StorageObject* GetObject() { return this->_object;}
+};
+
+class Session{
+
+public:
+    CK_BBOOL                _isReadWrite;
+    CK_ULONG                _state;
+    vector<StorageObject*>  _objects;
+    Template*               _searchTempl;
+    CDigest*                _digest;
+    CDigest*                _digestRSA;
+    CDigest*                _digestRSAVerification;
+
+    map<CK_ULONG, bool>     _sessionObjectsReturnedInSearch;
+    map<CK_ULONG, bool>     _tokenObjectsReturnedInSearch;
+
+    CryptoOperation*         _signature;
+    CryptoOperation*         _decryption;
+    CryptoOperation*         _verification;
+    CryptoOperation*         _encryption;
+
+    CK_BBOOL                _isSearchActive;
+    CK_BBOOL                _isDigestActive;
+    CK_BBOOL                _isDigestRSAActive;
+    CK_BBOOL                _isDigestRSAVerificationActive;
+
+    CK_ULONG                _id;
+    Slot*                   _slot;
+
+    u1Array*                _accumulatedDataToSign;
+    u1Array*                _accumulatedDataToVerify;
+
+
+    // Looks scary huh, the problem is that CardModule interface require
+    // cryptogram as part of ChangeReferenceData method whereas
+    // PKCS#11 first log SO in and then call InitPIN. InitPIN does not have any
+    // information about SO PIN so what we do here is to cache it momentarily.
+    // Basically during Login (as SO) we cache it and destroy it during closing
+    // of session
+    u1Array*                _soPIN;
+
+public:
+    Session(CK_BBOOL isReadWrite);
+    ~Session();
+
+    void SetSearchTemplate(Template* templ);
+    void RemoveSearchTemplate();
+
+    void SetDigest(CDigest* digest);
+    void RemoveDigest();
+
+    void SetEncryptionOperation(CryptoOperation* encryption);
+    void RemoveEncryptionOperation();
+    CK_BBOOL IsEncryptionActive();
+
+    void SetVerificationOperation(CryptoOperation* verification);
+    void RemoveVerificationOperation();
+    CK_BBOOL IsVerificationActive();
+
+    void SetDecryptionOperation(CryptoOperation* decryption);
+    void RemoveDecryptionOperation();
+    CK_BBOOL IsDecryptionActive();
+
+    void SetSignatureOperation(CryptoOperation* signature);
+    void RemoveSignatureOperation();
+    CK_BBOOL IsSignatureActive();
+
+    void SetDigestRSA(CDigest* digest);
+    void RemoveDigestRSA();
+
+    void SetDigestRSAVerification(CDigest* digest);
+    void RemoveDigestRSAVerification();
+
+    void UpdateState(CK_ULONG roleLogged);
+    CK_BBOOL IsSearchActive();
+    CK_BBOOL IsDigestActive();
+    CK_BBOOL IsDigestRSAActive();
+    CK_BBOOL IsDigestRSAVerificationActive();
+
+    CK_RV AddObject(StorageObject* object,CK_OBJECT_HANDLE_PTR phObject);
+    CK_RV DeleteObject(CK_OBJECT_HANDLE hObject);
+
+    CK_ULONG FindObjects(CK_ULONG idx,CK_OBJECT_HANDLE_PTR phObject,
+                         CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount);
+
+	CK_RV GetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    CK_RV SetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+
+    void SetId(CK_ULONG id);
+    void SetSlot(Slot* slot);
+
+    CK_RV GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object);
+
+private:
+    CK_ULONG MakeObjectHandle(CK_ULONG idx);
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,73 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "sha1.h"
+
+CSHA1::CSHA1(){
+    this->_hashValue     = (CK_BYTE_PTR)malloc(SHA1_HASH_LENGTH);
+    this->_workingBuffer = (CK_BYTE_PTR)malloc(SHA1_BLOCK_LENGTH);
+    this->_hashLength    = SHA1_HASH_LENGTH;
+    this->_blockLength   = SHA1_BLOCK_LENGTH;
+}
+
+CSHA1::~CSHA1(){
+}
+
+void CSHA1::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha1_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha1_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    algo_sha1_update(&ctx, data, SHA1_BLOCK_LENGTH);
+}
+
+void CSHA1::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha1_context ctx;
+
+    ctx.digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha1_starts(&ctx);
+    } else {
+        ctx.total[0] = counter;
+        ctx.total[1] = 0;
+    }
+
+    ctx.input = (u1*)malloc(SHA1_BLOCK_LENGTH);
+    memset(ctx.input,0,SHA1_BLOCK_LENGTH);
+
+    algo_sha1_update(&ctx, data, length);
+    algo_sha1_finish(&ctx);
+
+    free(ctx.input);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_sha1_h
+#define _include_sha1_h
+
+#include "MarshallerCfg.h"
+#include "algo_sha1.h"
+
+class CSHA1 : public CDigest
+{
+private:
+    void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+    void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+    CSHA1();
+    ~CSHA1();
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,78 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "sha256.h"
+
+CSHA256::CSHA256(){
+    this->_hashValue     = (CK_BYTE_PTR)malloc(SHA256_HASH_LENGTH);
+    this->_workingBuffer = (CK_BYTE_PTR)malloc(SHA256_BLOCK_LENGTH);
+    this->_hashLength    = SHA256_HASH_LENGTH;
+    this->_blockLength   = SHA256_BLOCK_LENGTH;
+}
+
+CSHA256::~CSHA256(){
+}
+
+void CSHA256::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha256_context* ctx = (algo_sha256_context*)malloc(sizeof(algo_sha256_context));
+
+    ctx->digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha256_starts(ctx);
+    } else {
+        ctx->total[0] = counter;
+        ctx->total[1] = 0;
+    }
+
+    algo_sha256_update(ctx, data, SHA256_BLOCK_LENGTH);
+
+    free((u1*)ctx);
+}
+
+void CSHA256::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+    algo_sha256_context* ctx = (algo_sha256_context*)malloc(sizeof(algo_sha256_context));
+
+    ctx->digest = (u4*)result;
+
+    if (counter == 0) {
+		algo_sha256_starts(ctx);
+    } else {
+        ctx->total[0] = counter;
+        ctx->total[1] = 0;
+    }
+
+    // allocate tempory working buffer
+    ctx->input = (u1*)malloc(SHA256_BLOCK_LENGTH);
+    memset(ctx->input, 0,SHA256_BLOCK_LENGTH);
+
+    // warning: algo_sha1_update must not throw any exception.
+    algo_sha256_update(ctx, data, length);
+    algo_sha256_finish(ctx);
+
+    free(ctx->input);
+    free((u1*)ctx);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_sha256_h
+#define _include_sha256_h
+
+#include "MarshallerCfg.h"
+#include "algo_sha256.h"
+
+class CSHA256 : public CDigest
+{
+private:
+    void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+    void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+    CSHA256();
+    ~CSHA256();
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,2836 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <winscard.h>
+#include "cardmoduleservice.h"
+
+#include <assert.h>
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "template.h"
+#include "digest.h"
+#include "sha1.h"
+#include "sha256.h"
+#include "md5.h"
+#include "session.h"
+#include "slot.h"
+#include "dataobject.h"
+#include "secretkeyobject.h"
+#include "rsaprivatekeyobject.h"
+#include "rsapublickeyobject.h"
+#include "x509pubkeycertobject.h"
+#include "application.h"
+#include "transaction.h"
+#include "log.h"
+#include "error.h"
+
+#ifdef _XCL_
+#include "xcl_utils.h"
+#endif // _XCL_
+
+CK_MECHANISM_TYPE MechanismList[] = {
+   CKM_RSA_PKCS_KEY_PAIR_GEN, // 0
+   CKM_RSA_PKCS,              // 1
+   CKM_RSA_X_509,             // 2
+   CKM_MD5_RSA_PKCS,          // 3
+   CKM_SHA1_RSA_PKCS,         // 4
+   CKM_SHA256_RSA_PKCS,       // 5
+#ifdef ENABLE_DIGEST
+   CKM_MD5,                   // 6
+   CKM_SHA_1,                 // 7
+   CKM_SHA256,                // 8
+#endif
+#ifdef ENABLE_SYMMETRIC
+   CKM_AES_KEY_GEN,           // 9
+   CKM_AES_ECB,               // 10
+   CKM_AES_CBC,               // 11
+   CKM_AES_CBC_PAD,           // 12
+   CKM_DES_KEY_GEN,           // 13
+   CKM_DES_ECB,               // 14
+   CKM_DES_CBC,               // 15
+   CKM_DES_CBC_PAD,           // 16
+   CKM_DES2_KEY_GEN,          // 17
+   CKM_DES3_KEY_GEN,          // 18
+   CKM_DES3_ECB,              // 19
+   CKM_DES3_CBC,              // 20
+   CKM_DES3_CBC_PAD           // 21
+#endif
+};
+
+CK_MECHANISM_INFO MechanismInfo[] = {
+   {/* 0 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_GENERATE_KEY_PAIR},
+#ifdef ENABLE_SYMMETRIC
+   {/* 1 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP},
+   {/* 2 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP},
+#else
+   {/* 1 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | /*CKF_SIGN_RECOVER |*/ CKF_VERIFY /*| CKF_VERIFY_RECOVER*/},
+   {/* 2 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_SIGN | /*CKF_SIGN_RECOVER |*/ CKF_VERIFY /*| CKF_VERIFY_RECOVER*/},
+#endif
+   {/* 3 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+   {/* 4 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+   {/* 5 */  RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+#ifdef ENABLE_DIGEST
+   {/* 6 */  0,0, CKF_SW | CKF_DIGEST},
+   {/* 7 */  0,0, CKF_SW | CKF_DIGEST},
+   {/* 8 */  0,0, CKF_SW | CKF_DIGEST},
+#endif
+#ifdef ENABLE_SYMMETRIC
+   {/* 9 */  16,32, CKF_HW | CKF_GENERATE},
+   {/* 10 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 11 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 12 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 13 */  0,0, CKF_HW | CKF_GENERATE},
+   {/* 14 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 15 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 16 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 17 */  0,0, CKF_HW | CKF_GENERATE},
+   {/* 18 */  0,0, CKF_HW | CKF_GENERATE},
+   {/* 19 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 20 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+   {/* 21 */  0,0, CKF_HW | CKF_ENCRYPT  | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}
+#endif
+};
+
+#define MAKE_SESSIONHANDLE(H,S)         (H | (S << 24))
+#define GET_SESSIONID(H)                (H & 0x00FFFFFF)
+#define GET_SLOTID(H)                   ((H & 0xFF000000) >> 24)
+
+//#define CHECK_IF_NULL_SESSION(A,S)      if(A->_sessions[S] == NULL_PTR){return CKR_SESSION_HANDLE_INVALID;}
+#define CHECK_IF_NULL_SESSION(A,S) try \
+   { \
+      if( A->_sessions.at( S ) == NULL_PTR ) \
+      { \
+         return CKR_SESSION_HANDLE_INVALID; \
+      } \
+   } \
+   catch( ... ) \
+   { \
+      return CKR_SESSION_HANDLE_INVALID; \
+   } \
+
+#define CHECK_IF_TOKEN_IS_PRESENT(S)    if(S->_token == NULL_PTR){return CKR_TOKEN_NOT_PRESENT;}
+
+Slot::Slot()
+{
+   // initialize the fields
+
+   CK_ULONG idx;
+
+   this->_token = NULL_PTR;
+   this->_readerName = NULL_PTR;
+
+   _sessions.resize(1,NULL_PTR);   // First element is dummy
+
+   // initialize this slot
+   this->_slotId = 0;
+   this->_slotInfo.firmwareVersion.major = 0;
+   this->_slotInfo.firmwareVersion.minor = 0;
+   this->_slotInfo.flags                 = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
+   this->_slotInfo.hardwareVersion.major = 0;
+   this->_slotInfo.hardwareVersion.minor = 0;
+
+   for(idx=0;idx<64;idx++)
+      this->_slotInfo.slotDescription[idx] = ' ';
+
+   this->_slotInfo.manufacturerID[0] = 'U';
+   this->_slotInfo.manufacturerID[1] = 'n';
+   this->_slotInfo.manufacturerID[2] = 'k';
+   this->_slotInfo.manufacturerID[3] = 'n';
+   this->_slotInfo.manufacturerID[4] = 'o';
+   this->_slotInfo.manufacturerID[5] = 'w';
+   this->_slotInfo.manufacturerID[6] = 'n';
+
+   for(idx=7;idx<32;idx++){
+      this->_slotInfo.manufacturerID[idx] = ' ';
+   }
+
+#ifdef INCLUDE_EVENTING
+   this->_tracker = NULL_PTR;
+   this->_event   = CK_FALSE;
+#endif
+
+}
+
+Slot::~Slot(){
+
+   if(this->_token != NULL_PTR)
+   {
+      delete this->_token;
+      this->_token = NULL_PTR;
+   }
+
+#ifdef INCLUDE_EVENTING
+   if(this->_tracker != NULL_PTR)
+   {
+      delete this->_tracker;
+      this->_tracker = NULL_PTR;
+   }
+#endif
+
+   if(this->_readerName != NULL_PTR)
+   {
+      delete this->_readerName;
+      this->_readerName = NULL_PTR;
+   }
+
+   // destroy all opened sessions
+   for(size_t i=1;i<_sessions.size();i++)
+   {
+      if( this->_sessions[i] != NULL_PTR)
+      {
+         delete this->_sessions[i];
+         this->_sessions[i] = NULL_PTR;
+      }
+   }
+}
+
+
+#ifdef INCLUDE_EVENTING
+
+void Slot::SetEvent(CK_BBOOL event)
+{
+   this->_event = event;
+}
+
+CK_BBOOL Slot::GetEvent()
+{
+   return this->_event;
+}
+
+void Slot::Clear()
+{
+   // close all the sessions when card is removed
+   this->CloseAllSessions();
+
+   if(this->_token != NULL_PTR)
+   {
+      delete this->_token;
+      this->_token = NULL_PTR;
+   }
+}
+
+#endif
+
+CK_RV Slot::GetInfo(CK_SLOT_INFO_PTR pInfo)
+{
+   CK_BYTE idx;
+
+   // Check Parameters
+   if(pInfo == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   for(idx=0;idx<64;idx++)
+   {
+      pInfo->slotDescription[idx] = this->_slotInfo.slotDescription[idx];
+   }
+
+   for(idx=0;idx<32;idx++)
+   {
+      pInfo->manufacturerID[idx]  = this->_slotInfo.manufacturerID[idx];
+   }
+
+   pInfo->hardwareVersion.major = this->_slotInfo.hardwareVersion.major;
+   pInfo->hardwareVersion.minor = this->_slotInfo.hardwareVersion.minor;
+   pInfo->firmwareVersion.major = this->_slotInfo.firmwareVersion.major;
+   pInfo->firmwareVersion.minor = this->_slotInfo.firmwareVersion.minor;
+
+   // it turns out that we need to dynamically poll if
+   // token is present or not. rest of the information should not
+   // change since we enumerated
+   SCARD_READERSTATE readerStates;
+
+   readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+   readerStates.szReader = this->_readerName->c_str();
+
+   // lets check if token is present
+#ifndef _XCL_
+
+   if (SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+   {
+      if ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+      {
+         // we found a card in this reader
+         this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+      }
+      else
+      {
+         // No card in reader
+         this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+         CloseAllSessions();
+      }
+   }
+
+#else // _XCL_
+
+    PRINT_MSG("IN Slot::GetInfo");
+    if (xCL_IsTokenPresent())
+    {
+        // we found a card in this reader
+        this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+    }
+    else
+    {
+        // No card in reader
+        this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+    }
+
+#endif // _XCL_
+
+   pInfo->flags = this->_slotInfo.flags;
+
+   return CKR_OK;
+}
+
+
+CK_RV Slot::GetTokenInfo( CK_TOKEN_INFO_PTR pInfo )
+{
+   Log::begin( "Slot::GetTokenInfo" );
+
+   checkConnection( this );
+
+   // Check Parameters
+   if( NULL_PTR == pInfo )
+   {
+      Log::error( "Slot::GetTokenInfo", "CKR_ARGUMENTS_BAD" );
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   //Log::log( "Slot::GetTokenInfo - BuildToken..." );
+   CK_RV rv = this->BuildToken( );
+   //Log::log( "Slot::GetTokenInfo - BuildToken <%#02x>", rv );
+   if( CKR_OK == rv )
+   {
+      Transaction trans(this);
+
+      CK_BYTE idx;
+
+      pInfo->firmwareVersion.major = this->_token->_tokenInfo.firmwareVersion.major;
+      pInfo->firmwareVersion.minor = this->_token->_tokenInfo.firmwareVersion.minor;
+      pInfo->flags                 = this->_token->_tokenInfo.flags;
+      pInfo->hardwareVersion.major = this->_token->_tokenInfo.hardwareVersion.major;
+      pInfo->hardwareVersion.minor = this->_token->_tokenInfo.hardwareVersion.minor;
+
+      // label
+      for(idx=0;idx<32;idx++)
+      {
+         pInfo->label[idx] = this->_token->_tokenInfo.label[idx];
+      }
+
+      // manufacturerID
+      for(idx=0;idx<32;idx++)
+      {
+         pInfo->manufacturerID[idx]  = this->_token->_tokenInfo.manufacturerID[idx];
+      }
+
+      // model
+      for(idx=0;idx<16;idx++)
+      {
+         pInfo->model[idx]  = this->_token->_tokenInfo.model[idx];
+      }
+
+      // serial number
+      for(idx=0;idx<16;idx++)
+      {
+         pInfo->serialNumber[idx]  = this->_token->_tokenInfo.serialNumber[idx];
+      }
+
+      pInfo->ulFreePrivateMemory  = this->_token->_tokenInfo.ulFreePrivateMemory;
+      pInfo->ulFreePublicMemory   = this->_token->_tokenInfo.ulFreePublicMemory;
+      pInfo->ulMaxPinLen          = this->_token->_tokenInfo.ulMaxPinLen;
+      pInfo->ulMinPinLen          = this->_token->_tokenInfo.ulMinPinLen;
+      pInfo->ulMaxRwSessionCount  = CK_EFFECTIVELY_INFINITE;
+      pInfo->ulSessionCount       = 0;
+      pInfo->ulMaxSessionCount    = CK_EFFECTIVELY_INFINITE;
+      pInfo->ulRwSessionCount     = 0;
+      pInfo->ulTotalPrivateMemory = this->_token->_tokenInfo.ulTotalPrivateMemory;
+      pInfo->ulTotalPublicMemory  = this->_token->_tokenInfo.ulTotalPublicMemory;
+
+      for(size_t i=1;i<_sessions.size();i++)
+      {
+         if(_sessions[i])
+         {
+            ++pInfo->ulSessionCount;
+            if(_sessions[i]->_isReadWrite)
+               ++pInfo->ulRwSessionCount;
+         }
+      }
+
+      // utcTime
+      for(idx=0;idx<16;idx++)
+      {
+         pInfo->utcTime[idx]  = this->_token->_tokenInfo.utcTime[idx];
+      }
+
+      // Check if the smart card is in SSO mode
+      if( ( true == this->_token->isSSO( ) ) && ( true == this->_token->isAuthenticated( ) ) )
+      {
+         this->_token->_tokenInfo.flags &= ~CKF_LOGIN_REQUIRED;
+      }
+      else
+      {
+         this->_token->_tokenInfo.flags |= CKF_LOGIN_REQUIRED;
+      }
+
+      Log::log( "Slot::GetTokenInfo - tokenInfo formated ok" );
+   }
+
+   Log::logCK_RV( "Slot::GetTokenInfo", rv );
+   Log::end( "Slot::GetTokenInfo" );
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::GetMechanismList(CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount)
+{
+   if(pulCount == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(pMechanismList == NULL_PTR)
+   {
+      *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+   }
+   else
+   {
+      if(*pulCount < (sizeof(MechanismList)/sizeof(CK_ULONG)))
+      {
+         *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+         return CKR_BUFFER_TOO_SMALL;
+      }
+
+      for(size_t i=0;i<(sizeof(MechanismList)/sizeof(CK_ULONG));i++)
+      {
+         pMechanismList[i] = MechanismList[i];
+      }
+      *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+   }
+
+   return CKR_OK;
+}
+
+
+/*
+*/
+CK_RV Slot::GetMechanismInfo(CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo)
+{
+   if(pInfo == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   size_t i = 0;
+   CK_BBOOL found = CK_FALSE;
+   for( ;i<(sizeof(MechanismList)/sizeof(CK_ULONG));i++)
+   {
+      if(MechanismList[i] == type)
+      {
+         found = CK_TRUE;
+         break;
+      }
+   }
+
+   if(found == CK_FALSE)
+   {
+      return CKR_MECHANISM_INVALID;
+   }
+
+   pInfo->ulMinKeySize = MechanismInfo[i].ulMinKeySize;
+   pInfo->ulMaxKeySize = MechanismInfo[i].ulMaxKeySize;
+   pInfo->flags  = MechanismInfo[i].flags;
+
+   return CKR_OK;
+}
+
+
+CK_RV Slot::InitToken(CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel)
+{
+   CK_RV rv = CKR_OK;
+
+   checkConnection( this );
+
+   if(pPin == NULL_PTR || ulPinLen == 0 || pLabel == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   // check if we have an open session
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] != NULL_PTR){
+         return CKR_SESSION_EXISTS;
+      }
+   }
+
+   rv = this->BuildToken();
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   u1Array* pin = new u1Array(ulPinLen);
+   pin->SetBuffer(pPin);
+
+   u1Array* label = new u1Array(32);
+   label->SetBuffer(pLabel);
+
+   // Don't do the Transaction here.
+
+   rv = this->_token->InitToken(pin,label);
+
+   delete pin;
+   delete label;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::OpenSession( CK_FLAGS flags, CK_VOID_PTR, CK_NOTIFY, CK_SESSION_HANDLE_PTR phSession )
+{
+   checkConnection( this );
+
+   if(phSession == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if( ( flags & CKF_SERIAL_SESSION ) != CKF_SERIAL_SESSION )
+   {
+      return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+   }
+
+   CK_RV rv = this->BuildToken( );
+   if( rv != CKR_OK )
+   {
+      return rv;
+   }
+
+   Transaction trans( this );
+
+   // if admin is logged we can not open RO session
+   CK_BBOOL rwSession = ((flags & CKF_RW_SESSION) == CKF_RW_SESSION);
+
+   if( ( this->_token->_roleLogged == CKU_SO ) && ( !rwSession ) )
+   {
+      return CKR_SESSION_READ_WRITE_SO_EXISTS;
+   }
+
+   // Create the session instance
+   Session* session = new Session( rwSession );
+
+   // lets create a session
+   s4 sessionId = this->AddSession( session );
+   if( 0 == sessionId )
+   {
+      return CKR_SESSION_COUNT;
+   }
+
+   session->SetId(sessionId);
+   session->SetSlot(this);
+
+   // Refresh the state of the session if the SSO mode is enabled
+   UpdateAuthenticationState( );
+
+   // prepare a unique session id
+   *phSession = MAKE_SESSIONHANDLE(sessionId,this->_slotId);
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::CloseSession( CK_SESSION_HANDLE hSession )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   //CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   //Slot* pSlot = NULL_PTR;
+   //GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   //checkConnection( pSlot );
+
+   //hSessionId = CK_INVALID_HANDLE;
+   //pSlot = NULL_PTR;
+   //CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+
+   if( CKR_OK == rv )
+   {
+      CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+      CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+
+      pSlot->RemoveSession( hSessionId );
+
+      // Refresh the state of the session if the SSO mode is enabled
+      pSlot->UpdateAuthenticationState( );
+   }
+
+   return rv;
+}
+
+
+/*
+Check first if the card is in SSO mode then update the state of all sessions
+*/
+void Slot::UpdateAuthenticationState( void )
+{
+   // Check if the smart card is in SSO mode
+   if( true == _token->isSSO( ) )
+   {
+      // Affect the role to the token if the user is authenticated
+      _token->_roleLogged = CKU_NONE;
+      if( true == _token->isAuthenticated( ) )
+      {
+         _token->_roleLogged = CKU_USER;
+      }
+
+      // Update the state of all sessions
+      UpdateSessionState( );
+   }
+}
+
+
+/*
+*/
+CK_RV Slot::CloseAllSessions(void)
+{
+   // remove all sessions
+   for( size_t i = 1 ; i < _sessions.size( ) ; i++ )
+   {
+      if( NULL_PTR != this->_sessions[ i ] )
+      {
+         delete this->_sessions[ i ];
+      }
+
+      this->_sessions[ i ] = NULL_PTR;
+   }
+
+   _sessions.resize( 1 );
+
+   CHECK_IF_TOKEN_IS_PRESENT( this );
+
+   this->_token->_roleLogged = CKU_NONE;
+
+   // Refresh the state of the session if the SSO mode is enabled
+   UpdateAuthenticationState( );
+
+   return CKR_OK;
+}
+
+
+/*
+*/
+CK_RV Slot::GetSessionInfo( CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if( CKR_OK != rv )
+   {
+      return rv;
+   }
+
+   if(pInfo == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId);
+
+   Transaction trans( pSlot );
+
+   pInfo->slotID = pSlot->_slotId;
+   pInfo->ulDeviceError = CKR_OK;
+
+   // Check if the smart card is in SSO mode
+   pSlot->UpdateAuthenticationState( );
+
+   pInfo->flags = ( ( pSlot->_sessions[ hSessionId ]->_isReadWrite ) ? CKF_RW_SESSION : 0 ) | (CKF_SERIAL_SESSION);
+   pInfo->state = pSlot->_sessions[ hSessionId ]->_state;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Login( CK_SESSION_HANDLE hSession,
+                   CK_USER_TYPE userType,
+                   CK_UTF8CHAR_PTR pPin,
+                   CK_ULONG ulPinLen )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   if(userType == CKU_SO)
+   {
+      if(pSlot->HasReadOnlySession())
+      {
+         return CKR_SESSION_READ_ONLY_EXISTS;
+      }
+   }
+
+   if( NULL_PTR == pPin )
+   {
+      ulPinLen = 0;
+   }
+
+   u1Array* pinValue = new u1Array(ulPinLen);
+   u1* pinValueBuffer = pinValue->GetBuffer();
+   CK_BYTE idx = 0;
+   for(idx=0;idx<ulPinLen;idx++)
+   {
+      pinValueBuffer[idx] = pPin[idx];
+   }
+   rv = pSlot->_token->Login(userType,pinValue);
+
+   if(rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
+   {
+      if(userType == CKU_SO)
+      {
+         // cache SO PIN for the duration of this session
+         pSlot->_sessions[ hSessionId ]->_soPIN = new u1Array(pinValue->GetLength());
+         pSlot->_sessions[ hSessionId ]->_soPIN->SetBuffer(pinValue->GetBuffer());
+      }
+   }
+
+   if(rv == CKR_OK)
+   {
+      pSlot->UpdateSessionState();
+   }
+
+   delete pinValue;
+
+   return rv;
+}
+
+
+
+CK_RV Slot::Logout( CK_SESSION_HANDLE hSession )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   rv = pSlot->_token->Logout( );
+
+   pSlot->UpdateSessionState( );
+
+   return rv;
+}
+
+
+CK_RV Slot::InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if(pPin == NULL_PTR || ulPinLen == 0){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->_state != CKS_RW_SO_FUNCTIONS)
+   {
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   PKCS11_ASSERT(session->_soPIN != NULL_PTR);
+
+   u1Array* pin = new u1Array(ulPinLen);
+   pin->SetBuffer(pPin);
+
+   rv = pSlot->_token->InitPIN(session->_soPIN,pin);
+
+   delete pin;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SetPIN( CK_SESSION_HANDLE hSession,
+                    CK_UTF8CHAR_PTR pOldPin,
+                    CK_ULONG ulOldLen,
+                    CK_UTF8CHAR_PTR pNewPin,
+                    CK_ULONG ulNewLen )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   if(pOldPin == NULL_PTR || ulOldLen == 0 || pNewPin == NULL_PTR || ulNewLen == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   CK_ULONG state = pSlot->_sessions[ hSessionId ]->_state;
+
+   if((state != CKS_RW_PUBLIC_SESSION) &&
+      (state != CKS_RW_SO_FUNCTIONS)&&
+      (state != CKS_RW_USER_FUNCTIONS))
+   {
+      return CKR_SESSION_READ_ONLY;
+   }
+
+   u1Array* oldPin = new u1Array(ulOldLen);
+   oldPin->SetBuffer(pOldPin);
+
+   u1Array* newPin = new u1Array(ulNewLen);
+   newPin->SetBuffer(pNewPin);
+
+   rv = pSlot->_token->SetPIN(oldPin,newPin);
+
+   delete oldPin;
+   delete newPin;
+
+   return rv;
+}
+
+
+CK_RV  Slot::FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   if((pTemplate == NULL_PTR) && (ulCount != 0))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // check if search is active for this session or not
+   if(session->IsSearchActive() == CK_TRUE)
+   {
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   Template* searchTmpl = NULL_PTR;
+   if(ulCount != 0)
+   {
+      searchTmpl = new Template(pTemplate,ulCount);
+   }
+
+   session->SetSearchTemplate(searchTmpl);
+
+   return rv;
+}
+
+
+
+CK_RV  Slot::FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+                         CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount)
+{
+   Log::begin( "Slot::FindObjects" );
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   if((phObject == NULL_PTR) || (pulObjectCount == NULL_PTR))
+   {
+      Log::error( "Slot::FindObjects", "CKR_ARGUMENTS_BAD" );
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   Log::log( "Slot::FindObjects - CHECK_IF_TOKEN_IS_PRESENT" );
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   Log::log( "Slot::FindObjects - CHECK_IF_TOKEN_IS_PRESENT" );
+
+   Log::log( "Slot::FindObjects - CHECK_IF_NULL_SESSION" );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Log::log( "Slot::FindObjects - CHECK_IF_NULL_SESSION" );
+
+   // Not needed here...
+   Log::log( "Slot::FindObjects - Transaction" );
+   Transaction trans( pSlot );
+   Log::log( "Slot::FindObjects - Transaction" );
+
+   Log::log( "Slot::FindObjects - session" );
+   Session* session = pSlot->_sessions[ hSessionId ];
+   Log::log( "Slot::FindObjects - session" );
+
+   // check if search is active for this session or not
+   Log::log( "Slot::FindObjects - IsSearchActive" );
+   if(session->IsSearchActive() == CK_FALSE)
+   {
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+   Log::log( "Slot::FindObjects - IsSearchActive" );
+
+   *pulObjectCount = 0;
+
+   // find the token objects matching the template
+   // count will tell how much of the phObject buffer was written
+   Log::log( "Slot::FindObjects - FindObjects" );
+   CK_ULONG count = pSlot->_token->FindObjects( session, phObject, ulMaxObjectCount, pulObjectCount );
+   Log::log( "Slot::FindObjects - FindObjects" );
+
+   if(count < ulMaxObjectCount)
+   {
+      // find the session objects matching the template
+      Log::log( "Slot::FindObjects - (count < ulMaxObjectCount)" );
+      count = session->FindObjects(count,phObject,ulMaxObjectCount,pulObjectCount);
+      Log::log( "Slot::FindObjects - (count < ulMaxObjectCount)" );
+   }
+
+   Log::logCK_RV( "Slot::FindObjects", rv );
+   Log::end( "Slot::FindObjects" );
+
+   return rv;
+}
+
+
+
+CK_RV  Slot::FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+
+   // Not needed here
+   // Transaction trans(slot);
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // check if search is active for this session or not
+   if(session->IsSearchActive() == CK_FALSE)
+   {
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   session->RemoveSearchTemplate();
+
+   return rv;
+}
+
+CK_RV Slot::GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR randomData,CK_ULONG ulRandomLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   if((randomData == NULL_PTR) || (ulRandomLen == 0))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   return pSlot->_token->GenerateRandom(randomData,ulRandomLen);
+}
+
+
+
+CK_RV Slot::CreateObject( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject )
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   checkConnection( pSlot );
+
+  if(rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   // check the pointer arguments
+   if((pTemplate == NULL_PTR) || (ulCount == 0) || (phObject == NULL_PTR))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   // Check Template Consitency
+   rv = Template::CheckTemplate(pTemplate, ulCount, MODE_CREATE);
+   if (rv != CKR_OK)
+   {
+      return rv;
+   }
+
+   CK_ULONG classVal = Template::FindClassFromTemplate(pTemplate,ulCount);
+   PKCS11_ASSERT(classVal != -1);
+
+   auto_ptr<StorageObject> object;
+
+   switch(classVal){
+
+        case CKO_DATA:
+           object = auto_ptr<StorageObject>(new DataObject());
+           break;
+
+        case CKO_SECRET_KEY:
+           object = auto_ptr<StorageObject>(new SecretKeyObject());
+           break;
+
+        case CKO_PUBLIC_KEY:
+           object = auto_ptr<StorageObject>(new RSAPublicKeyObject());
+           break;
+
+        case CKO_PRIVATE_KEY:
+           object = auto_ptr<StorageObject>(new RSAPrivateKeyObject());
+           break;
+
+        case CKO_CERTIFICATE:
+           object = auto_ptr<StorageObject>(new X509PubKeyCertObject());
+           break;
+
+        default:
+           PKCS11_ASSERT(CK_FALSE);
+           break;
+   }
+
+   CK_BBOOL objCreationFailed = CK_FALSE;
+   CK_BYTE idx;
+   for(idx = 0; idx < ulCount; idx++)
+   {
+      if((rv = object->SetAttribute(pTemplate[idx],CK_TRUE)) != CKR_OK){
+         objCreationFailed = CK_TRUE;
+         break;
+      }
+   }
+
+   if(objCreationFailed)
+   {
+      return rv;
+   }
+
+   switch(object->_class)
+   {
+        case CKO_PUBLIC_KEY:
+           if(((RSAPublicKeyObject*)object.get())->_keyType != CKK_RSA)
+           {
+              return CKR_KEY_TYPE_INCONSISTENT;
+           }
+           break;
+
+        case CKO_PRIVATE_KEY:
+           if(((RSAPrivateKeyObject*)object.get())->_keyType != CKK_RSA)
+           {
+              return CKR_KEY_TYPE_INCONSISTENT;
+           }
+           break;
+   }
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // if this is a readonly session and
+   // user is not logged then only public session objects
+   // can be created
+   if(session->_isReadWrite == CK_FALSE)
+   {
+      if(object->_tokenObject)
+      {
+         return CKR_SESSION_READ_ONLY;
+      }
+   }
+
+   if ((pSlot->_token->_roleLogged != CKU_USER) && (object->_private == CK_TRUE))
+   {
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   if(object->_tokenObject)
+   {
+
+      // any type of token object cannot be created
+      // unless user is logged in
+
+      // NOTE : Not PKCS#11 compilance
+      // CardModule service does not allow 'deletion' of any file unless user is logged in. We can create a file
+      // when nobody is logged in but we can not delete. In order to be symmetrical we do not also allow
+      // the creation.
+      if(pSlot->_token->_roleLogged != CKU_USER)
+      {
+         return CKR_USER_NOT_LOGGED_IN;
+      }
+
+      // some sanity checks
+      if(object->_class == CKO_PRIVATE_KEY)
+      {
+         rv = pSlot->_token->AddPrivateKeyObject(object, phObject);
+      }
+      else if(object->_class == CKO_CERTIFICATE)
+      {
+         rv = pSlot->_token->AddCertificateObject(object, phObject);
+      }
+      else
+      {
+         rv = pSlot->_token->AddObject(object, phObject);
+      }
+   }
+   else
+   {
+      rv = session->AddObject(object.get(),phObject);
+      if(rv == CKR_OK)
+         object.release();
+   }
+
+   return rv;
+}
+
+
+
+CK_RV Slot::DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hObject & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   // if this is a readonly session and
+   // user is not logged then only public session objects
+   // can be created
+   if(session->_isReadWrite == CK_FALSE)
+   {
+      if(istoken)
+      {
+         return CKR_SESSION_READ_ONLY;
+      }
+   }
+
+   if(istoken)
+   {
+      rv = pSlot->_token->DeleteObject(hObject);
+   }
+   else
+   {
+      rv = session->DeleteObject(hObject);
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::GetAttributeValue( CK_SESSION_HANDLE hSession,
+                               CK_OBJECT_HANDLE hObject,
+                               CK_ATTRIBUTE_PTR pTemplate,
+                               CK_ULONG ulCount )
+{
+   if(pTemplate == NULL_PTR || ulCount == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hObject & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   // TBD : Attributes of types such as Array which have not be initialized ?
+   // for eg label
+
+   if(istoken)
+   {
+      rv = pSlot->_token->GetAttributeValue(hObject,pTemplate,ulCount);
+   }
+   else
+   {
+      rv = session->GetAttributeValue(hObject,pTemplate,ulCount);
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SetAttributeValue( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+{
+   if(pTemplate == NULL_PTR || ulCount == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+  if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* pSession = pSlot->_sessions[ hSessionId ];
+
+   // From object handle we can determine if it is a token object or session object
+   CK_BBOOL istoken = ( ( hObject & CO_TOKEN_OBJECT ) == CO_TOKEN_OBJECT );
+   if( TRUE == istoken )
+   {
+      if( CK_FALSE == pSession->_isReadWrite )
+      {
+         return CKR_SESSION_READ_ONLY;
+      }
+
+      rv = pSlot->_token->SetAttributeValue( hObject, pTemplate, ulCount );
+   }
+   else
+   {
+      rv = pSession->SetAttributeValue( hObject, pTemplate, ulCount );
+   }
+
+   return rv;
+}
+
+
+CK_RV Slot::GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+                            CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,
+                            CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)
+{
+   // Since MODULUS_BITS is an essential attribute pPublicKeyTemplate should never be NULL or ulPublicKeyAttributeCount
+   // should not be zero. For private key template there is not compuslary attributes to be specified so it can be
+   // NULL_PTR
+
+   if((pMechanism == NULL_PTR) || (pPublicKeyTemplate == NULL_PTR) ||
+      (ulPublicKeyAttributeCount == 0) || (phPublicKey == NULL_PTR) ||
+      (phPrivateKey == NULL_PTR))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(pMechanism->mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN)
+      return CKR_MECHANISM_INVALID;
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   //Session* session = pSlot->_sessions[ hSessionId ];
+
+   // Check Public Template Consitency
+   rv = Template::CheckTemplate(pPublicKeyTemplate, ulPublicKeyAttributeCount, MODE_GENERATE_PUB);
+   if (rv != CKR_OK)
+      return rv;
+
+   // Check Private Template Consitency
+   rv = Template::CheckTemplate(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, MODE_GENERATE_PRIV);
+   if (rv != CKR_OK)
+      return rv;
+
+   auto_ptr<StorageObject> rsaPubKey(new RSAPublicKeyObject());
+   for(u4 i=0;i<ulPublicKeyAttributeCount;i++){
+      rv = rsaPubKey->SetAttribute(pPublicKeyTemplate[i],CK_TRUE);
+      if(rv != CKR_OK){
+         return rv;
+      }
+   }
+
+   auto_ptr<StorageObject> rsaPrivKey(new RSAPrivateKeyObject());
+   for(u4 i=0;i<ulPrivateKeyAttributeCount;i++){
+      rv = rsaPrivKey->SetAttribute(pPrivateKeyTemplate[i],CK_TRUE);
+      if(rv != CKR_OK){
+         return rv;
+      }
+   }
+
+   if(rsaPrivKey->_tokenObject){
+      rv = pSlot->_token->GenerateKeyPair(rsaPubKey,rsaPrivKey,phPublicKey,phPrivateKey);
+   }else{
+
+      // We do not support generation of key pair in the software
+      // TBD: Should we ?. I have noticed that during the import of
+      // p12 file using firefox it asks you to generate it in session
+
+      return CKR_ATTRIBUTE_VALUE_INVALID;
+   }
+
+   if(rv == CKR_OK)
+   {
+      if(rsaPubKey.get() && !rsaPubKey->_tokenObject)
+      {
+         pSlot->_sessions[ hSessionId ]->AddObject(rsaPubKey.get(),phPublicKey);
+         rsaPubKey.release();
+      }
+   }
+   return rv;
+}
+
+// ------------------------------------------------------------------------------------------------
+//                                  DIGEST RELATED FUNCTIONS
+// ------------------------------------------------------------------------------------------------
+CK_RV Slot::DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)
+{
+   if(pMechanism == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   // Not needed
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->IsDigestActive()){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   switch(pMechanism->mechanism){
+
+        case CKM_SHA_1:
+           session->SetDigest(new CSHA1());
+           break;
+
+        case CKM_SHA256:
+           session->SetDigest(new CSHA256());
+           break;
+
+        case CKM_MD5:
+           session->SetDigest(new CMD5());
+           break;
+
+        default:
+           return CKR_MECHANISM_INVALID;
+
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                   CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)
+{
+   if((pData == NULL_PTR) || (ulDataLen == 0) || (pulDigestLen == NULL_PTR)){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDigestActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   CDigest* digest = session->_digest;
+
+   if((*pulDigestLen < (CK_ULONG)digest->HashLength()) && (pDigest != NULL_PTR)){
+      *pulDigestLen = (CK_ULONG)digest->HashLength();
+      return CKR_BUFFER_TOO_SMALL;
+   }
+   else if(!pDigest){
+      *pulDigestLen = digest->HashLength();
+      return CKR_OK;
+   }
+
+   digest->HashCore(pData, 0, ulDataLen);
+
+   *pulDigestLen = (CK_ULONG)digest->HashLength();
+
+   if (pDigest != NULL_PTR)
+   {
+      digest->HashFinal(pDigest);
+      session->RemoveDigest();
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)
+{
+   if(pPart == NULL_PTR || ulPartLen == 0)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDigestActive() == CK_FALSE)
+   {
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   session->_digest->HashCore(pPart,0,ulPartLen);
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)
+{
+   if(pulDigestLen == NULL_PTR)
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->IsDigestActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   CDigest*    digest   = session->_digest;
+
+   if((*pulDigestLen < (CK_ULONG)digest->HashLength()) && (pDigest != NULL_PTR)){
+      *pulDigestLen = (CK_ULONG)digest->HashLength();
+      return CKR_BUFFER_TOO_SMALL;
+   }
+   else if(!pDigest){
+      *pulDigestLen = digest->HashLength();
+      return CKR_OK;
+   }
+
+   *pulDigestLen = (CK_ULONG)digest->HashLength();
+
+   if (pDigest != NULL_PTR){
+      digest->HashFinal(pDigest);
+      session->RemoveDigest();
+   }
+
+   return rv;
+}
+
+// ------------------------------------------------------------------------------------------------
+//                                  SIGNATURE RELATED FUNCTIONS
+// ------------------------------------------------------------------------------------------------
+CK_RV Slot::SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+   if(session->IsSignatureActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_SIGN);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if(pSlot->_token->_roleLogged != CKU_USER){
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_SIGN);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetSignatureOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   if(pMechanism->mechanism == CKM_SHA1_RSA_PKCS){
+      session->SetDigestRSA(new CSHA1());
+   }else if(pMechanism->mechanism == CKM_SHA256_RSA_PKCS){
+      session->SetDigestRSA(new CSHA256());
+   }else if(pMechanism->mechanism == CKM_MD5_RSA_PKCS){
+      session->SetDigestRSA(new CMD5());
+   }
+
+   return rv;
+}
+
+
+
+CK_RV Slot::Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                 CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsSignatureActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pData == NULL_PTR || ulDataLen == 0 || pulSignatureLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   StorageObject* object = session->_signature->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+   CK_ULONG mechanism = session->_signature->GetMechanism();
+
+   // TBD : Private key may not necessarily have the modulus or modulus bits
+   // if that is the case then we need to locate the corresponding public key
+   // or may be I should always put the modulus bits in private key attributes
+
+   u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(((mechanism == CKM_RSA_PKCS) && (ulDataLen > modulus->GetLength() - 11)) ||
+      ((mechanism == CKM_RSA_X_509) && (ulDataLen > modulus->GetLength())))
+   {
+      return CKR_DATA_LEN_RANGE;
+   }
+
+   if(pSignature == NULL_PTR){
+      *pulSignatureLen = modulus->GetLength();
+      return CKR_OK;
+   }else{
+      if(*pulSignatureLen < modulus->GetLength()){
+         *pulSignatureLen = modulus->GetLength();
+         return CKR_BUFFER_TOO_SMALL;
+      }
+   }
+
+   u1Array* dataToSign = NULL_PTR;
+
+   if(session->IsDigestRSAActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSA;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashCore(pData,0,ulDataLen);
+      digest->HashFinal(hash);
+
+      dataToSign  = new u1Array(digest->HashLength());
+      dataToSign->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToSign = new u1Array(ulDataLen);
+      dataToSign->SetBuffer(pData);
+   }
+
+   rv = pSlot->_token->Sign(session->_signature->GetObject(),dataToSign,session->_signature->GetMechanism(),pSignature);
+
+   if(rv == CKR_OK){
+      *pulSignatureLen = modulus->GetLength();
+   }
+
+   session->RemoveDigestRSA();
+   session->RemoveSignatureOperation();
+
+   delete dataToSign;
+
+   return rv;
+}
+
+
+
+CK_RV Slot::SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+   // what we do here is to update the hash or
+   // if hashing is not getting used we just accumulate it
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsSignatureActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pPart == NULL_PTR || ulPartLen == 0){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(session->IsDigestRSAActive() == CK_TRUE){
+      CDigest* digest = session->_digestRSA;
+      digest->HashCore(pPart,0,ulPartLen);
+   }
+   // Sign Only
+   else {
+
+      if(session->_accumulatedDataToSign != NULL_PTR){
+         // just accumulate the data
+         u1Array* updatedData = new u1Array(session->_accumulatedDataToSign->GetLength() + ulPartLen);
+         memcpy(updatedData->GetBuffer(),session->_accumulatedDataToSign->GetBuffer(),session->_accumulatedDataToSign->GetLength());
+
+         memcpy((u1*)&updatedData->GetBuffer()[session->_accumulatedDataToSign->GetLength()],pPart,ulPartLen);
+
+         delete session->_accumulatedDataToSign;
+
+         session->_accumulatedDataToSign = updatedData;
+      }else{
+
+         session->_accumulatedDataToSign = new u1Array(ulPartLen);
+         session->_accumulatedDataToSign->SetBuffer(pPart);
+      }
+
+      CK_ULONG mech = session->_signature->GetMechanism();
+      u1Array* modulus = ((RSAPrivateKeyObject*)session->_signature->GetObject())->_modulus;
+
+      if(((mech == CKM_RSA_PKCS) && (session->_accumulatedDataToSign->GetLength() > modulus->GetLength() - 11)) ||
+         ((mech == CKM_RSA_X_509) && (session->_accumulatedDataToSign->GetLength() > modulus->GetLength())))
+      {
+         return CKR_DATA_LEN_RANGE;
+      }
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsSignatureActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pulSignatureLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   StorageObject* object = session->_signature->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+
+   // TBD : Private key may not necessarily have the modulus or modulus bits
+   // if that is the case then we need to locate the corresponding public key
+   // or may be I should always put the modulus bits in private key attributes
+
+   u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(pSignature == NULL_PTR){
+      *pulSignatureLen = modulus->GetLength();
+      return CKR_OK;
+   }else{
+      if(*pulSignatureLen < modulus->GetLength()){
+         *pulSignatureLen = modulus->GetLength();
+         return CKR_BUFFER_TOO_SMALL;
+      }
+   }
+
+   u1Array* dataToSign = NULL_PTR;
+
+   if(session->IsDigestRSAActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSA;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashFinal(hash);
+
+      dataToSign  = new u1Array(digest->HashLength());
+      dataToSign->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToSign = session->_accumulatedDataToSign;
+   }
+
+   rv = pSlot->_token->Sign(session->_signature->GetObject(),dataToSign,session->_signature->GetMechanism(),pSignature);
+
+   if(rv == CKR_OK){
+      *pulSignatureLen = modulus->GetLength();
+   }
+
+   session->RemoveDigestRSA();
+   session->RemoveSignatureOperation();
+
+   delete dataToSign;
+   session->_accumulatedDataToSign = NULL_PTR;
+
+   return rv;
+}
+
+
+
+CK_RV Slot::EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsEncryptionActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_ENCRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if(pSlot->_token->_roleLogged != CKU_USER){
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_ENCRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetEncryptionOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                    CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)
+{
+   if(pData == NULL_PTR || ulDataLen == 0 || pulEncryptedDataLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+    if(rv != CKR_OK)
+   {
+      return rv;
+   }
+  checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsEncryptionActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   StorageObject* object = session->_encryption->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+
+   //CK_ULONG mechanism = session->_encryption->GetMechanism();
+
+   u1Array* modulus = ((RSAPublicKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(pEncryptedData == NULL_PTR){
+      *pulEncryptedDataLen = modulus->GetLength();
+      return CKR_OK;
+   }else{
+      if(*pulEncryptedDataLen < modulus->GetLength()){
+         *pulEncryptedDataLen = modulus->GetLength();
+         return CKR_BUFFER_TOO_SMALL;
+      }
+   }
+
+   u1Array* dataToEncrypt = new u1Array(ulDataLen);
+   dataToEncrypt->SetBuffer(pData);
+
+   rv = pSlot->_token->Encrypt(session->_encryption->GetObject(),dataToEncrypt,session->_encryption->GetMechanism(),pEncryptedData);
+
+   if(rv == CKR_OK){
+      *pulEncryptedDataLen = modulus->GetLength();
+   }
+
+   session->RemoveEncryptionOperation();
+
+   delete dataToEncrypt;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDecryptionActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_DECRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if(pSlot->_token->_roleLogged != CKU_USER){
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_DECRYPT);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetDecryptionOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,
+                    CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
+{
+   if(pEncryptedData == NULL_PTR || ulEncryptedDataLen == 0 ||pulDataLen == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsDecryptionActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   StorageObject* object = session->_decryption->GetObject();
+
+   PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+   CK_ULONG mechanism = session->_decryption->GetMechanism();
+
+   // TBD : Private key may not necessarily have the modulus or modulus bits
+   // if that is the case then we need to locate the corresponding public key
+   // or may be I should always put the modulus bits in private key attributes
+
+   u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   // [HB]: Fix length of return value
+   if(mechanism == CKM_RSA_PKCS){
+      // Can't know exact size of returned value before decryption has been done
+      if(pData == NULL_PTR){
+         *pulDataLen = modulus->GetLength() - 11;
+         return CKR_OK;
+      }
+   }
+   else if(mechanism == CKM_RSA_X_509){
+      if(pData == NULL_PTR){
+         *pulDataLen = modulus->GetLength();
+         return CKR_OK;
+      }else{
+         if(*pulDataLen < modulus->GetLength()){
+            *pulDataLen = modulus->GetLength();
+            return CKR_BUFFER_TOO_SMALL;
+         }
+      }
+   }
+   else
+      return CKR_MECHANISM_INVALID;
+
+   if(ulEncryptedDataLen != modulus->GetLength()){
+      return CKR_ENCRYPTED_DATA_LEN_RANGE;
+   }
+
+   u1Array* dataToDecrypt = new u1Array(ulEncryptedDataLen);
+   dataToDecrypt->SetBuffer(pEncryptedData);
+
+   rv = pSlot->_token->Decrypt(session->_decryption->GetObject(),dataToDecrypt,session->_decryption->GetMechanism(),pData, pulDataLen);
+
+   session->RemoveDecryptionOperation();
+
+   delete dataToDecrypt;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV  Slot::VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+   if(pMechanism == NULL_PTR){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+    if(rv != CKR_OK)
+   {
+      return rv;
+   }
+  checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_TRUE){
+      return CKR_OPERATION_ACTIVE;
+   }
+
+   rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_VERIFY);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   if(pSlot->_token->_roleLogged != CKU_USER){
+      return CKR_USER_NOT_LOGGED_IN;
+   }
+
+   // get the corresponding object
+   StorageObject* object = NULL_PTR;
+
+   // from object handle we can determine
+   // if it is a token object or session object
+   CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+   if(istoken){
+      rv = pSlot->_token->GetObject(hKey,&object);
+   }else{
+      rv = session->GetObject(hKey,&object);
+   }
+
+   if(rv != CKR_OK){
+
+      if(rv == CKR_OBJECT_HANDLE_INVALID){
+         return CKR_KEY_HANDLE_INVALID;
+      }
+
+      return rv;
+   }
+
+   rv = Slot::IsValidCryptoOperation(object,CKF_VERIFY);
+
+   if(rv != CKR_OK){
+      return rv;
+   }
+
+   // let's initialize this crypto operation
+   session->SetVerificationOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+   if(pMechanism->mechanism == CKM_SHA1_RSA_PKCS){
+      session->SetDigestRSAVerification(new CSHA1());
+   }else if(pMechanism->mechanism == CKM_SHA256_RSA_PKCS){
+      session->SetDigestRSAVerification(new CSHA256());
+   }else if(pMechanism->mechanism == CKM_MD5_RSA_PKCS){
+      session->SetDigestRSAVerification(new CMD5());
+   }
+
+   return CKR_OK;
+
+}
+
+
+/*
+*/
+CK_RV  Slot::Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+                    CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if((pData == NULL_PTR) || (ulDataLen == 0) ||
+      (pSignature == NULL_PTR) || (ulSignatureLen == 0))
+   {
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   CK_ULONG mechanism = session->_verification->GetMechanism();
+
+
+   // I am doubtful regarding these 3 lines as
+   // the object could be privatekey which contains
+   // the public components
+   StorageObject* object = session->_verification->GetObject();
+   PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+   u1Array* modulus = ((RSAPublicKeyObject*)object)->_modulus;
+
+   PKCS11_ASSERT(modulus != NULL_PTR);
+
+   if(((mechanism == CKM_RSA_PKCS) && (ulDataLen > modulus->GetLength() - 11)) ||
+      ((mechanism == CKM_RSA_X_509) && (ulDataLen > modulus->GetLength())))
+   {
+      return CKR_DATA_LEN_RANGE;
+   }
+
+   u1Array* dataToVerify = NULL_PTR;
+
+   if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSAVerification;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashCore(pData,0,ulDataLen);
+      digest->HashFinal(hash);
+
+      dataToVerify  = new u1Array(digest->HashLength());
+      dataToVerify->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToVerify = new u1Array(ulDataLen);
+      dataToVerify->SetBuffer(pData);
+   }
+
+   u1Array* signature = new u1Array(ulSignatureLen);
+   signature->SetBuffer(pSignature);
+
+   rv = pSlot->_token->Verify(session->_verification->GetObject(),dataToVerify,session->_verification->GetMechanism(),signature);
+
+   delete signature;
+
+   session->RemoveDigestRSAVerification();
+   session->RemoveVerificationOperation();
+
+   delete dataToVerify;
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)
+{
+
+   // what we do here is to update the hash or
+   // if hashing is not getting used we just accumulate it
+
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if(pPart == NULL_PTR || ulPartLen == 0){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+      CDigest* digest = session->_digestRSAVerification;
+      digest->HashCore(pPart,0,ulPartLen);
+   }
+   // Sign Only
+   else {
+
+      if(session->_accumulatedDataToVerify != NULL_PTR){
+         // just accumulate the data
+         u1Array* updatedData = new u1Array(session->_accumulatedDataToVerify->GetLength() + ulPartLen);
+         memcpy(updatedData->GetBuffer(),session->_accumulatedDataToVerify->GetBuffer(),session->_accumulatedDataToVerify->GetLength());
+
+         memcpy((u1*)&updatedData->GetBuffer()[session->_accumulatedDataToVerify->GetLength()],pPart,ulPartLen);
+
+         delete session->_accumulatedDataToVerify;
+
+         session->_accumulatedDataToVerify = updatedData;
+      }else{
+
+         session->_accumulatedDataToVerify = new u1Array(ulPartLen);
+         session->_accumulatedDataToVerify->SetBuffer(pPart);
+      }
+
+      CK_ULONG mech = session->_verification->GetMechanism();
+      u1Array* modulus = ((RSAPublicKeyObject*)session->_verification->GetObject())->_modulus;
+
+      if(((mech == CKM_RSA_PKCS) && (session->_accumulatedDataToVerify->GetLength() > modulus->GetLength() - 11)) ||
+         ((mech == CKM_RSA_X_509) && (session->_accumulatedDataToVerify->GetLength() > modulus->GetLength())))
+      {
+         return CKR_DATA_LEN_RANGE;
+      }
+   }
+
+   return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
+{
+   CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+   Slot* pSlot = NULL_PTR;
+   CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+   if(rv != CKR_OK)
+   {
+      return rv;
+   }
+   checkConnection( pSlot );
+
+   CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+   CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+   Transaction trans( pSlot );
+
+   Session* session = pSlot->_sessions[ hSessionId ];
+
+
+   if(session->IsVerificationActive() == CK_FALSE){
+      return CKR_OPERATION_NOT_INITIALIZED;
+   }
+
+   if((pSignature == NULL_PTR) || (ulSignatureLen == 0)){
+      return CKR_ARGUMENTS_BAD;
+   }
+
+   //StorageObject* object = session->_verification->GetObject();
+   //PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+
+   u1Array* dataToVerify = NULL_PTR;
+
+   if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+      // require hashing also
+      CK_BYTE_PTR hash   = NULL_PTR;
+      CDigest* digest = session->_digestRSAVerification;
+
+      hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+      digest->HashFinal(hash);
+
+      dataToVerify  = new u1Array(digest->HashLength());
+      dataToVerify->SetBuffer(hash);
+
+      free(hash);
+   }
+   // Sign Only
+   else {
+      dataToVerify = session->_accumulatedDataToVerify;
+   }
+
+   u1Array* signature = new u1Array(ulSignatureLen);
+   signature->SetBuffer(pSignature);
+
+   rv = pSlot->_token->Verify(session->_verification->GetObject(),dataToVerify,session->_verification->GetMechanism(),signature);
+
+   session->RemoveDigestRSAVerification();
+   session->RemoveVerificationOperation();
+
+   delete dataToVerify;
+   delete signature;
+   session->_accumulatedDataToVerify = NULL_PTR;
+
+   return rv;
+}
+
+
+
+// --------------
+
+
+
+/* Return true if the connection is aware
+*/
+/*bool*/ void Slot::checkConnection( Slot* a_pSlot )
+{
+   Log::begin( "Slot::checkConnection" );
+
+   //bool bRet = false;
+
+   if( NULL_PTR != a_pSlot )
+   {
+      char readers[ 1024 ];
+      memset( readers, 0, sizeof( readers ) );
+      memcpy( readers, a_pSlot->_readerName->c_str( ), a_pSlot->_readerName->length( ) );
+      DWORD dwLen = sizeof( readers );
+      DWORD dwState = 0;
+      DWORD dwProtocol = 0;
+      BYTE Atr[32];
+      memset( Atr, 0, sizeof( Atr ) );
+      DWORD dwLenAtr = sizeof( Atr );
+      if( NULL != a_pSlot->_token )
+      {
+         CardModuleService* pMSCM = a_pSlot->_token->GetMiniDriverService( );
+         if( NULL != pMSCM )
+         {
+            SCARDHANDLE hCard = pMSCM->GetPcscCardHandle( );
+            DWORD hResult = SCardStatus( hCard, readers, &dwLen, &dwState, &dwProtocol, &Atr[0], &dwLenAtr );
+            Log::log( "Slot::checkConnection - SCardStatus <%#02x>", hResult );
+            if( ( SCARD_W_RESET_CARD == hResult ) || ( SCARD_W_REMOVED_CARD == hResult ) )
+            {
+               Log::error( "Slot::checkConnection", "Connection is broken" );
+
+               // Close all session
+               a_pSlot->CloseAllSessions( );
+
+               // Rebuild the token to restablish the CardModule communication
+               delete a_pSlot->_token;
+               a_pSlot->_token = NULL_PTR;
+               a_pSlot->BuildToken( );
+
+              // bRet = false;
+            }
+         }
+      }
+   }
+
+   Log::end( "Slot::checkConnection" );
+
+   //return bRet;
+}
+
+
+CK_LONG Slot::AddSession(Session* session)
+{
+   // 0 is an invalid session handle
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] == NULL_PTR){
+         this->_sessions[i] = session;
+         session->UpdateState(this->_token->_roleLogged);
+         return (CK_LONG)i;
+      }
+   }
+
+   // No free elements, add a new
+   _sessions.push_back(session);
+   return (CK_LONG)(_sessions.size()-1);
+}
+
+
+/*
+*/
+void Slot::RemoveSession( CK_LONG sessionId )
+{
+   delete this->_sessions[ sessionId ];
+   this->_sessions[sessionId] = NULL_PTR;
+
+   // If this was the upper element in the vector, reduce size
+   size_t maxId = 0;
+   for( size_t i = 1 ; i < _sessions.size( ) ; i++ )
+   {
+      if( _sessions[ i ] )
+      {
+         maxId = i;
+      }
+   }
+   if( maxId < _sessions.size( ) - 1 )
+   {
+      _sessions.resize( maxId + 1 );
+   }
+
+   // if this was the last session to be removed
+   // then the login state of token for application
+   // returns to public sessions
+   if( 0 == maxId )
+   {
+      // TBD : Should I call logout here or merely set the flag ?
+      // if I logged the user out from this application
+      // what happens to another application
+      // This is where on-card implementation helps
+
+      PKCS11_ASSERT(this->_token != NULL_PTR);
+
+      this->_token->_roleLogged = CKU_NONE;
+   }
+}
+
+void Slot::UpdateSessionState()
+{
+   // update the state of all sessions
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] != NULL_PTR){
+         this->_sessions[i]->UpdateState(this->_token->_roleLogged);
+      }
+   }
+}
+
+CK_BBOOL Slot::HasReadOnlySession()
+{
+   for(size_t i=1;i<_sessions.size();i++){
+      if(this->_sessions[i] != NULL_PTR){
+         if(this->_sessions[i]->_isReadWrite == CK_FALSE){
+            return CK_TRUE;
+         }
+      }
+   }
+
+   return CK_FALSE;
+}
+
+CK_RV Slot::GetSlotAndSessionIdFromSessionHandle(CK_SESSION_HANDLE hSession,
+                                                 Slot** slot,
+                                                 CK_ULONG_PTR sessionId)
+{
+   CK_SLOT_ID slotId  = GET_SLOTID(hSession);
+   *sessionId         = GET_SESSIONID(hSession);
+
+   if(((int)slotId < 0) || (slotId >= CONFIG_MAX_SLOT)){
+      // we return here invalid session handle as
+      // app does not have a notion of slot at this time
+      return CKR_SESSION_HANDLE_INVALID;
+   }
+
+   if (Application::_slotCache[slotId] != NULL_PTR){
+      *slot = Application::_slotCache[slotId];
+
+      if((*sessionId < 1) || (*sessionId >= ((*slot)->_sessions.size()))){
+         return CKR_SESSION_HANDLE_INVALID;
+      }
+      if((*slot)->_sessions[*sessionId]) {
+         return CKR_OK;
+      }
+   }
+
+   return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV Slot::BuildToken(void)
+{
+   Log::begin( "Slot::BuildToken" );
+
+   if(this->_token == NULL_PTR)
+   {
+      SCARD_READERSTATE readerStates;
+      memset( &readerStates, 0, sizeof( SCARD_READERSTATE ) );
+      readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+      readerStates.szReader = this->_readerName->c_str( );
+
+#ifndef _XCL_
+
+      if( SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+      {
+         if ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)
+         {
+            // we not found a card in this reader
+            this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+            Log::log( "Slot::BuildToken - ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)" );
+            Log::logCK_RV( "Slot::BuildToken", CKR_TOKEN_NOT_PRESENT );
+            return CKR_TOKEN_NOT_PRESENT;
+         }
+         else
+         {
+            // we found a card in this reader
+            this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+         }
+      }
+
+#else // _XCL_
+
+      if (xCL_IsTokenPresent())
+      {
+          // we found a card in this reader
+          this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+      }
+      else
+      {
+          // we not found a card in this reader
+          this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+          return CKR_TOKEN_NOT_PRESENT;
+      }
+
+#endif // _XCL_
+
+      // TBD: Check if token is a .net smart card
+
+      // token is present in the slot
+      Log::log( "Slot::BuildToken - new Token..." );
+      this->_token = new Token( this->_readerName );
+      Log::log( "Slot::BuildToken - new Token ok"  );
+
+      Log::logCK_RV( "Slot::BuildToken", CKR_OK );
+      Log::end( "Slot::BuildToken" );
+   }
+
+   return CKR_OK;
+}
+
+
+CK_RV Slot::IsValidMechanism(CK_ULONG mechanism,CK_ULONG operation)
+{
+   size_t i = 0;
+
+   CK_BBOOL found = CK_FALSE;
+
+   for(;i<sizeof(MechanismList)/sizeof(CK_ULONG);i++){
+      if(MechanismList[i] == mechanism){
+         found = CK_TRUE;
+         break;
+      }
+   }
+
+   if(found == CK_FALSE){
+      return CKR_MECHANISM_INVALID;
+   }
+
+   if((MechanismInfo[i].flags & operation) != operation){
+      return CKR_MECHANISM_INVALID;
+   }
+
+   return CKR_OK;
+}
+
+CK_RV Slot::IsValidCryptoOperation(StorageObject* object,CK_ULONG operation)
+{
+   // Check if key is consistent
+   switch(operation)
+   {
+   case CKF_ENCRYPT:
+   case CKF_VERIFY:
+   case CKF_VERIFY_RECOVER:
+      if(object->_class != CKO_PUBLIC_KEY && object->_class != CKO_SECRET_KEY){
+         return CKR_KEY_TYPE_INCONSISTENT;
+      }
+      break;
+
+   case CKF_DECRYPT:
+   case CKF_SIGN:
+   case CKF_SIGN_RECOVER:
+      if(object->_class != CKO_PRIVATE_KEY && object->_class != CKO_SECRET_KEY){
+         return CKR_KEY_TYPE_INCONSISTENT;
+      }
+      break;
+   }
+
+   // Check if key supports the operation
+   switch(operation)
+   {
+   case CKF_ENCRYPT:
+      if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_encrypt))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_encrypt))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   case CKF_DECRYPT:
+      if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_decrypt))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_decrypt))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   case CKF_VERIFY:
+      if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_verify))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_verify))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+
+   case CKF_VERIFY_RECOVER:
+      if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_verifyRecover))){
+         return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+
+   case CKF_SIGN:
+      if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_sign))
+#ifdef ENABLE_SYMMETRIC
+         ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_sign))
+#endif
+         ){
+            return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   case CKF_SIGN_RECOVER:
+      if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_signRecover))){
+         return CKR_KEY_FUNCTION_NOT_PERMITTED;
+      }
+      break;
+
+   }
+
+   return CKR_OK;
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,413 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_slot_h
+#define _include_slot_h
+
+#include "sctoken.h"
+#include "critsect.h"
+
+#ifdef _XCL_
+#include "xcl_public.h"
+#include <xcl_utils.h>
+#endif // _XCL
+
+class CardMonitoringThread;
+
+class Slot {
+
+public:
+   CK_SLOT_ID              _slotId;
+   CK_SLOT_INFO            _slotInfo;
+   std::string*            _readerName;
+   CK_BBOOL                _event;
+   CardMonitoringThread*   _tracker;
+   vector<Session*>        _sessions;
+   Token*                  _token;
+
+private:
+   CK_LONG AddSession(Session* session);
+   void RemoveSession(CK_LONG sessionId);
+   CK_BBOOL HasReadOnlySession();
+   static /*bool*/ void checkConnection( Slot* a_pSlot );
+
+public:
+   Slot();
+   virtual ~Slot();
+
+   void UpdateSessionState();
+   void UpdateAuthenticationState( void );
+
+   static void ClearCache(void);
+   static CK_RV GetSlotAndSessionIdFromSessionHandle(CK_SESSION_HANDLE hSession,
+      Slot** slot,CK_ULONG_PTR sessionId);
+
+   static CK_RV IsValidMechanism(CK_ULONG mechanism,CK_ULONG operation);
+   static CK_RV IsValidCryptoOperation(StorageObject* object,CK_ULONG operation);
+
+   CK_BBOOL    GetEvent();
+   void        SetEvent(CK_BBOOL event);
+   CK_SLOT_ID  GetSlotId() { return _slotId;}
+   CK_BBOOL    IsCardPresent() { return ((_slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);}
+   void        Clear(void);
+
+   CK_RV  BuildToken(void);
+
+   CK_RV  GetInfo(CK_SLOT_INFO_PTR pInfo);
+   CK_RV  GetTokenInfo(CK_TOKEN_INFO_PTR pInfo);
+   CK_RV  GetMechanismList(CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount);
+   CK_RV  GetMechanismInfo(CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo);
+   CK_RV  OpenSession(CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession);
+   static CK_RV  CloseSession(CK_SESSION_HANDLE hSession);
+   CK_RV  CloseAllSessions(void);
+   static CK_RV  GetSessionInfo(CK_SESSION_HANDLE hSession,CK_SESSION_INFO_PTR pInfo);
+
+   static CK_RV  Login(CK_SESSION_HANDLE hSession,CK_USER_TYPE userType,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen);
+   static CK_RV  Logout(CK_SESSION_HANDLE hSession);
+
+   CK_RV InitToken(CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel);
+   static CK_RV  InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen);
+   static CK_RV  SetPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pOldPin,CK_ULONG ulOldLen,
+      CK_UTF8CHAR_PTR pNewPin,CK_ULONG ulNewLen);
+
+   static CK_RV  CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject);
+   static CK_RV  DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject);
+   static CK_RV  GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE  hObject,CK_ATTRIBUTE_PTR  pTemplate,CK_ULONG ulCount);
+   static CK_RV  SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+   static CK_RV  FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR  pTemplate,CK_ULONG ulCount);
+   static CK_RV  FindObjects(CK_SESSION_HANDLE  hSession, CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR  pulObjectCount);
+   static CK_RV  FindObjectsFinal(CK_SESSION_HANDLE hSession);
+
+   static CK_RV  GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR RandomData,CK_ULONG ulRandomLen);
+
+   static CK_RV  GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+      CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,
+      CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey);
+
+   //static CK_RV  WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR  pMechanism,
+   //                      CK_OBJECT_HANDLE  hWrappingKey,CK_OBJECT_HANDLE  hKey,
+   //                      CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen);
+
+   //static CK_RV  UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,
+   //                       CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,
+   //                       CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,
+   //                       CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey);
+
+   static CK_RV  EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE  hKey);
+   static CK_RV  Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen);
+
+   static CK_RV  DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR  pMechanism,CK_OBJECT_HANDLE  hKey);
+   static CK_RV  Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen);
+
+   static CK_RV  SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+   static CK_RV  Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen);
+   static CK_RV  SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+   static CK_RV  SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen);
+
+   static CK_RV  VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+   static CK_RV  Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen);
+   static CK_RV  VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+   static CK_RV  VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen);
+   //static CK_RV  VerifyRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+   //static CK_RV  VerifyRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen);
+
+   static CK_RV  DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism);
+   static CK_RV  Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen);
+   static CK_RV  DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+   static CK_RV  DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen);
+};
+
+#define CARD_PRESENT 1
+#define CARD_ABSENT  2
+
+#define CARD_DETECTION_INSERTED 1
+#define CARD_DETECTION_REMOVED  2
+
+
+#ifdef INCLUDE_EVENTING
+
+extern CCriticalSection _critSect;
+
+class CardMonitoringThread : public CThread
+{
+
+private:
+   CK_BYTE m_bCardState;
+   Slot*   m_slot;
+   SCARDCONTEXT m_hMonitoringContext;
+
+public:
+   // CThread override
+   void stop()
+   {
+      //printf( "%s - %d - %s - m_monitoringContext <%ld>\n", __FILE__, __LINE__, __FUNCTION__, m_hMonitoringContext );
+
+#ifndef _XCL_
+
+      if( 0 != m_hMonitoringContext )
+      {
+         SCardCancel(m_hMonitoringContext);
+         //printf( "%s - %d - %s - SCardCancel\n", __FILE__, __LINE__, __FUNCTION__);
+
+         /*
+         printf( "%s - %d - %s - SCardReleaseContext -->\n", __FILE__, __LINE__, __FUNCTION__);
+         SCardReleaseContext(m_hMonitoringContext);
+         printf( "%s - %d - %s - SCardReleaseContext <--\n", __FILE__, __LINE__, __FUNCTION__);
+         m_hMonitoringContext = 0;
+         */
+      }
+
+#endif // _XCL_
+
+      CThread::stop();
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+   CardMonitoringThread(const char* nm) //: m_hMonitoringContext(0)
+   {
+      m_hMonitoringContext = 0;
+      m_bCardState = CARD_ABSENT;
+      CThread::setName(nm);
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+   void SetSlot(Slot* slot)
+   {
+      m_slot = slot;
+
+      if(slot->IsCardPresent() == CK_FALSE)
+      {
+         m_bCardState = CARD_ABSENT;
+      }
+      else
+      {
+         m_bCardState = CARD_PRESENT;
+      }
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+   void run()
+   {
+      bool bTrue = true;
+      while( bTrue )
+      {
+         switch(m_bCardState)
+         {
+         case CARD_PRESENT:
+            if(Monitor(CARD_DETECTION_REMOVED) == false)
+            {
+               return;
+            }
+            m_bCardState = CARD_ABSENT;
+
+            // clean the slot, lock during session deletion
+            {
+               CCriticalSectionLocker cslock(_critSect);
+               m_slot->Clear();
+            }
+            break;
+
+         case CARD_ABSENT:
+            if(Monitor(CARD_DETECTION_INSERTED) == false)
+            {
+               return;
+            }
+            m_bCardState = CARD_PRESENT;
+            break;
+         }
+
+         // we fire the event from here
+         m_slot->SetEvent(CK_TRUE);
+         CryptokiEvent.Signal();
+      }
+   }
+
+   //------------------------------------------------------------------------------
+   //------------------------------------------------------------------------------
+
+#ifndef _XCL_
+
+   bool Monitor(BYTE detectionType)
+   {
+
+      // establish monitoring context
+      LONG lReturn = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &m_hMonitoringContext );
+      //printf( "%s - %d - %s - SCardEstablishContext --> m_hMonitoringContext <%ld>\n", __FILE__, __LINE__,  __FUNCTION__, m_hMonitoringContext);
+
+      //LONG lReturn = SCardEstablishContext(0, NULL, NULL, (LPSCARDCONTEXT)&m_monitoringContext);
+
+      if(lReturn != SCARD_S_SUCCESS)
+      {
+         return false;
+      }
+
+      SCARD_READERSTATE readerStates;
+      readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+      readerStates.szReader       = this->getName()->c_str();
+      readerStates.pvUserData     = NULL;
+      readerStates.dwEventState   = 0;         // TO INSPECT THIS STATE
+
+      bool bTrue = true;
+      while( bTrue )
+      {
+
+         if((lReturn = SCardGetStatusChange( m_hMonitoringContext, 60*1000, &readerStates, 1 )) != SCARD_S_SUCCESS)
+         {
+            if(lReturn == (LONG)SCARD_E_TIMEOUT)
+            {
+               if(this->isStopRequested() == CK_TRUE)
+               {
+                  SCardReleaseContext(m_hMonitoringContext);
+                  //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+                  m_hMonitoringContext = 0;
+                  return false;
+               }
+
+               goto resume;
+            }
+
+            SCardReleaseContext(m_hMonitoringContext);
+            //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+            m_hMonitoringContext = 0;
+            return false;
+         }
+
+resume:
+         if((readerStates.dwEventState & SCARD_STATE_CHANGED) == SCARD_STATE_CHANGED)
+         {
+            if((readerStates.dwEventState & SCARD_STATE_UNAVAILABLE) == SCARD_STATE_UNAVAILABLE)
+            {
+               // reader removed
+               SCardReleaseContext(m_hMonitoringContext);
+               //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+               m_hMonitoringContext = 0;
+               return true;
+            }
+            else if(((readerStates.dwCurrentState & SCARD_STATE_EMPTY) == SCARD_STATE_EMPTY) &&
+               ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT))
+            {
+               if(detectionType == CARD_PRESENT)
+               {
+                  // card is inserted
+                  SCardReleaseContext(m_hMonitoringContext);
+                  //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+                  m_hMonitoringContext = 0;
+                  return true;
+               }
+            }
+            else if(((readerStates.dwCurrentState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT) &&
+               ((readerStates.dwEventState & SCARD_STATE_EMPTY) == SCARD_STATE_EMPTY))
+            {
+               if(detectionType == CARD_ABSENT)
+               {
+                  // card is removed
+                  SCardReleaseContext(m_hMonitoringContext);
+                  //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+                  m_hMonitoringContext = 0;
+                  return true;
+               }
+            }
+         }
+
+         readerStates.dwCurrentState = readerStates.dwEventState ;
+      }
+
+      SCardReleaseContext(m_hMonitoringContext);
+      //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+      m_hMonitoringContext = 0;
+      return false;
+   }
+
+#else // _XCL_
+
+    bool Monitor(BYTE detectionType)
+    {
+        BOOL initialTokenPresent;
+        BOOL currentTokenPresent;
+        UINT rv;
+        UINT deviceID2;
+        xCL_DeviceHandle deviceHandle2;
+
+        PRINT_MSG("IN Monitor top");
+
+        initialTokenPresent = false;
+        currentTokenPresent = false;
+
+        deviceHandle2 = 0;
+        deviceID2 = 0;
+        rv = xCL_CreateHandleFromDeviceID(deviceID2, &deviceHandle2);
+        if (rv == 0)
+        {
+            initialTokenPresent = true;
+            currentTokenPresent = true;
+        }
+        rv = xCL_CloseHandle(deviceHandle2);
+
+        while(true)
+        {
+            PRINT_MSG("IN Monitor loop");
+
+            // sleep for some time
+            sleep(500);
+
+            // See if token is present now
+            deviceHandle2 = 0;
+            deviceID2 = 0;
+            rv = xCL_CreateHandleFromDeviceID(deviceID2, &deviceHandle2);
+            if (rv == 0)
+            {
+                currentTokenPresent = true;
+                rv = xCL_CloseHandle(deviceHandle2);
+            }
+            else
+            {
+                currentTokenPresent = false;
+            }
+
+            if (initialTokenPresent == currentTokenPresent)
+            {
+                PRINT_MSG("IN Monitor no change");
+
+                // No change in token state
+                if(this->isStopRequested() == CK_TRUE)
+                {
+                    PRINT_MSG("IN Monitor no change exit");
+                    return false;
+                }
+            }
+            else
+            {
+                PRINT_MSG("IN Monitor yes change");
+                // There is a change ...
+                return true;
+            }
+        }
+    }
+
+#endif // _XCL_
+
+};
+#endif
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,41 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+
+// Determine Processor Endianess
+#include <limits.h>
+#if (UINT_MAX == 0xffffffffUL)
+   typedef unsigned int _u4;
+#else
+#  if (ULONG_MAX == 0xffffffffUL)
+     typedef unsigned long _u4;
+#  else
+#    if (USHRT_MAX == 0xffffffffUL)
+       typedef unsigned short _u4;
+#    endif
+#  endif
+#endif
+
+_u4 endian = 1;
+
+bool IS_LITTLE_ENDIAN = (*((unsigned char *)(&endian))) ? true  : false;
+bool IS_BIG_ENDIAN    = (*((unsigned char *)(&endian))) ? false : true;
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,50 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_stadfx_h
+#define _include_stadfx_h
+
+#ifdef WIN32
+    #include <windows.h>
+    #include <wincrypt.h>
+    #include <assert.h>
+#else
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <string.h>
+	#ifdef __APPLE__
+    #include <wintypes.h>
+    #endif
+    #include <winscard.h>
+    typedef BYTE *PBYTE;
+#ifndef HAVE_LPCTSTR
+    typedef const char *LPCTSTR;
+#endif
+#ifndef HAVE_LPCSTR
+    typedef LPCTSTR LPCSTR;
+#endif
+
+#endif
+
+extern bool IS_BIG_ENDIAN;
+extern bool IS_LITTLE_ENDIAN;
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,373 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+#include "storageobject.h"
+#include "error.h"
+
+StorageObject::StorageObject()
+{
+    this->_version     = 0;
+    this->_uniqueId    = 0;
+    this->_tokenObject = CK_FALSE;
+    this->_private     = CK_FALSE;
+    this->_modifiable  = CK_TRUE;
+    this->_label       = NULL_PTR;
+}
+
+StorageObject::~StorageObject(){
+
+    if(this->_label != NULL_PTR)
+        delete this->_label;
+
+}
+
+bool StorageObject::IsEqual(const StorageObject * that) const
+{
+    if(_uniqueId != 0 && that->_uniqueId != 0)
+        return (_uniqueId == that->_uniqueId);
+
+    // Only objects that have been stored under p11 directory
+    // will have a non-zero _uniqueId. For other objects, do
+    // a deep comparison based on other attributes. In the base
+    // class, only negative comparison based on _class can be performed.
+    if(_class != that->_class)
+        return false;
+    else
+        throw CkError(CKR_FUNCTION_FAILED);
+}
+
+CK_BBOOL StorageObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+        case CKA_CLASS:
+            return (this->_class == *(CK_ULONG*)attribute.pValue);
+
+        case CKA_PRIVATE:
+            return (this->_private == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_TOKEN:
+            return (this->_tokenObject == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_MODIFIABLE:
+            return (this->_modifiable == *(CK_BBOOL*)attribute.pValue);
+
+        case CKA_LABEL:
+            if(this->_label->GetLength() == attribute.ulValueLen){
+                return Util::CompareByteArrays(this->_label->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+            }
+            return CK_FALSE;
+
+        default:
+            return CK_FALSE;
+
+    }
+}
+
+CK_RV StorageObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+    CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_CLASS:
+            case CKA_PRIVATE:
+            case CKA_TOKEN:
+            case CKA_MODIFIABLE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+        case CKA_CLASS:
+            break;
+
+        case CKA_PRIVATE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_private = btemp; }
+            }
+            break;
+
+        case CKA_TOKEN:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_tokenObject = btemp; }
+            }
+            break;
+
+        case CKA_MODIFIABLE:
+            {
+                CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){ this->_modifiable = btemp; }
+            }
+            break;
+
+        case CKA_LABEL:
+            {
+                u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_label != NULL_PTR){
+                        delete this->_label;
+                    }
+                    this->_label = stemp;
+                }
+            }
+            break;
+
+        default:
+            return CKR_ATTRIBUTE_TYPE_INVALID;
+
+    }
+
+    return rv;
+}
+
+CK_RV StorageObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+   CK_RV ulRet = CKR_OK;
+
+    switch(attribute->type)
+    {
+        case CKA_CLASS:
+            ulRet = StorageObject::PutULongInAttribute(this->_class,attribute);
+            break;
+
+        case CKA_PRIVATE:
+            ulRet = StorageObject::PutBBoolInAttribute(this->_private,attribute);
+            break;
+
+        case CKA_TOKEN:
+            ulRet = StorageObject::PutBBoolInAttribute(this->_tokenObject,attribute);
+            break;
+
+        case CKA_MODIFIABLE:
+            ulRet = StorageObject::PutBBoolInAttribute(this->_modifiable,attribute);
+            break;
+
+        case CKA_LABEL:
+            ulRet = StorageObject::PutU1ArrayInAttribute(this->_label,attribute);
+            break;
+
+        default:
+           attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+           ulRet = CKR_ATTRIBUTE_TYPE_INVALID;
+           break;
+    }
+
+    return ulRet;
+}
+
+void StorageObject::Serialize(std::vector<u1>* to)
+{
+    // serialize format version
+    Util::PushBBoolInVector(to,this->_version);
+
+    // serialize unique id
+    Util::PushULongLongInVector(to,this->_uniqueId);
+
+    // serialize class attribute
+    Util::PushULongInVector(to,this->_class);
+
+    // serialize private attribute
+    Util::PushBBoolInVector(to,this->_private);
+
+    // serialize token attribute
+    Util::PushBBoolInVector(to,this->_tokenObject);
+
+    // serialize modifiable attribute
+    Util::PushBBoolInVector(to,this->_modifiable);
+
+    // serialize label attribute
+    Util::PushByteArrayInVector(to,this->_label);
+}
+
+void StorageObject::Deserialize(std::vector<u1> from,CK_ULONG_PTR idx)
+{
+    this->_version = Util::ReadBBoolFromVector(from,idx);
+
+    this->_uniqueId = Util::ReadULongLongFromVector(from, idx);
+
+    this->_class = Util::ReadULongFromVector(from,idx);
+
+    this->_private = Util::ReadBBoolFromVector(from,idx);
+
+    this->_tokenObject = Util::ReadBBoolFromVector(from,idx);
+
+    this->_modifiable = Util::ReadBBoolFromVector(from,idx);
+
+    this->_label = Util::ReadByteArrayFromVector(from,idx);
+}
+
+CK_RV StorageObject::PutU1ArrayInAttribute(u1Array* value,CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        if(value == NULL_PTR){
+            attribute->ulValueLen = 0;
+        }else{
+            attribute->ulValueLen = value->GetLength();
+        }
+        return CKR_OK;
+    }
+    if(value == NULL_PTR){
+        // I am not sure about it (TBD: Check)
+        attribute->ulValueLen = 0;
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < value->GetLength()){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+
+    attribute->ulValueLen = value->GetLength();
+    memcpy((CK_BYTE_PTR)attribute->pValue,value->GetBuffer(),attribute->ulValueLen);
+
+    return CKR_OK;
+}
+
+CK_RV StorageObject::PutU4ArrayInAttribute(u4Array* value,CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        if(value == NULL_PTR){
+            attribute->ulValueLen = 0;
+        }else{
+            attribute->ulValueLen = (value->GetLength() * 4);
+        }
+        return CKR_OK;
+    }
+    if(value == NULL_PTR){
+        // I am not sure about it (TBD: Check)
+        attribute->ulValueLen = 0;
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < (value->GetLength() * 4)){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+
+    attribute->ulValueLen = value->GetLength() * 4;
+    memcpy((CK_BYTE_PTR)attribute->pValue,(u1*)value->GetBuffer(),attribute->ulValueLen);
+
+    return CKR_OK;
+}
+
+CK_RV StorageObject::PutBBoolInAttribute(CK_BBOOL value, CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        attribute->ulValueLen = sizeof(CK_BBOOL);
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < sizeof(CK_BBOOL)){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+    attribute->ulValueLen = sizeof(CK_BBOOL);
+    *(CK_BBOOL*)attribute->pValue = value;
+
+    return CKR_OK;
+}
+
+CK_RV StorageObject::PutULongInAttribute(CK_ULONG value, CK_ATTRIBUTE_PTR attribute)
+{
+    if(attribute->pValue == NULL_PTR){
+        attribute->ulValueLen = sizeof(CK_ULONG);
+        return CKR_OK;
+    }
+    if(attribute->ulValueLen < sizeof(CK_ULONG)){
+        attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+        return CKR_BUFFER_TOO_SMALL;
+    }
+    attribute->ulValueLen = sizeof(CK_ULONG);
+    *(CK_ULONG*)attribute->pValue = value;
+
+    return CKR_OK;
+}
+
+CK_ULONG StorageObject::ReadULongFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+    if(attribute.ulValueLen != sizeof(CK_ULONG)){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return 0;
+    }
+
+    return *(CK_ULONG*)attribute.pValue;
+}
+
+CK_BBOOL StorageObject::ReadBBoolFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+    if(attribute.ulValueLen != sizeof(CK_BBOOL)){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return 0;
+    }
+
+    CK_BBOOL val = *(CK_BBOOL*)attribute.pValue;
+
+    if(val != 0x00 && val != 0x01){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return 0;
+    }
+
+    return val;
+}
+
+u1Array* StorageObject::ReadU1ArrayFromAttribute(CK_ATTRIBUTE attribute)
+{
+    u1Array* val = new u1Array(attribute.ulValueLen);
+    val->SetBuffer((CK_BYTE_PTR)attribute.pValue);
+
+    return val;
+}
+
+u1Array* StorageObject::ReadDateFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+    if(attribute.ulValueLen != 8){
+        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+        return NULL_PTR;
+    }
+
+    return StorageObject::ReadU1ArrayFromAttribute(attribute);
+}
+
+u1Array* StorageObject::ReadStringFromAttribute(CK_ATTRIBUTE attribute,CK_RV* /*rv*/)
+{
+
+    // [HB]: Shall support UTF-8
+
+    //for(u4 i=0;i<attribute.ulValueLen;i++){
+
+    //    CK_BYTE bval = ((CK_BYTE_PTR)attribute.pValue)[i];
+
+    //    if((bval < 0x20)||(bval > 0x7D)||(bval == 0x24)||(bval == 0x40)||(bval == 0x60)){
+    //        *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+    //        return NULL_PTR;
+    //    }
+    //}
+
+    return StorageObject::ReadU1ArrayFromAttribute(attribute);
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_storageobject_h
+#define _include_storageobject_h
+
+#include <string>
+#include <MarshallerCfg.h>
+#include <Array.h>
+#include <vector>
+
+using namespace std;
+using namespace Marshaller;
+
+class StorageObject {
+
+
+public:
+    CK_BBOOL        _version;       // Version is used to manage evolution of the storage.
+    u8              _uniqueId;      // A random number that identifies this object
+    CK_ULONG		_class;
+    CK_BBOOL		_tokenObject;
+    CK_BBOOL		_private;
+    CK_BBOOL		_modifiable;
+    u1Array*		_label;
+
+    // extra fields (not part of PKCS#11 spec
+    std::string     _fileName;      // name of the file in the card which contains this object
+
+    StorageObject();
+    virtual ~StorageObject();
+
+    virtual bool IsEqual(const StorageObject * that) const;
+    virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    virtual void Serialize(vector<u1>* to);
+    virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+protected:
+    static CK_RV PutU1ArrayInAttribute(u1Array* value,CK_ATTRIBUTE_PTR attribute);
+    static CK_RV PutU4ArrayInAttribute(u4Array* value,CK_ATTRIBUTE_PTR attribute);
+    static CK_RV PutULongInAttribute(CK_ULONG value, CK_ATTRIBUTE_PTR attribute);
+    static CK_RV PutBBoolInAttribute(CK_BBOOL value, CK_ATTRIBUTE_PTR attribute);
+
+    static CK_BBOOL ReadBBoolFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+    static CK_ULONG ReadULongFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+    static u1Array* ReadU1ArrayFromAttribute(CK_ATTRIBUTE attribute);
+    static u1Array* ReadDateFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+    static u1Array* ReadStringFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+};
+
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,224 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+
+CSymmAlgo::CSymmAlgo(){
+    this->_cipherMode  = CIPHER_MODE_CBC;
+    this->_paddingMode = PADDING_MODE_PKCS7;
+    this->_iv          = NULL_PTR;
+    this->_key         = NULL_PTR;
+}
+
+CSymmAlgo::~CSymmAlgo(){
+    if(this->_key != NULL_PTR)
+        free(this->_key);
+}
+
+void CSymmAlgo::SetKey(CK_BYTE_PTR key,CK_LONG keyLength){
+    this->_key       = (CK_BYTE_PTR)malloc(keyLength);
+    this->_keyLength = keyLength;
+
+    memcpy(this->_key,key,keyLength);
+}
+
+void CSymmAlgo::SetIV(CK_BYTE_PTR iv){
+    this->_iv = iv;
+}
+
+void CSymmAlgo::SetEncryptMode(CK_LONG mode){
+    this->_encryptMode = mode;
+}
+
+void CSymmAlgo::SetCipherMode(CK_LONG cmode){
+    this->_cipherMode = cmode;
+}
+
+void CSymmAlgo::SetPaddingMode(CK_LONG pmode){
+    this->_paddingMode = pmode;
+}
+
+CK_LONG CSymmAlgo::GetOutputLength(CK_LONG input_count){
+
+    CK_LONG outputLen;
+
+    if(this->_encryptMode == ENCRYPT){
+        outputLen = input_count & -this->_blockSize;
+
+        switch(this->_paddingMode){
+
+            case PADDING_MODE_ISO9797M2:
+            case PADDING_MODE_PKCS7:
+                // atleast 1 padding byte will be needed
+                if(input_count >= outputLen){
+                    outputLen += this->_blockSize;
+                }
+                break;
+
+            case PADDING_MODE_ZEROS:
+                if(input_count > outputLen){
+                    outputLen += this->_blockSize;
+                }
+                break;
+
+            case PADDING_MODE_NONE:
+                outputLen = input_count;
+                break;
+        }
+    }else{
+        outputLen = input_count;
+    }
+
+    return outputLen;
+}
+
+CK_LONG CSymmAlgo::TransformBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                                  CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    CK_LONG res = 0;
+    while (res != input_count)
+    {
+        TransformBlockInternal(_iv,_key,_encryptMode,input,input_offset,output,output_offset);
+
+        if (_cipherMode == CIPHER_MODE_CBC)
+        {
+            if (_encryptMode == ENCRYPT){
+                // last block of output becomes icv for next round.
+                memcpy(_iv,&output[output_offset],_blockSize);
+            }
+            else {
+                // last block of input becomes icv for next round.
+                memcpy(_iv,&input[input_offset],_blockSize);
+            }
+        }
+
+        // adjust offsets
+        input_offset += _blockSize;
+        res += _blockSize;
+        output_offset += _blockSize;
+    }
+
+    return res;
+}
+
+CK_LONG CSymmAlgo::TransformFinalBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                                       CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    CK_LONG workingLength;
+
+    if (((this->_paddingMode == PADDING_MODE_NONE) ||
+         (this->_encryptMode == DECRYPT)) &&
+         (input_count % _blockSize != 0))
+    {
+        PKCS11_ASSERT(CK_FALSE);
+    }
+
+    // prepare outbuffer in case of encryption
+    if (this->_encryptMode == ENCRYPT)
+    {
+        // ~ round_down(inputCount, _blockSizeByte)
+        workingLength = input_count & -_blockSize;
+    }
+    else
+    {
+        // we're in Decrypt mode, hence workingLength is % _blockSizeByte
+        workingLength = input_count;
+    }
+
+    if (workingLength > 0)
+    {
+        // compute the workingLength length part (% _blockSizeByte)
+        TransformBlock(input,input_offset, workingLength,output,output_offset);
+
+        input_offset += workingLength;
+        output_offset += workingLength;
+        input_count -= workingLength;
+    }
+
+    if (this->_encryptMode == DECRYPT)
+    {
+        switch (this->_paddingMode)
+        {
+            case PADDING_MODE_PKCS7:
+                // check the padding value make sense
+                if (output[output_offset - 1] > _blockSize){
+                    PKCS11_ASSERT(CK_FALSE);
+                }
+                workingLength -= output[output_offset - 1];
+                break;
+
+            case PADDING_MODE_ISO9797M2:
+                // remove trailing zeros
+                while (output[output_offset - 1] == 0x00){
+                    workingLength--;
+                    output_offset--;
+                }
+                // check initial byte is 0x80
+                if (output[output_offset - 1] != 0x80){
+                    PKCS11_ASSERT(CK_FALSE);
+                }
+                workingLength--;
+                break;
+
+            // note when PaddingMode.Zeros is used, we do not remove the 0s (no way to differentiate from the actual data)
+        }
+    }
+    else
+    {
+        if ((this->_paddingMode == PADDING_MODE_PKCS7)
+            || (this->_paddingMode == PADDING_MODE_ISO9797M2)
+            || ((this->_paddingMode == PADDING_MODE_ZEROS) && (input_count > 0)))
+        {
+            CK_BYTE_PTR paddedIntput = (CK_BYTE_PTR)malloc(_blockSize);
+            memset(paddedIntput,0,_blockSize);
+
+            memcpy(paddedIntput,&input[input_offset],input_count);
+
+            // add padding information in buffer if relevant
+            switch (this->_paddingMode)
+            {
+                // set first bit to 1, all other bits already set to 0
+                case PADDING_MODE_ISO9797M2:
+                    paddedIntput[input_count] = 0x80;
+                    break;
+
+                case PADDING_MODE_PKCS7:
+                    CK_BYTE paddingValue = (CK_BYTE)(_blockSize - input_count);
+                    for (CK_LONG i = input_count; i < _blockSize; i++){
+                        paddedIntput[i] = paddingValue;
+                    }
+                    break;
+            }
+
+            // compute last block
+            TransformBlock(paddedIntput, 0, _blockSize, output, output_offset);
+
+            workingLength += _blockSize;
+
+            free(paddedIntput);
+        }
+    }
+
+    // over, let's return.
+    return workingLength;
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,72 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_symmalgo_h
+#define _include_symmalgo_h
+
+#define PADDING_MODE_ISO9797M2 1
+#define PADDING_MODE_NONE      2
+#define PADDING_MODE_PKCS7     3
+#define PADDING_MODE_ZEROS     4
+
+#define ENCRYPT 1
+#define DECRYPT 2
+
+#define CIPHER_MODE_CBC 1
+#define CIPHER_MODE_ECB 2
+
+class CSymmAlgo
+{
+
+protected:
+    CK_BYTE_PTR _iv;
+    CK_BYTE_PTR _key;
+    CK_LONG     _keyLength;
+    CK_LONG     _blockSize;
+    CK_LONG     _cipherMode;
+    CK_LONG     _paddingMode;
+    CK_LONG     _encryptMode;
+
+protected:
+    virtual void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                           CK_BYTE_PTR input,CK_LONG input_offset,
+                                           CK_BYTE_PTR output,CK_LONG output_offset) = 0;
+
+public:
+    CSymmAlgo();
+    virtual ~CSymmAlgo();
+
+    void SetKey(CK_BYTE_PTR key,CK_LONG keyLength);
+    void SetIV(CK_BYTE_PTR iv);
+    void SetEncryptMode(CK_LONG mode);
+    void SetCipherMode(CK_LONG cmode);
+    void SetPaddingMode(CK_LONG pmode);
+
+    CK_LONG GetOutputLength(CK_LONG input_count);
+
+    CK_LONG TransformBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                           CK_BYTE_PTR output,CK_LONG output_offset);
+
+    CK_LONG TransformFinalBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+                                CK_BYTE_PTR output,CK_LONG output_offset);
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+#include "tdes.h"
+
+CTripleDES::CTripleDES(){
+    this->_blockSize = 8;
+}
+
+CTripleDES::~CTripleDES(){
+}
+
+void CTripleDES::TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                        CK_BYTE_PTR input,CK_LONG input_offset,
+                                        CK_BYTE_PTR output,CK_LONG output_offset)
+{
+    // encryprtMode == ENCRYPT then we need to XOR input with iv
+    if(iv != NULL_PTR && this->_encryptMode == ENCRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            input[input_offset+i] ^= iv[i];
+        }
+    }
+
+    algo_DES_3DESProcess((u1)_keyLength,key,&input[input_offset],&output[output_offset],(u1)encryptMode);
+
+    if(iv != NULL_PTR && this->_encryptMode == DECRYPT){
+        for(CK_LONG i=0;i<8;i++){
+            output[output_offset+i] ^= iv[i];
+        }
+    }
+}
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,42 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_tdes_h
+#define _include_tdes_h
+
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+class CTripleDES : public CSymmAlgo
+{
+
+public:
+    CTripleDES();
+    ~CTripleDES();
+
+private:
+    void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+                                CK_BYTE_PTR input,CK_LONG input_offset,
+                                CK_BYTE_PTR output,CK_LONG output_offset);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,303 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "template.h"
+
+Template::Template(CK_ATTRIBUTE_PTR attrTemplate,CK_ULONG ulCount){
+
+
+   for(CK_ULONG i=0;i<ulCount;i++){
+      CK_ATTRIBUTE attribute;
+
+      attribute.type = attrTemplate[i].type;
+      attribute.ulValueLen = attrTemplate[i].ulValueLen;
+      attribute.pValue = NULL_PTR;
+
+      if(attribute.ulValueLen > 0) {
+         attribute.pValue = malloc(attribute.ulValueLen);
+         memcpy(attribute.pValue, attrTemplate[i].pValue, attribute.ulValueLen);
+      }
+
+      this->_attributes.push_back(attribute);
+   }
+}
+
+
+Template::~Template( )
+{
+   std::vector<CK_ATTRIBUTE>::size_type sz = _attributes.size( );
+   for( std::vector<CK_ATTRIBUTE>::size_type i = 0 ; i < sz ; i++ )
+   {
+      if( NULL_PTR != _attributes[ i ].pValue )
+      {
+         free( _attributes[ i ].pValue );
+      }
+   }
+}
+
+
+void Template::FixEndianness(CK_ATTRIBUTE attrTemplate)
+{
+   // Only for Little Endian processors
+   if (IS_LITTLE_ENDIAN)
+   {
+      // we need to fix the endianness if
+      // we are dealing with data on 2 or 4 or 8 bytes
+      switch(attrTemplate.ulValueLen)
+      {
+      case 2:
+      case 4:
+      case 8:
+         {
+            // fix up needs to be done for specific
+            // attributes. Byte arrays may have sizes of 2,4 or 8
+            switch(attrTemplate.type)
+            {
+               // CK_ULONG data types
+            case CKA_CLASS:
+            case CKA_CERTIFICATE_TYPE:
+            case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+            case CKA_KEY_TYPE:
+            case CKA_KEY_GEN_MECHANISM:
+            case CKA_MODULUS_BITS:
+               {
+                  PKCS11_ASSERT(attrTemplate.ulValueLen == sizeof(CK_ULONG));
+                  CK_BYTE b1 = ((CK_BYTE_PTR)attrTemplate.pValue)[0];
+                  CK_BYTE b2 = ((CK_BYTE_PTR)attrTemplate.pValue)[1];
+                  CK_BYTE b3 = ((CK_BYTE_PTR)attrTemplate.pValue)[2];
+                  CK_BYTE b4 = ((CK_BYTE_PTR)attrTemplate.pValue)[3];
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[3] = b1;
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[2] = b2;
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[1] = b3;
+                  ((CK_BYTE_PTR)attrTemplate.pValue)[0] = b4;
+               }
+               break;
+            }
+         }
+         break;
+
+      default:
+         break;
+      }
+   }
+}
+
+CK_ULONG Template::FindClassFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == CKA_CLASS)
+      {
+         return *(CK_ULONG*)pTemplate[idx].pValue;
+      }
+   }
+
+   return (CK_ULONG)-1;
+}
+
+CK_ULONG Template::FindCertTypeFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == CKA_CERTIFICATE_TYPE)
+      {
+         return *(CK_ULONG*)pTemplate[idx].pValue;
+      }
+   }
+
+   return (CK_ULONG)-1;
+}
+
+CK_BBOOL Template::FindTokenFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == CKA_TOKEN)
+      {
+         return *(CK_BBOOL*)pTemplate[idx].pValue;
+      }
+   }
+
+   return CK_FALSE;
+}
+
+CK_BBOOL Template::IsAttrInTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_ATTRIBUTE_TYPE AttrType)
+{
+   CK_ULONG idx = 0;
+
+   for(idx=0;idx<ulCount;idx++)
+   {
+      if(pTemplate[idx].type == AttrType)
+      {
+         return CK_TRUE;
+      }
+   }
+
+   return CK_FALSE;
+}
+
+CK_RV Template::CheckTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_BYTE bMode)
+{
+   CK_OBJECT_CLASS     ObjClass = (CK_ULONG)-1;
+   CK_CERTIFICATE_TYPE CertType = (CK_ULONG)-1;
+
+   // Get Object Class
+   ObjClass = FindClassFromTemplate(pTemplate, ulCount);
+
+   // Get Cert Type
+   if (ObjClass == CKO_CERTIFICATE)
+   {
+      CertType = FindCertTypeFromTemplate(pTemplate, ulCount);
+   }
+
+   // Check Creation Template
+   if (bMode == MODE_CREATE)
+   {
+      switch (ObjClass)
+      {
+      case CKO_DATA:
+         {
+            if (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+            {
+               return CKR_OK;
+            }
+         }
+         break;
+
+      case CKO_CERTIFICATE:
+         {
+            if (CertType == CKC_X_509)
+            {
+               if (  (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_SUBJECT))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_VALUE))
+                  )
+               {
+                  return CKR_OK;
+               }
+            }
+
+            else if (CertType == CKC_X_509_ATTR_CERT)
+            {
+               if (  (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_OWNER))
+                  &&(IsAttrInTemplate(pTemplate, ulCount, CKA_VALUE))
+                  )
+               {
+                  return CKR_OK;
+               }
+            }
+
+            else
+            {
+               return CKR_TEMPLATE_INCONSISTENT;
+            }
+         }
+         break;
+
+      case CKO_PUBLIC_KEY:
+         {
+            if (  ( IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_TYPE))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS_BITS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+               )
+            {
+               return CKR_OK;
+            }
+         }
+         break;
+
+      case CKO_PRIVATE_KEY:
+         {
+            if (  ( IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_TYPE))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_ALWAYS_SENSITIVE))
+               &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_NEVER_EXTRACTABLE))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIVATE_EXPONENT))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_1))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_2))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_1))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_2))
+               &&( IsAttrInTemplate(pTemplate, ulCount, CKA_COEFFICIENT))
+               )
+            {
+               return CKR_OK;
+            }
+         }
+         break;
+
+      default:
+         return CKR_TEMPLATE_INCONSISTENT;
+      }
+   }
+
+   // Check Public Key Generation Template
+   else if (bMode == MODE_GENERATE_PUB)
+   {
+      if (  (!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+         &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS_BITS))
+         &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+         )
+      {
+         return CKR_OK;
+      }
+   }
+
+   // Check Private Key Generation Template
+   else if (bMode == MODE_GENERATE_PRIV)
+   {
+      if (  (!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_ALWAYS_SENSITIVE))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_NEVER_EXTRACTABLE))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIVATE_EXPONENT))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_1))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_2))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_1))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_2))
+         &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_COEFFICIENT))
+         )
+      {
+         return CKR_OK;
+      }
+   }
+
+   return CKR_TEMPLATE_INCONSISTENT;
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,56 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_template_h
+#define _include_template_h
+
+#include <list>
+#include <vector>
+
+using namespace std;
+
+#define MODE_CREATE        0x01
+#define MODE_GENERATE_PUB  0x02
+#define MODE_GENERATE_PRIV 0x03
+
+class Template
+{
+
+public:
+    vector<CK_ATTRIBUTE> _attributes;
+
+public:
+    Template(CK_ATTRIBUTE_PTR temp,CK_ULONG ulCount);
+    ~Template();
+
+    static void FixEndianness(CK_ATTRIBUTE attrTemplate);
+
+    static CK_ULONG FindClassFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    static CK_ULONG FindCertTypeFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    static CK_BBOOL FindTokenFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+    static CK_BBOOL IsAttrInTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_ATTRIBUTE_TYPE AttrType);
+    static CK_RV CheckTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_BYTE bMode);
+
+};
+
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,312 @@
+
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include <string>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include "thread.h"
+
+#ifdef WIN32
+const CK_LONG CThread::P_ABOVE_NORMAL = THREAD_PRIORITY_ABOVE_NORMAL;
+const CK_LONG CThread::P_BELOW_NORMAL = THREAD_PRIORITY_BELOW_NORMAL;
+const CK_LONG CThread::P_HIGHEST      = THREAD_PRIORITY_HIGHEST;
+const CK_LONG CThread::P_IDLE         = THREAD_PRIORITY_IDLE;
+const CK_LONG CThread::P_LOWEST       = THREAD_PRIORITY_LOWEST;
+const CK_LONG CThread::P_NORMAL       = THREAD_PRIORITY_NORMAL;
+const CK_LONG CThread::P_CRITICAL     = THREAD_PRIORITY_TIME_CRITICAL;
+#endif
+
+CThread::CThread()
+{
+#ifdef WIN32
+    m_hThread = NULL;
+#endif
+    m_strName = NULL;
+    m_stopRequested = false;
+}
+
+CThread::CThread(const char* nm)
+{
+#ifdef WIN32
+    m_hThread = NULL;
+#endif
+    m_strName = new std::string(nm);
+}
+
+CThread::~CThread()
+{
+#ifdef WIN32
+    if(m_hThread != NULL)
+    {
+        if(m_strName != NULL)
+        {
+            delete m_strName;
+        }
+        stop();
+    }
+#else
+
+#endif
+}
+
+void CThread::setName(const char* nm)
+{
+    m_strName = new std::string(nm);
+}
+
+std::string* CThread::getName() const
+{
+    return m_strName;
+}
+
+void CThread::run()
+{
+    // Base run
+}
+
+void CThread::sleep(CK_LONG ms)
+{
+#ifdef WIN32
+    Sleep(ms);
+#else
+    usleep(ms*1000);
+#endif
+}
+
+void CThread::start()
+{
+
+#ifdef WIN32
+    DWORD tid = 0;
+    m_hThread = (unsigned long*)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_ou_thread_proc,(CThread*)this,0,&tid);
+
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Failed to create thread");
+    }
+    else
+    {
+        setPriority(CThread::P_NORMAL);
+    }
+
+#else
+
+    pthread_create(&m_hThread,0,_ou_thread_proc,(CThread*)this);
+
+#endif
+
+}
+
+void CThread::stop()
+{
+#ifdef WIN32
+    if(m_hThread == NULL) return;
+
+    m_stopRequested = true;
+
+    DWORD dwTimeout = 1000;
+    DWORD dwSleepTime = 10;
+    DWORD dwExitCode = STILL_ACTIVE;
+
+    for(DWORD i=0; i< dwTimeout/dwSleepTime; i++)
+    {
+        if(GetExitCodeThread(m_hThread, &dwExitCode))
+        {
+            if(dwExitCode!=STILL_ACTIVE)
+                break;
+        }
+        else
+            break; // Some error
+        Sleep(dwSleepTime);
+    }
+
+    if( dwExitCode == STILL_ACTIVE )
+        TerminateThread(m_hThread, 0);
+
+    // Never do this.
+    ///WaitForSingleObject(m_hThread,INFINITE);
+    CloseHandle(m_hThread);
+    m_hThread = NULL;
+
+    m_stopRequested = false;
+
+#else
+
+    m_stopRequested = true;
+
+    pthread_join(m_hThread,NULL);
+
+    m_stopRequested = false;
+
+#endif
+}
+
+CK_BBOOL CThread::isStopRequested()
+{
+    return m_stopRequested;
+}
+
+#ifdef WIN32
+void CThread::setPriority(CK_LONG tp)
+#else
+void CThread::setPriority( CK_LONG )
+#endif
+{
+#ifdef WIN32
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Thread object is null");
+    }
+    else
+    {
+        if(SetThreadPriority(m_hThread,tp) == 0)
+        {
+            assert(FALSE);
+            //throw ThreadException("Failed to set priority");
+        }
+    }
+#else
+#endif
+}
+
+void CThread::suspend()
+{
+
+#ifdef WIN32
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Thread object is null");
+    }
+    else
+    {
+        if((int)SuspendThread(m_hThread) < 0)
+        {
+            assert(FALSE);
+            //throw ThreadException("Failed to suspend thread");
+        }
+    }
+#else
+#endif
+}
+
+void CThread::resume()
+{
+#ifdef WIN32
+    if(m_hThread == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Thread object is null");
+    }
+    else
+    {
+        if((int)ResumeThread(m_hThread) < 0)
+        {
+            assert(FALSE);
+            //throw ThreadException("Failed to resume thread");
+        }
+    }
+#else
+#endif
+}
+
+#ifdef WIN32
+CK_BBOOL CThread::wait(const char* m,CK_LONG ms)
+#else
+CK_BBOOL CThread::wait( const char*, CK_LONG )
+#endif
+{
+#ifdef WIN32
+    HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
+
+    if(h == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Mutex not found");
+    }
+    DWORD d = WaitForSingleObject(h,ms);
+
+    switch(d)
+    {
+    case WAIT_ABANDONED:
+        assert(FALSE);
+        //throw ThreadException("Mutex not signaled");
+        break;
+    case WAIT_OBJECT_0:
+        return true;
+    case WAIT_TIMEOUT:
+        assert(FALSE);
+        //throw ThreadException("Wait timed out");
+        break;
+    }
+    return false;
+#else
+    return false;
+#endif
+}
+
+#ifdef WIN32
+void CThread::release(const char* m)
+#else
+void CThread::release( const char* )
+#endif
+{
+#ifdef WIN32
+    HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
+    if(h == NULL)
+    {
+        assert(FALSE);
+        //throw ThreadException("Invalid mutex handle");
+    }
+    if(ReleaseMutex(h) == 0)
+    {
+        assert(FALSE);
+        //throw ThreadException("Failed to release mutex");
+    }
+#else
+#endif
+}
+
+#ifdef WIN32
+// global thread caallback
+unsigned int _ou_thread_proc(void* param)
+{
+    CThread* tp = (CThread*)param;
+    tp->run();
+    return 0;
+}
+#else
+void* _ou_thread_proc(void* param)
+{
+    CThread* tp = (CThread*)param;
+    tp->run();
+    return NULL;
+}
+#endif
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,91 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_thread_h
+#define _include_thread_h
+
+#include <string>
+
+#ifdef INCLUDE_EVENTING
+
+using namespace std;
+
+class CThread
+{
+
+private:
+    // unsigned long* to the low-level thread object
+#ifdef WIN32
+    CK_ULONG_PTR m_hThread;
+#else
+    pthread_t 	 m_hThread;
+#endif
+
+    // a name to identify the thread
+    std::string* m_strName;
+    CK_BBOOL     m_stopRequested;
+
+public:
+    CThread();
+    CThread(const char* nm);
+    virtual ~CThread();
+
+    void setName(const char* nm);
+    std::string* getName() const;
+
+    void start();
+    virtual void run();
+    void sleep(CK_LONG ms);
+    void suspend();
+    void resume();
+    virtual void stop();
+
+    void setPriority(CK_LONG p);
+    CK_BBOOL isStopRequested();
+
+    CK_BBOOL wait(const char* m,CK_LONG ms=5000);
+    void release(const char* m);
+
+public:
+    // Thread priorities
+    static const CK_LONG P_ABOVE_NORMAL;
+    static const CK_LONG P_BELOW_NORMAL;
+    static const CK_LONG P_HIGHEST;
+    static const CK_LONG P_IDLE;
+    static const CK_LONG P_LOWEST;
+    static const CK_LONG P_NORMAL;
+    static const CK_LONG P_CRITICAL;
+};
+
+// global function called by the thread object.
+// this in turn calls the overridden run()
+extern "C"
+{
+#ifdef WIN32
+    unsigned int _ou_thread_proc(void* param);
+#else
+    void* _ou_thread_proc(void* param);
+#endif
+}
+
+#endif
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,49 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "timer.h"
+
+#if defined(_WIN32)
+#include "Windows.h"
+#else
+#include <inttypes.h>
+#include <sys/time.h>
+#endif
+
+unsigned long CTimer::ClockTicks()
+{
+#if defined(_WIN32)
+    return GetTickCount();
+#else
+    static uint64_t startuptime = 0;
+    struct timeval t;
+
+    if(!startuptime) {
+        gettimeofday(&t,0);
+        startuptime = t.tv_sec*1000 + t.tv_usec/1000;
+    }
+
+    gettimeofday(&t,0);
+    uint64_t time = t.tv_sec*1000 + t.tv_usec/1000 - startuptime;
+    return (unsigned long)(time & 0xFFFFFFFF);
+
+#endif
+
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,31 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_timer_h
+#define _include_timer_h
+
+class CTimer
+{
+public:
+    static unsigned long ClockTicks();
+};
+
+#endif // _include_timer_h
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,57 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "transaction.h"
+#include "cardmoduleservice.h"
+
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "session.h"
+#include "slot.h"
+#include "sctoken.h"
+#include "error.h"
+
+
+Transaction::Transaction(Slot * slot) : _slot(slot)
+{
+
+    if(!slot || !slot->_token)
+        throw CkError(CKR_FUNCTION_FAILED);
+
+    _slot->_token->BeginTransaction();
+
+    // As a result of card re-set, user may have been logged out
+    _slot->UpdateSessionState();
+}
+
+Transaction::~Transaction() throw()
+{
+    if(!_slot || !_slot->_token)
+        return;
+
+    try
+    {
+        _slot->_token->EndTransaction();
+    }
+    catch(...) {}
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,37 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_transaction_h
+#define _include_transaction_h
+
+class Slot;
+
+/** Class that manages token transaction */
+class Transaction
+{
+public:
+    Transaction(Slot * slot);
+    ~Transaction() throw();
+
+private:
+    Slot * _slot;
+};
+
+#endif

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,373 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "digest.h"
+#include "sha1.h"
+#include "error.h"
+#include "util.h"
+
+R_RANDOM_STRUCT Util::_randomStruct;
+
+void Util::SeedRandom(u1Array const & seed)
+{
+    InitRandomStruct(&_randomStruct);
+    R_RandomUpdate(&_randomStruct, const_cast<unsigned char*>(seed.GetBuffer()), seed.GetLength());
+}
+
+R_RANDOM_STRUCT & Util::RandomStruct()
+{
+    return _randomStruct;
+}
+
+CK_ULONG Util::MakeULong(CK_BYTE_PTR buffer,CK_ULONG offset)
+{
+    return (CK_ULONG)(((CK_ULONG)buffer[offset] << 24) | ((CK_ULONG)buffer[offset+1] << 16) | ((CK_ULONG)buffer[offset+2] << 8) | buffer[offset+3]);
+}
+
+CK_BBOOL Util::CompareByteArrays(CK_BYTE_PTR abuffer,CK_BYTE_PTR bbuffer,CK_ULONG len)
+{
+    for(CK_ULONG i=0;i<len;i++){
+        if(abuffer[i] != bbuffer[i])
+            return CK_FALSE;
+    }
+
+
+    return CK_TRUE;
+}
+
+CK_BBOOL Util::CompareU1Arrays(u1Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len)
+{
+    if((abuffer == NULL_PTR) && (bbuffer == NULL_PTR)){
+        return CK_TRUE;
+    }
+
+    if((abuffer != NULL_PTR) && (bbuffer != NULL_PTR)){
+        if(len == abuffer->GetLength()){
+            return Util::CompareByteArrays(abuffer->GetBuffer(),(CK_BYTE_PTR)bbuffer,len);
+        }
+    }
+
+    return CK_FALSE;
+}
+
+
+CK_BBOOL Util::CompareU4Arrays(u4Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len)
+{
+    if((abuffer == NULL_PTR) && (bbuffer == NULL_PTR)){
+        return CK_TRUE;
+    }
+
+    if((abuffer != NULL_PTR) && (bbuffer != NULL_PTR)){
+        if(len == abuffer->GetLength()){
+            return Util::CompareByteArrays((u1*)abuffer->GetBuffer(),(CK_BYTE_PTR)bbuffer,len);
+        }
+    }
+
+    return CK_FALSE;
+}
+
+void Util::PushULongInVector(vector<u1>* to, CK_ULONG value)
+{
+    to->push_back((u1)(value >> 24));
+    to->push_back((u1)(value >> 16));
+    to->push_back((u1)(value >> 8));
+    to->push_back((u1)(value));
+}
+
+void Util::PushULongLongInVector(vector<u1>* to, u8 value)
+{
+    to->push_back((u1)(value >> 56));
+    to->push_back((u1)(value >> 48));
+    to->push_back((u1)(value >> 40));
+    to->push_back((u1)(value >> 32));
+    to->push_back((u1)(value >> 24));
+    to->push_back((u1)(value >> 16));
+    to->push_back((u1)(value >> 8));
+    to->push_back((u1)(value));
+}
+
+void Util::PushBBoolInVector(std::vector<u1>* to, CK_BBOOL value)
+{
+    // push the value
+    to->push_back(value);
+}
+
+void Util::PushByteArrayInVector(std::vector<u1>* to, u1Array *value)
+{
+    if((value == NULL_PTR) || value->GetLength() == 0){
+        to->push_back(0);
+    }else{
+        Util::PushLengthInVector(to,value->GetLength());
+        for(u4 i=0;i<value->GetLength();i++){
+            to->push_back(value->GetBuffer()[i]);
+        }
+    }
+}
+
+void Util::PushIntArrayInVector(std::vector<u1>* to, u4Array *value)
+{
+    if((value == NULL_PTR) || value->GetLength() == 0){
+        to->push_back(0);
+    }else{
+        Util::PushLengthInVector(to,(value->GetLength() * 4));
+        u1* buffer = (u1*)value->GetBuffer();
+        for(u4 i=0;i<(value->GetLength() * 4);i++){
+            to->push_back(buffer[i]);
+        }
+    }
+}
+
+u1Array* Util::ReadByteArrayFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG len = Util::ReadLengthFromVector(from,idx);
+
+    if(len == 0){
+        return NULL_PTR;
+    }
+
+    u1Array* val = new u1Array(len);
+
+    for(u4 i=0;i<len;i++){
+        val->SetU1At(i,from.at(*idx));
+        *idx = *idx + 1;
+    }
+
+    return val;
+}
+
+u4Array* Util::ReadIntArrayFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG len = Util::ReadLengthFromVector(from,idx);
+
+    if(len == 0){
+        return NULL_PTR;
+    }
+
+    u4Array* val = new u4Array(len/4);
+
+    for(u4 i=0;i<(len/4);i++){
+
+        u1 a = from.at(*idx);
+        u1 b = from.at(*idx + 1);
+        u1 c = from.at(*idx + 2);
+        u1 d = from.at(*idx + 3);
+
+        // make an int
+        u4 anInt = (u4)(((u4)a << 24) | ((u4)b << 16) | ((u4)c << 8) | d);
+
+        val->SetU4At(i,anInt);
+
+        *idx = *idx + 4;
+    }
+
+    return val;
+}
+
+void Util::PushLengthInVector(std::vector<u1>* to, CK_USHORT len)
+{
+    if(len < (CK_USHORT)0x80){
+        to->push_back(len & 0x7F);
+    }else if(len <= (CK_USHORT)0xFF){
+        to->push_back(0x81);
+        to->push_back(len & 0xFF);
+    }else{
+        to->push_back(0x82);
+        to->push_back((u1)((len >> 8) & 0x00FF));
+        to->push_back((u1)(len));
+    }
+}
+
+CK_ULONG Util::ReadLengthFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_USHORT val = (CK_USHORT)from.at(*idx);
+
+    if(val < (CK_USHORT)0x80){
+        *idx = *idx + 1;
+        return val;
+    }else if(val == 0x81){
+        *idx = *idx + 1;
+        val = from.at(*idx);
+        *idx = *idx + 1;
+        return val;
+    }else if(val == 0x82){
+        *idx = *idx + 1;
+        val = (u2)(((u2)from.at(*idx)) << 8);
+        *idx = *idx + 1;
+        val = val | (u2)from.at(*idx);
+        *idx = *idx + 1;
+        return val;
+    }
+
+    PKCS11_ASSERT(CK_FALSE);
+
+    return 0;
+}
+
+CK_BBOOL Util::ReadBBoolFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_BBOOL val = (CK_BBOOL)from.at(*idx);
+    *idx = *idx + 1;
+
+    return val;
+}
+
+CK_ULONG Util::ReadULongFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG offset = *idx;
+
+    CK_ULONG val = (CK_ULONG)(((CK_ULONG)from.at(offset) << 24) | ((CK_ULONG)from.at(offset+1) << 16) | ((CK_ULONG)from.at(offset+2) << 8) | from.at(offset+3));
+
+    *idx = *idx + 4;
+
+    return val;
+}
+
+u8 Util::ReadULongLongFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CK_ULONG offset = *idx;
+
+    u8 val = (u8)(((u8)from.at(offset  ) << 56) | ((u8)from.at(offset+1) << 48) |
+                  ((u8)from.at(offset+2) << 40) | ((u8)from.at(offset+3) << 32) |
+                  ((u8)from.at(offset+4) << 24) | ((u8)from.at(offset+5) << 16) |
+                  ((u8)from.at(offset+6) <<  8) | from.at(offset+7));
+
+    *idx = *idx + 8;
+
+    return val;
+}
+
+void Util::ConvAscii(u1 *pIn, u4 dwLen,u1 *pOut)
+{
+   #define tohex(x)  (((x) >= 0xA) ? ((x) - 0xA + 'A') : ((x) + '0'))
+   register u4 i;
+
+   for(i=0; i < dwLen; i++)
+   {
+      pOut[i*2] = tohex((pIn[i] >> 4) & 0xF);
+      pOut[i*2+1] =  tohex(pIn[i] & 0xF);
+   }
+   #undef tohex
+}
+
+char* Util::ItoA(s4 value, char* str, s4 radix)
+{
+
+#ifdef WIN32
+
+    return _itoa(value,str,radix);
+
+#else
+
+    s4  rem = 0;
+    s4  pos = 0;
+    char ch  = '!' ;
+
+    do
+    {
+        rem    = value % radix ;
+        value /= radix;
+        if ( 16 == radix )
+        {
+            if( rem >= 10 && rem <= 15 )
+            {
+                switch( rem )
+                {
+                    case 10:
+                        ch = 'a' ;
+                        break;
+                    case 11:
+                        ch ='b' ;
+                        break;
+                    case 12:
+                        ch = 'c' ;
+                        break;
+                    case 13:
+                        ch ='d' ;
+                        break;
+                    case 14:
+                        ch = 'e' ;
+                        break;
+                    case 15:
+                        ch ='f' ;
+                        break;
+                }
+            }
+        }
+        if( '!' == ch )
+        {
+            str[pos++] = (char) ( rem + 0x30 );
+        }
+        else
+        {
+            str[pos++] = ch ;
+        }
+    }while( value != 0 );
+
+    str[pos] = '\0' ;
+
+    int i = strlen(str);
+    int t = !(i%2)? 1 : 0;      // check the length of the string .
+
+    for(int j = i-1 , k = 0 ; j > (i/2 -t) ; j-- )
+    {
+        char ch2  = str[j];
+        str[j]   = str[k];
+        str[k++] = ch2;
+    }
+
+    return str;
+
+#endif
+
+}
+
+u8 Util::MakeCheckValue(const unsigned char * pBuf, unsigned int length)
+{
+    CSHA1 sha1;
+    u1 hash[20];
+    sha1.HashCore(const_cast<unsigned char *>(pBuf), 0, length);
+    sha1.HashFinal(hash);
+    u8 val = 0;
+    for(size_t i = 0; i< sizeof(u8); ++i)
+        val = (val << 8) | hash[i];
+    return val;
+}
+
+u8 Util::MakeUniqueId()
+{
+    unsigned char buf[8];
+    if(R_GenerateBytes(buf, 8, &_randomStruct))
+        throw CkError(CKR_FUNCTION_FAILED);
+    u8 * value = reinterpret_cast<u8*>(buf);
+    return *value;
+}
+
+string Util::MakeIntString(unsigned int number, int width)
+{
+    if(width < 1)
+        return string();
+    char temp[16];
+    sprintf(temp, "%011d", number);
+    string s(temp);
+    return s.substr(s.size()-width, width);
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,107 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_util_h
+#define _include_util_h
+
+#include <string>
+#include <vector>
+
+#include <MarshallerCfg.h>
+#include <Array.h>
+#include <cr_random.h>
+
+using namespace std;
+using namespace Marshaller;
+
+// Very simple class similar to auto_ptr, but for arrays.
+// It means that it calls delete[] instead of delete.
+template<class T> class autoarray
+{
+public:
+    autoarray(T* t) : _t(t) {}
+    ~autoarray() { delete [] _t; }
+    T * get() { return _t; }
+    T & operator[](size_t index) { return _t[index]; }
+    const T & operator[](size_t index) const { return _t[index]; }
+
+private:
+    T * _t;
+};
+
+template<typename T> void IntToLittleEndian(T t, unsigned char * buf, size_t offset = 0)
+{
+    size_t n = sizeof(T);
+    for(size_t i = 0; i < n; i++)
+    {
+        buf[offset+i] = static_cast<unsigned char>(t & 0xFF);
+        t >>= 8;
+    }
+}
+
+template<typename T> T LittleEndianToInt(const unsigned char * buf, size_t offset = 0)
+{
+    size_t n = sizeof(T);
+    T t = 0;
+    for(size_t i = 0; i < n; i++)
+    {
+        t <<= 8;
+        t |= buf[offset+n-i-1];
+    }
+    return t;
+}
+
+class Util{
+
+public:
+    static void SeedRandom(u1Array const & seed);
+    static R_RANDOM_STRUCT & RandomStruct();
+
+    static CK_ULONG MakeULong(CK_BYTE_PTR pValue,CK_ULONG offset);
+    static CK_BBOOL CompareByteArrays(CK_BYTE_PTR abuffer,CK_BYTE_PTR bbuffer,CK_ULONG len);
+    static void PushULongInVector(vector<u1>* to,CK_ULONG value);
+    static void PushULongLongInVector(vector<u1>* to,u8 value);
+    static void PushBBoolInVector(vector<u1>* to,CK_BBOOL value);
+    static void PushByteArrayInVector(vector<u1>* to,u1Array* value);
+    static void PushIntArrayInVector(vector<u1>* to,u4Array* value);
+    static void PushLengthInVector(vector<u1>* to,CK_USHORT len);
+    static CK_ULONG ReadLengthFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static CK_ULONG ReadULongFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static u8       ReadULongLongFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static CK_BBOOL ReadBBoolFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static u1Array* ReadByteArrayFromVector(vector<u1> from,CK_ULONG_PTR idx);
+    static u4Array* ReadIntArrayFromVector(vector<u1> from,CK_ULONG_PTR idx);
+
+    static CK_BBOOL CompareU1Arrays(u1Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len);
+    static CK_BBOOL CompareU4Arrays(u4Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len);
+    static void ConvAscii(u1 *pIn, u4 dwLen,u1 *pOut);
+    static char* ItoA(s4 value, char* str, s4 radix);
+    static u8 MakeCheckValue(const unsigned char * pBuf, unsigned int length);
+    static u8 MakeUniqueId();
+    static std::string MakeIntString(unsigned int number, int width);
+
+private:
+    static R_RANDOM_STRUCT _randomStruct;
+
+};
+
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,564 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This implementation is based on RFC 2459 which can be fetched from
+// http://www.ietf.org.
+
+// This code is based on class in ACS baseline.
+
+//#include "slbPki.h"
+#include "x509cert.h"
+
+using namespace std;
+
+X509Cert::X509Cert()
+{
+}
+
+X509Cert::X509Cert(const X509Cert &cert)
+{
+   *this = cert;
+}
+
+X509Cert::X509Cert(const BEROctet::Blob &buffer)
+{
+   *this = buffer;
+}
+
+X509Cert::X509Cert(const unsigned char *buffer, const unsigned long size)
+{
+   m_Cert = BEROctet(BEROctet::Blob(buffer,size));
+   if(size != m_Cert.Octet().size())
+      throw runtime_error("X509CertFormatError");
+
+   Decode();
+}
+
+X509Cert& X509Cert::operator=(const X509Cert &cert)
+{
+   m_Cert = cert.m_Cert;
+   Decode();
+
+   return *this;
+}
+
+X509Cert& X509Cert::operator=(const BEROctet::Blob &buffer)
+{
+   m_Cert = BEROctet(buffer);
+   if(buffer.size() != m_Cert.Octet().size())
+      throw runtime_error("X509CertFormatError");
+   Decode();
+
+   return *this;
+}
+
+// Returns whole DER string of Serial Number.
+
+BEROctet::Blob X509Cert::SerialNumber() const
+{
+   return m_SerialNumber.Octet();
+}
+
+// Returns whole DER string of Issuer
+
+BEROctet::Blob X509Cert::Issuer() const
+{
+   return m_Issuer.Octet();
+}
+
+// Returns whole string of Issuer in UTF8.
+
+BEROctet::Blob X509Cert::UTF8Issuer() const
+{
+   return ToUTF8(m_Issuer.Tag(), m_Issuer.Octet() );
+}
+
+
+// Returns list of attributes in Issuer matching id-at-organizationName.
+// List will be invalidated when object changes.
+
+std::vector<std::string> X509Cert::IssuerOrg() const
+{
+
+   std::vector<std::string> orgNames;
+   std::vector<BEROctet const*> orgOcts;
+
+   m_Issuer.SearchOIDNext(OID_id_at_organizationName,orgOcts);
+
+   for(unsigned long i=0; i<orgOcts.size(); i++)
+      orgNames.push_back(string((char*)orgOcts[i]->Data().data(),orgOcts[i]->Data().size()));
+
+   return orgNames;
+
+}
+
+// Returns list of attributes in Issuer matching id-at-organizationName.
+// List will be invalidated when object changes.
+// the string in the list is in UTF8 format.
+
+std::vector<std::string> X509Cert::UTF8IssuerOrg() const
+{
+
+   std::vector<std::string> orgNames;
+   std::vector<BEROctet const*> orgOcts;
+
+   m_Issuer.SearchOIDNext(OID_id_at_organizationName,orgOcts);
+
+   for(unsigned long i=0; i<orgOcts.size(); i++)
+   {
+      BEROctet::Blob blbData = ToUTF8(orgOcts[i]->Tag(), orgOcts[i]->Data());
+      orgNames.push_back(string((char*)blbData.data(),blbData.size()));
+   }
+
+   return orgNames;
+}
+
+
+// Returns Validity notBefore attribute as "YYYYMMDDHHMMSS"
+
+string X509Cert::ValidityNotBefore() const
+{
+
+   if(m_Validity.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   return m_Validity.SubOctetList()[0]->Time();
+
+}
+
+// Returns Validity notAfter attribute as "YYYYMMDDHHMMSS"
+
+string X509Cert::ValidityNotAfter() const
+{
+
+   if(m_Validity.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   return m_Validity.SubOctetList()[1]->Time();
+
+}
+
+
+// Returns whole DER string of Subject
+
+BEROctet::Blob X509Cert::Subject() const
+{
+   return m_Subject.Octet();
+}
+
+// Returns Subject in UTF8 format.
+
+BEROctet::Blob X509Cert::UTF8Subject() const
+{
+   return ToUTF8(m_Subject.Tag(), m_Subject.Octet());
+}
+
+// Returns list of attributes in Subject matching id-at-commonName
+// List will be invalidated when object changes.
+
+std::vector<std::string> X509Cert::SubjectCommonName() const
+{
+
+   std::vector<std::string> cnNames;
+   std::vector<BEROctet const*> cnOcts;
+
+   m_Subject.SearchOIDNext(OID_id_at_commonName,cnOcts);
+
+   for(std::vector<BEROctet const*>::size_type i=0; i<cnOcts.size(); i++)
+      cnNames.push_back(string((char*)cnOcts[i]->Data().data(),cnOcts[i]->Data().size()));
+
+   return cnNames;
+
+}
+
+// Returns list of attributes in Subject matching id-at-commonName
+// List will be invalidated when object changes.
+// string in list is in UTF8.
+
+std::vector<std::string> X509Cert::UTF8SubjectCommonName() const
+{
+
+   std::vector<std::string> cnNames;
+   std::vector<BEROctet const*> cnOcts;
+
+   m_Subject.SearchOIDNext(OID_id_at_commonName,cnOcts);
+
+   for(std::vector<BEROctet const*>::size_type i=0; i<cnOcts.size(); i++)
+   {
+      BEROctet::Blob blbData = ToUTF8(cnOcts[i]->Tag(), cnOcts[i]->Data());
+      cnNames.push_back(string((char*)blbData.data(),blbData.size()));
+   }
+
+   return cnNames;
+
+}
+
+// Returns modulus from SubjectPublicKeyInfo, stripped for any leading zero(s).
+
+BEROctet::Blob X509Cert::Modulus() const
+{
+
+   BEROctet::Blob RawMod = RawModulus();
+
+   unsigned long i = 0;
+   while(!RawMod[i] && i<RawMod.size()) i++; // Skip leading zero(s).
+
+   return BEROctet::Blob(&RawMod[i],RawMod.size()-i);
+
+}
+
+// Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
+
+BEROctet::Blob X509Cert::RawModulus() const
+{
+
+   if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
+
+   BEROctet::Blob KeyBlob = PubKeyString.Data();
+
+   if(KeyBlob[0])                                 // Expect number of unused bits in
+      throw runtime_error("X509CertFormatError");    // last octet to be zero.
+
+
+
+   BEROctet PubKeyOct(KeyBlob.substr(1,BEROctet::Blob::npos));
+
+   if(PubKeyOct.SubOctetList().size()!=2) throw runtime_error("X509CertFormatError");
+
+   return PubKeyOct.SubOctetList()[0]->Data();
+
+}
+
+// Returns public exponent from SubjectPublicKeyInfo, stripped for any leading zero(s).
+
+BEROctet::Blob X509Cert::PublicExponent() const
+{
+
+   BEROctet::Blob RawPubExp = RawPublicExponent();
+
+   unsigned long i = 0;
+   while(!RawPubExp[i] && i<RawPubExp.size()) i++; // Skip leading zero(s).
+
+   return BEROctet::Blob(&RawPubExp[i],RawPubExp.size()-i);
+
+}
+// Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
+
+BEROctet::Blob X509Cert::RawPublicExponent() const
+{
+
+   if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2)
+      throw runtime_error("X509CertFormatError");
+
+   BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
+
+   BEROctet::Blob KeyBlob = PubKeyString.Data();
+
+   if(KeyBlob[0])                                  // Expect number of unused bits
+      throw runtime_error("X509CertFormatError");     // in last octet to be zero.
+
+
+   BEROctet PubKeyOct(KeyBlob.substr(1,BEROctet::Blob::npos));
+
+   if(PubKeyOct.SubOctetList().size()!=2) throw runtime_error("X509CertFormatError");
+
+   return PubKeyOct.SubOctetList()[1]->Data();
+
+}
+
+// Returns KeyUsage attribute, left justified with most significant bit as first bit (BER convention)
+
+unsigned long X509Cert::KeyUsage() const
+{
+
+   if(!m_Extensions.Data().size())
+      throw runtime_error("X509CertExtensionNotPresent");
+
+   unsigned long ReturnKeyUsage = 0;
+
+   const unsigned char UnusedBitsMask[]  = {0xFF,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
+
+   std::vector<BEROctet const*> ExtensionList;
+
+   m_Extensions.SearchOID(OID_id_ce_keyUsage,ExtensionList);
+
+   if(ExtensionList.size()!=1)
+      throw runtime_error("X509CertExtensionNotPresent"); // One and only one instance
+
+   BEROctet const* Extension = ExtensionList[0];
+   BEROctet* extnValue = 0;
+   if(Extension->SubOctetList().size()==2)
+      extnValue = Extension->SubOctetList()[1];  // No "critical" attribute present
+
+   else if(Extension->SubOctetList().size()==3)
+      extnValue = Extension->SubOctetList()[2];  // A "critical" attribute present
+
+   else
+      throw runtime_error("X509CertFormatError");    // "Extensions" must contain either 2 or 3 octets
+
+   BEROctet KeyUsage(extnValue->Data());
+   BEROctet::Blob KeyUsageBitString = KeyUsage.Data();
+
+   unsigned char UnusedBits = KeyUsageBitString[0];
+   size_t NumBytes = KeyUsageBitString.size()-1;
+   if(NumBytes>4)
+   {
+      NumBytes = 4; // Truncate to fit the ulong, should be plenty though
+      UnusedBits = 0;
+   }
+
+   unsigned long Shift = 24;
+   for(unsigned long i=0; i<NumBytes-1; i++)
+   {
+      ReturnKeyUsage |= (((unsigned long)KeyUsageBitString[i+1]) << Shift);
+      Shift -= 8;
+   }
+
+   ReturnKeyUsage |= ( (KeyUsageBitString[NumBytes] & UnusedBitsMask[UnusedBits]) << Shift );
+
+   return ReturnKeyUsage;
+
+}
+
+bool X509Cert::ExtendedKeyUsage(string const &strOID) const
+{
+   if(!m_Extensions.Data().size())
+      return false;
+
+   vector<BEROctet const*> veku;
+
+   m_Extensions.SearchOIDNext(OID_id_ce_extKeyUsage, veku);
+   if(veku.size() != 1)
+      return false;
+
+   try
+   {
+      BEROctet berEKU(veku[0]->Data());
+      vector<BEROctet const*> ekuOcts;
+      berEKU.SearchOID(strOID,ekuOcts);
+      if(ekuOcts.size() > 0)
+         return true;
+      else
+         return false;
+   }
+   catch(...)
+   {
+      return false;
+   }
+}
+
+bool X509Cert::IsCACert() const
+{
+   return m_bCACert;
+}
+
+bool X509Cert::IsRootCert() const
+{
+   return m_bRootCert;
+}
+
+void X509Cert::Decode()
+{
+
+   const unsigned int dwTagVersion         = 0;
+   //const unsigned int dwTagIssuerUniqueID  = 1;
+   //const unsigned int dwTagSubjectUniqueID = 2;
+   const unsigned int dwTagExtensions      = 3;
+
+   if(m_Cert.SubOctetList().size()!=3)  throw runtime_error("X509CertFormatError");
+
+   BEROctet *tbsCert = m_Cert.SubOctetList()[0];
+   size_t Size = tbsCert->SubOctetList().size();
+   if(!Size) throw runtime_error("X509CertFormatError");
+
+   std::vector<BEROctet const*>::size_type  i = 0;
+   BEROctet *first = tbsCert->SubOctetList()[i];
+   if((first->Class()==tcContext) && (first->Tag()==dwTagVersion)) i++; // Version
+
+   if(Size < static_cast<unsigned long>(6+i))
+      throw runtime_error("X509CertFormatError");
+
+   m_SerialNumber = *(tbsCert->SubOctetList()[i]); i++;            // SerialNumber
+   i++;                                                            // Signature (algorithm)
+   m_Issuer = *(tbsCert->SubOctetList()[i]); i++;                  // Issuer
+   m_Validity = *(tbsCert->SubOctetList()[i]); i++;                // Validity
+   m_Subject = *(tbsCert->SubOctetList()[i]); i++;                 // Subject
+   m_SubjectPublicKeyInfo = *(tbsCert->SubOctetList()[i]);    i++; // SubjectPublicKeyInfo
+
+   m_Extensions = BEROctet();
+   while(i<Size) {
+      BEROctet *oct = tbsCert->SubOctetList()[i];
+      if((oct->Class()==tcContext) && (oct->Tag()==dwTagExtensions)) {
+         m_Extensions = *oct;
+         break;
+      }
+      i++;
+   }
+
+   m_bCACert = false;
+   std::vector<BEROctet const*> ExtensionList;
+   m_Extensions.SearchOID(OID_id_ce_basicConstraints, ExtensionList);
+
+
+   if(1 == ExtensionList.size())
+   {
+      BEROctet const* Extension = ExtensionList[0];
+      BEROctet* extnValue = 0;
+      if(Extension->SubOctetList().size()==2)
+         extnValue = Extension->SubOctetList()[1];  // No "critical" attribute present
+
+      else if(Extension->SubOctetList().size()==3)
+         extnValue = Extension->SubOctetList()[2];  // A "critical" attribute present
+
+      if (extnValue)
+      {
+         BEROctet BasicContrainsts(extnValue->Data());
+         std::vector<BEROctet*> bcMembers(BasicContrainsts.SubOctetList());
+         if(bcMembers.size()>0 && bcMembers[0]->Tag() == dwBerUnivBool)
+         {
+            BEROctet::Blob flag(bcMembers[0]->Data());
+            if(flag.size()==1)
+               m_bCACert = flag[0] ? true : false;
+         }
+      }
+   }
+
+   m_bRootCert = false;
+   if (Issuer() == Subject())
+   {
+      m_bRootCert = true;
+   }
+}
+
+
+BEROctet::Blob X509Cert::ToUTF8( unsigned int dwTag, const BEROctet::Blob &blbData ) const
+{
+   BEROctet::Blob blbReturn;
+   size_t cUnicode = 0;
+   bool bConvert = false;
+   switch(dwTag)
+   {
+   case dwBerBMPString:
+      //string in 2 byte Unicode Big Endian format.
+      cUnicode = 2;
+      bConvert = true;
+      break;
+   case dwBerUniversalString:
+   case dwBerCharacterString:
+      //string in ISO10646, 4 byte unicode big endian format.
+      //this is hardly used but we never know.
+      cUnicode = 4;
+      bConvert = true;
+      break;
+   default:
+      //return as is.
+      blbReturn = blbData;
+   }
+
+   if(bConvert)
+   {
+      unsigned char bAppend = 0;
+      for(size_t i = 0; i < blbData.size() / cUnicode; i++ )
+      {
+         unsigned int dwUnicode = 0;
+         unsigned int dwTemp = 0;
+         int nBytesInUTF8 = 0;
+
+         //first get the Unicode unsigned int from BIG ENDIAN BYTES.
+         for(size_t j = 0; j < cUnicode; j++)
+         {
+            dwTemp = blbData.at(i*cUnicode + j);
+            dwUnicode += dwTemp << (8*(cUnicode-(j+1)));
+         }
+
+         //now calculate the number of bytes required to represent
+         // the unicode value in UTF8
+         if( dwUnicode <= 0x0000007F )
+         {
+            nBytesInUTF8 = 1;
+         }
+         else if( dwUnicode <= 0x000007FF )
+         {
+            nBytesInUTF8 = 2;
+         }
+         else if( dwUnicode <= 0x0000FFFF )
+         {
+            nBytesInUTF8 = 3;
+         }
+         else if( dwUnicode <= 0x001FFFFF )
+         {
+            nBytesInUTF8 = 4;
+         }
+         else if( dwUnicode <= 0x03FFFFFF )
+         {
+            nBytesInUTF8 = 5;
+         }
+         else if( dwUnicode <= 0x7FFFFFFF )
+         {
+            nBytesInUTF8 = 6;
+         }
+
+         //The bitwise & code is 0x7F (7 bits) when there is only one byte
+         // Otherwise the & code is 0x3f ( 6 bits)
+         // when there are more that one UTF8 bytes required,
+         // Ideally the MS unsigned char has to be & with less than 6 bits,
+         // but it does not matter since the other bits
+         // will be zero, so it is safe to & 6 bits.
+
+         unsigned char bBitWiseAndCode = 0x3f;
+         if( nBytesInUTF8 == 1)
+         {
+            bBitWiseAndCode = 0x7f;
+         }
+
+
+         // Shift in the multiples of 6 starting with maximum.
+         // This way the MSB will be appended first and then the rest.
+         // Add to MS Byte the bits which indicates number of bytes coded for UTF8
+         // for all other bytes add 0x80.
+         for( int k = nBytesInUTF8 - 1; k >= 0; k--)
+         {
+            unsigned char bytAdd = 0;
+            if( nBytesInUTF8 > 1 )
+            {
+               if( k == nBytesInUTF8 - 1 )
+               {
+                  bytAdd = ( 0xFF << (8 - nBytesInUTF8 ) );
+               }
+               else
+               {
+                  bytAdd = 0x80;
+               }
+
+            }
+            bAppend = static_cast<unsigned char>( ((dwUnicode >> k*6) & bBitWiseAndCode));
+            bAppend  += bytAdd;
+            blbReturn.append( &bAppend, 1);
+         }
+      }
+      //append the NULL char.
+      bAppend = 0;
+      blbReturn.append( &bAppend, 1);
+   }
+   return blbReturn;
+}

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,95 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_x509cert_h
+#define _include_x509cert_h
+
+#include <string>
+#include <vector>
+
+#include "beroctet.h"
+
+class X509Cert
+{
+
+public:
+    X509Cert();
+    X509Cert(const X509Cert &cert);
+    X509Cert(const BEROctet::Blob &buffer);
+    X509Cert(const unsigned char *buffer, const unsigned long size);
+    X509Cert& operator=(const X509Cert &cert);
+    X509Cert& operator=(const BEROctet::Blob &buffer);
+
+    BEROctet::Blob SerialNumber() const;
+    BEROctet::Blob Issuer() const;
+    BEROctet::Blob UTF8Issuer() const;
+    std::vector<std::string> IssuerOrg() const;
+    std::vector<std::string> UTF8IssuerOrg() const;
+    std::string ValidityNotBefore() const;
+    std::string ValidityNotAfter() const;
+    BEROctet::Blob Subject() const;
+    BEROctet::Blob UTF8Subject() const;
+    std::vector<std::string> SubjectCommonName() const;
+    std::vector<std::string> UTF8SubjectCommonName() const;
+    BEROctet::Blob Modulus() const;
+    BEROctet::Blob RawModulus() const;
+    BEROctet::Blob PublicExponent() const;
+    BEROctet::Blob RawPublicExponent() const;
+
+    unsigned long KeyUsage() const;
+    bool ExtendedKeyUsage(std::string const &strOID) const;
+    bool IsCACert() const;
+    bool IsRootCert() const;
+
+private:
+    void Decode();
+
+    BEROctet::Blob ToUTF8( unsigned int dwTag, const BEROctet::Blob &blbData ) const;
+
+private:
+    BEROctet m_Cert;
+    BEROctet m_SerialNumber;
+    BEROctet m_Issuer;
+    BEROctet m_Validity;
+    BEROctet m_Subject;
+    BEROctet m_SubjectPublicKeyInfo;
+    BEROctet m_Extensions;
+    bool     m_bCACert;
+    bool     m_bRootCert;
+
+
+};
+
+// Key Usage flags from X.509 spec
+
+const unsigned long digitalSignature = 0x80000000;
+const unsigned long nonRepudiation   = 0x40000000;
+const unsigned long keyEncipherment  = 0x20000000;
+const unsigned long dataEncipherment = 0x10000000;
+const unsigned long keyAgreement     = 0x08000000;
+const unsigned long keyCertSign      = 0x04000000;
+const unsigned long cRLSign          = 0x02000000;
+const unsigned long encipherOnly     = 0x01000000;
+const unsigned long decipherOnly     = 0x00800000;
+
+
+#endif //_include_x509cert_h

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,265 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "x509pubkeycertobject.h"
+
+X509PubKeyCertObject::X509PubKeyCertObject() : CertificateObject()
+{
+    this->_subject              = NULL_PTR;
+    this->_id                   = NULL_PTR;
+    this->_issuer               = NULL_PTR;
+    this->_serialNumber         = NULL_PTR;
+    this->_value                = NULL_PTR;
+    this->_url                  = NULL_PTR;
+    this->_hashOfSubjectPubKey  = NULL_PTR;
+    this->_hashOfIssuerPubKey   = NULL_PTR;
+
+    this->_certType             = CKC_X_509;
+    this->_trusted              = CK_TRUE;
+}
+
+X509PubKeyCertObject::~X509PubKeyCertObject()
+{
+    if(this->_subject != NULL_PTR)
+        delete this->_subject;
+
+    if(this->_id != NULL_PTR)
+        delete this->_id;
+
+    if(this->_issuer != NULL_PTR)
+        delete this->_issuer;
+
+    if(this->_serialNumber != NULL_PTR)
+        delete this->_serialNumber;
+
+    if(this->_value != NULL_PTR)
+        delete this->_value;
+
+    if(this->_url != NULL_PTR)
+        delete this->_url;
+
+    if(this->_hashOfSubjectPubKey != NULL_PTR)
+        delete this->_hashOfSubjectPubKey;
+
+    if(this->_hashOfIssuerPubKey != NULL_PTR)
+        delete this->_hashOfIssuerPubKey;
+
+}
+
+CK_BBOOL X509PubKeyCertObject::Compare(CK_ATTRIBUTE attribute)
+{
+    switch(attribute.type){
+
+        case CKA_SUBJECT:
+            return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_ID:
+            return Util::CompareU1Arrays(this->_id,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_ISSUER:
+            return Util::CompareU1Arrays(this->_issuer,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_SERIAL_NUMBER:
+            return Util::CompareU1Arrays(this->_serialNumber,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_VALUE:
+            return Util::CompareU1Arrays(this->_value,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_URL:
+            return Util::CompareU1Arrays(this->_url,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+            return Util::CompareU1Arrays(this->_hashOfSubjectPubKey,attribute.pValue,attribute.ulValueLen);
+
+        case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+            return Util::CompareU1Arrays(this->_hashOfIssuerPubKey,attribute.pValue,attribute.ulValueLen);
+
+        default:
+            return CertificateObject::Compare(attribute);
+    }
+}
+
+CK_RV X509PubKeyCertObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+   if( 0 == attribute.ulValueLen )
+   {
+      return CKR_OK;
+   }
+
+   CK_RV rv = CKR_OK;
+
+    if(objCreation == CK_FALSE){
+        switch(attribute.type){
+            case CKA_SUBJECT:
+            case CKA_VALUE:
+                return CKR_ATTRIBUTE_READ_ONLY;
+        }
+    }
+
+    switch(attribute.type){
+
+        case CKA_SUBJECT:
+            if(this->_subject != NULL_PTR){
+                delete this->_subject;
+            }
+            this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_ID:
+            if(this->_id != NULL_PTR){
+                delete this->_id;
+            }
+            this->_id = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_ISSUER:
+            if(this->_issuer != NULL_PTR){
+                delete this->_issuer;
+            }
+            this->_issuer = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_SERIAL_NUMBER:
+            if(this->_serialNumber != NULL_PTR){
+                delete this->_serialNumber;
+            }
+            this->_serialNumber = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_VALUE:
+            if(this->_value != NULL_PTR){
+                delete this->_value;
+            }
+            this->_value = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_URL:
+            {
+                u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+                if(rv == CKR_OK){
+                    if(this->_url != NULL_PTR){
+                        delete this->_url;
+                    }
+                    this->_url = stemp;
+                }
+            }
+            break;
+
+        case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+            if(this->_hashOfSubjectPubKey != NULL_PTR){
+                delete this->_hashOfSubjectPubKey;
+            }
+            this->_hashOfSubjectPubKey = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+            if(this->_hashOfIssuerPubKey != NULL_PTR){
+                delete this->_hashOfIssuerPubKey;
+            }
+            this->_hashOfIssuerPubKey = StorageObject::ReadU1ArrayFromAttribute(attribute);
+            break;
+
+        default:
+            return CertificateObject::SetAttribute(attribute,objCreation);
+    }
+
+    return rv;
+}
+
+CK_RV X509PubKeyCertObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+    switch(attribute->type){
+
+        case CKA_SUBJECT:
+            return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+        case CKA_ID:
+            return StorageObject::PutU1ArrayInAttribute(this->_id,attribute);
+
+        case CKA_ISSUER:
+            return StorageObject::PutU1ArrayInAttribute(this->_issuer,attribute);
+
+        case CKA_SERIAL_NUMBER:
+            return StorageObject::PutU1ArrayInAttribute(this->_serialNumber,attribute);
+
+        case CKA_VALUE:
+            return StorageObject::PutU1ArrayInAttribute(this->_value,attribute);
+
+        case CKA_URL:
+            return StorageObject::PutU1ArrayInAttribute(this->_url,attribute);
+
+        case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+            return StorageObject::PutU1ArrayInAttribute(this->_hashOfSubjectPubKey,attribute);
+
+        case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+            return StorageObject::PutU1ArrayInAttribute(this->_hashOfIssuerPubKey,attribute);
+
+        default:
+            return CertificateObject::GetAttribute(attribute);
+    }
+}
+
+void X509PubKeyCertObject::Serialize(std::vector<u1> *to)
+{
+    CertificateObject::Serialize(to);
+
+    Util::PushByteArrayInVector(to,this->_subject);
+
+    Util::PushByteArrayInVector(to,this->_id);
+
+    Util::PushByteArrayInVector(to,this->_issuer);
+
+    Util::PushByteArrayInVector(to,this->_serialNumber);
+
+    Util::PushByteArrayInVector(to,this->_url);
+
+    Util::PushByteArrayInVector(to,this->_hashOfSubjectPubKey);
+
+    Util::PushByteArrayInVector(to,this->_hashOfIssuerPubKey);
+
+    PKCS11_ASSERT(!this->_certName.empty());
+
+}
+
+void X509PubKeyCertObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+    CertificateObject::Deserialize(from,idx);
+
+    this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_id = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_issuer = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_serialNumber = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_url = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_hashOfSubjectPubKey = Util::ReadByteArrayFromVector(from,idx);
+
+    this->_hashOfIssuerPubKey = Util::ReadByteArrayFromVector(from,idx);
+
+}
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_x509pubkeycertobject_h
+#define _include_x509pubkeycertobject_h
+
+#include "certificateobject.h"
+
+class X509PubKeyCertObject : public CertificateObject
+{
+
+public:
+    u1Array*    _subject;
+    u1Array*    _id;
+    u1Array*    _issuer;
+    u1Array*    _serialNumber;
+    u1Array*    _value;
+    u1Array*    _url;
+    u1Array*    _hashOfSubjectPubKey;
+    u1Array*    _hashOfIssuerPubKey;
+
+public:
+     X509PubKeyCertObject();
+    ~X509PubKeyCertObject();
+
+    CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+    CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+    CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+    void Serialize(vector<u1>* to);
+    void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,8989 @@
+# generated automatically by aclocal 1.10.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(AC_AUTOCONF_VERSION, [2.61],,
+[m4_warning([this file was generated for autoconf 2.61.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 56 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+		   [m4_fatal([Libtool version $1 or higher is required],
+		             63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\	*)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+_LT_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+	[m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+	[tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+	   m4_quote(lt_decl_varnames),
+	m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+					   [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+	dnl If the libtool generation code has been placed in $CONFIG_LT,
+	dnl instead of duplicating it all over again into config.status,
+	dnl then we will have config.status run $CONFIG_LT later, so it
+	dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\[$]0 --fallback-echo"')dnl "
+  lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
+  ;;
+esac
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+cat >"$CONFIG_LT" <<_LTEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate a libtool stub with the current configuration.
+
+lt_cl_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AS_SHELL_SANITIZE
+_AS_PREPARE
+
+exec AS_MESSAGE_FD>&1
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool at gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+if test "$no_create" != yes; then
+  lt_cl_success=:
+  test "$silent" = yes &&
+    lt_config_lt_args="$lt_config_lt_args --quiet"
+  exec AS_MESSAGE_LOG_FD>/dev/null
+  $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+  exec AS_MESSAGE_LOG_FD>>config.log
+  $lt_cl_success || AS_EXIT(1)
+fi
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  _LT_PROG_XSI_SHELLFNS
+
+  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+    || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],			[_LT_LANG(C)],
+  [C++],		[_LT_LANG(CXX)],
+  [Java],		[_LT_LANG(GCJ)],
+  [Fortran 77],		[_LT_LANG(F77)],
+  [Fortran],		[_LT_LANG(FC)],
+  [Windows Resource],	[_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+	# By default we will add the -single_module flag. You can override
+	# by either setting the environment variable LT_MULTI_MODULE
+	# non-empty at configure time, or by adding -multi_module to the
+	# link flags.
+	rm -rf libconftest.dylib*
+	echo "int foo(void){return 1;}" > conftest.c
+	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+	  lt_cv_apple_cc_single_mod=yes
+	else
+	  cat conftest.err >&AS_MESSAGE_LOG_FD
+	fi
+	rm -rf libconftest.dylib*
+	rm -f conftest.*
+      fi])
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+	[lt_cv_ld_exported_symbols_list=yes],
+	[lt_cv_ld_exported_symbols_list=no])
+	LDFLAGS="$save_LDFLAGS"
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+	10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+	10.[[012]]*)
+	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+	10.*)
+	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES
+# --------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=echo
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+    m4_if([$1], [CXX],
+[   if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX
+# -----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+    /Import File Strings/,/^$/ {
+	/^0/ {
+	    s/^0  *\(.*\)$/\1/
+	    p
+	}
+    }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+	     [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+	 [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_SHELL_INIT
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[_LT_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<_LT_EOF
+[$]*
+_LT_EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+  if test "X${echo_test_string+set}" != Xset; then
+    # find a string as large as possible, as long as the shell can cope with it
+    for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+      # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+      if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+	 { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+      then
+        break
+      fi
+    done
+  fi
+
+  if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+     echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+     test "X$echo_testing_string" = "X$echo_test_string"; then
+    :
+  else
+    # The Solaris, AIX, and Digital Unix default echo programs unquote
+    # backslashes.  This makes it impossible to quote backslashes using
+    #   echo "$something" | sed 's/\\/\\\\/g'
+    #
+    # So, first we look for a working echo in the user's PATH.
+
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for dir in $PATH /usr/ucb; do
+      IFS="$lt_save_ifs"
+      if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+         test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        ECHO="$dir/echo"
+        break
+      fi
+    done
+    IFS="$lt_save_ifs"
+
+    if test "X$ECHO" = Xecho; then
+      # We didn't find a better echo, so look for alternatives.
+      if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+         echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+         test "X$echo_testing_string" = "X$echo_test_string"; then
+        # This shell has a builtin print -r that does the trick.
+        ECHO='print -r'
+      elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+	   test "X$CONFIG_SHELL" != X/bin/ksh; then
+        # If we have ksh, try running configure again with it.
+        ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+        export ORIGINAL_CONFIG_SHELL
+        CONFIG_SHELL=/bin/ksh
+        export CONFIG_SHELL
+        exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+      else
+        # Try using printf.
+        ECHO='printf %s\n'
+        if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+	   echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+	   test "X$echo_testing_string" = "X$echo_test_string"; then
+	  # Cool, printf works
+	  :
+        elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+	  export CONFIG_SHELL
+	  SHELL="$CONFIG_SHELL"
+	  export SHELL
+	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+        elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+	     test "X$echo_testing_string" = 'X\t' &&
+	     echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+	     test "X$echo_testing_string" = "X$echo_test_string"; then
+	  ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+        else
+	  # maybe with a smaller string...
+	  prev=:
+
+	  for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+	    if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+	    then
+	      break
+	    fi
+	    prev="$cmd"
+	  done
+
+	  if test "$prev" != 'sed 50q "[$]0"'; then
+	    echo_test_string=`eval $prev`
+	    export echo_test_string
+	    exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+	  else
+	    # Oops.  We lost completely, so just stick with echo.
+	    ECHO=echo
+	  fi
+        fi
+      fi
+    fi
+  fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(lt_ECHO)
+])
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1],
+    [An echo program that does not interpret backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+	HPUX_IA64_MODE="32"
+	;;
+      *ELF-64*)
+	HPUX_IA64_MODE="64"
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -melf32bsmip"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -melf32bmipn32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -melf64bmip"
+	;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+	*32-bit*)
+	  LD="${LD-ld} -32"
+	  ;;
+	*N32*)
+	  LD="${LD-ld} -n32"
+	  ;;
+	*64-bit*)
+	  LD="${LD-ld} -64"
+	  ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_i386_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_i386"
+	    ;;
+	  ppc64-*linux*|powerpc64-*linux*)
+	    LD="${LD-ld} -m elf32ppclinux"
+	    ;;
+	  s390x-*linux*)
+	    LD="${LD-ld} -m elf_s390"
+	    ;;
+	  sparc64-*linux*)
+	    LD="${LD-ld} -m elf32_sparc"
+	    ;;
+	esac
+	;;
+      *64-bit*)
+	case $host in
+	  x86_64-*kfreebsd*-gnu)
+	    LD="${LD-ld} -m elf_x86_64_fbsd"
+	    ;;
+	  x86_64-*linux*)
+	    LD="${LD-ld} -m elf_x86_64"
+	    ;;
+	  ppc*-*linux*|powerpc*-*linux*)
+	    LD="${LD-ld} -m elf64ppc"
+	    ;;
+	  s390*-*linux*|s390*-*tpf*)
+	    LD="${LD-ld} -m elf64_s390"
+	    ;;
+	  sparc*-*linux*)
+	    LD="${LD-ld} -m elf64_sparc"
+	    ;;
+	esac
+	;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+sparc*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+      *)
+	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+	  LD="${LD-ld} -64"
+	fi
+	;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[AC_CHECK_TOOL(AR, ar, false)
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1])
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[	 ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+	         = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+	      test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL		DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL		0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW		DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW	DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW	0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+	  [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+	    [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+	[AC_CHECK_FUNC([dlopen],
+	      [lt_cv_dlopen="dlopen"],
+	  [AC_CHECK_LIB([dl], [dlopen],
+		[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+	    [AC_CHECK_LIB([svld], [dlopen],
+		  [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+	      [AC_CHECK_LIB([dld], [dld_link],
+		    [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+	      ])
+	    ])
+	  ])
+	])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+	  lt_cv_dlopen_self, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+	  lt_cv_dlopen_self_static, [dnl
+	  _LT_TRY_DLOPEN_SELF(
+	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+	 [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+	 [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+	 [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+	[Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+  [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+   test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+	[], [
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+	   echo ' yes '
+	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+	:
+      else
+	can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[123]]*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+	if test "$lt_cv_prog_gnu_ld" = yes; then
+		version_type=linux
+	else
+		version_type=irix
+	fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # Some binutils ld are patched to set DT_RUNPATH
+  save_LDFLAGS=$LDFLAGS
+  save_libdir=$libdir
+  eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+       LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+    [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+       [shlibpath_overrides_runpath=yes])])
+  LDFLAGS=$save_LDFLAGS
+  libdir=$save_libdir
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
+    *)				need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+	shlibpath_overrides_runpath=no
+	;;
+      *)
+	shlibpath_overrides_runpath=yes
+	;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+	;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+    [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+	case $deplibs_check_method in
+	"file_magic "*)
+	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+	    $EGREP "$file_magic_regex" > /dev/null; then
+	    :
+	  else
+	    cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool at gnu.org
+
+_LT_EOF
+	  fi ;;
+	esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+	test "$with_gnu_ld" != no && break
+	;;
+      *)
+	test "$with_gnu_ld" != yes && break
+	;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_DECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method == "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+	# Check to see if the nm accepts a BSD-compat flag.
+	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+	#   nm: unknown option "B" ignored
+	# Tru64's nm complains that /dev/null is an invalid object file
+	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+	*/dev/null* | *'Invalid file or object type'*)
+	  lt_cv_path_NM="$tmp_nm -B"
+	  break
+	  ;;
+	*)
+	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+	  */dev/null*)
+	    lt_cv_path_NM="$tmp_nm -p"
+	    break
+	    ;;
+	  *)
+	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+	    continue # so that we can try to find one that supports BSD flags
+	    ;;
+	  esac
+	  ;;
+	esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
+  AC_SUBST([DUMPBIN])
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+	[Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+	mv -f "$nlist"T "$nlist"
+      else
+	rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+	  cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+	  # Now generate the symbol file.
+	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+	  cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+const struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+	  cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+	  # Now try linking the two files.
+	  mv conftest.$ac_objext conftstm.$ac_objext
+	  lt_save_LIBS="$LIBS"
+	  lt_save_CFLAGS="$CFLAGS"
+	  LIBS="conftstm.$ac_objext"
+	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+	  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+	    pipe_works=yes
+	  fi
+	  LIBS="$lt_save_LIBS"
+	  CFLAGS="$lt_save_CFLAGS"
+	else
+	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+	fi
+      else
+	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+	# All AIX code is PIC.
+	if test "$host_cpu" = ia64; then
+	  # AIX 5 now supports IA64 processor
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	else
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+	fi
+	;;
+      chorus*)
+	case $cc_basename in
+	cxch68*)
+	  # Green Hills C++ Compiler
+	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+	  ;;
+	esac
+	;;
+      dgux*)
+	case $cc_basename in
+	  ec++*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  ghcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      freebsd* | dragonfly*)
+	# FreeBSD uses GNU C++
+	;;
+      hpux9* | hpux10* | hpux11*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    if test "$host_cpu" != ia64; then
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	    fi
+	    ;;
+	  aCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+	    case $host_cpu in
+	    hppa*64*|ia64*)
+	      # +Z the default
+	      ;;
+	    *)
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	      ;;
+	    esac
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      interix*)
+	# This is c89, which is MS Visual C++ (no shared libs)
+	# Anyone wants to do a port?
+	;;
+      irix5* | irix6* | nonstopux*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    # CC pic flag -KPIC is the default.
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      linux* | k*bsd*-gnu)
+	case $cc_basename in
+	  KCC*)
+	    # KAI C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    ;;
+	  ecpc* )
+	    # old Intel C++ for x86_64 which still supported -KPIC.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  icpc* )
+	    # Intel C++, used to be incompatible with GCC.
+	    # ICC 10 doesn't accept -KPIC any more.
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+	    ;;
+	  pgCC* | pgcpp*)
+	    # Portland Group C++ compiler
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  cxx*)
+	    # Compaq C++
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  xlc* | xlC*)
+	    # IBM XL 8.0 on PPC
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+      lynxos*)
+	;;
+      m88k*)
+	;;
+      mvs*)
+	case $cc_basename in
+	  cxx*)
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      netbsd* | netbsdelf*-gnu)
+	;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+	case $cc_basename in
+	  KCC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+	    ;;
+	  RCC*)
+	    # Rational C++ 2.4.1
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  cxx*)
+	    # Digital/Compaq C++
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    # Make sure the PIC flag is empty.  It appears that all Alpha
+	    # Linux and Compaq Tru64 Unix objects are PIC.
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      psos*)
+	;;
+      solaris*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+	    ;;
+	  gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sunos4*)
+	case $cc_basename in
+	  CC*)
+	    # Sun C++ 4.x
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	  lcc*)
+	    # Lucid
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+	case $cc_basename in
+	  CC*)
+	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	    ;;
+	esac
+	;;
+      tandem*)
+	case $cc_basename in
+	  NCC*)
+	    # NonStop-UX NCC 3.20
+	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	    ;;
+	  *)
+	    ;;
+	esac
+	;;
+      vxworks*)
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+	;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+	# AIX 5 now supports IA64 processor
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+	# +Z the default
+	;;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+	;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+	;;
+      pgcc* | pgf77* | pgf90* | pgf95*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+	# which looks to be a dead project)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl*)
+	# IBM XL C 8.0/Fortran 10.1 on PPC
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+	;;
+      *)
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)
+	  # Sun C 5.9
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+	  ;;
+	*Sun\ F*)
+	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+	  ;;
+	esac
+	;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95*)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t at m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+	[How to pass a linker flag through the compiler])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t at m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+	[Additional compiler flags for building library objects])
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+	[Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw* | cegcc*)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  linux* | k*bsd*-gnu)
+    _LT_TAGVAR(link_all_deplibs, $1)=no
+  ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	# Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+	# support --undefined.  This deserves some investigation.  FIXME
+	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	# If the export-symbols file already is a .def file (1st line
+	# is EXPORTS), use it as is; otherwise, prepend...
+	_LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	  cp $export_symbols $output_objdir/$soname.def;
+	else
+	  echo EXPORTS > $output_objdir/$soname.def;
+	  cat $export_symbols >> $output_objdir/$soname.def;
+	fi~
+	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+	case $cc_basename in
+	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+	esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+	 && test "$tmp_diet" = no
+      then
+	tmp_addflag=
+	tmp_sharedflag='-shared'
+	case $cc_basename,$host_cpu in
+        pgcc*)				# Portland Group C compiler
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag'
+	  ;;
+	pgf77* | pgf90* | pgf95*)	# Portland Group f77 and f90 compilers
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  tmp_addflag=' $pic_flag -Mnomain' ;;
+	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+	  tmp_addflag=' -i_dynamic' ;;
+	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+	ifc* | ifort*)			# Intel Fortran compiler
+	  tmp_addflag=' -nofor_main' ;;
+	lf95*)				# Lahey Fortran 8.1
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+	  tmp_sharedflag='--shared' ;;
+	xl[[cC]]*)			# IBM XL C 8.0 on PPC (deal with xlf below)
+	  tmp_sharedflag='-qmkshrobj'
+	  tmp_addflag= ;;
+	esac
+	case `$CC -V 2>&1 | sed 5q` in
+	*Sun\ C*)			# Sun C 5.9
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+	  tmp_sharedflag='-G' ;;
+	*Sun\ F*)			# Sun Fortran 8.3
+	  tmp_sharedflag='-G' ;;
+	esac
+	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	    echo "local: *; };" >> $output_objdir/$libname.ver~
+	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+	case $cc_basename in
+	xlf*)
+	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+	  if test "x$supports_anon_versioning" = xyes; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+	      echo "local: *; };" >> $output_objdir/$libname.ver~
+	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+	  fi
+	  ;;
+	esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+	wlarc=
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+	;;
+	*)
+	  # For security reasons, it is highly recommended that you always
+	  # use absolute paths for naming shared libraries, and exclude the
+	  # DT_RUNPATH tag from executables and libraries.  But doing so
+	  # requires that you compile everything twice, which is a pain.
+	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+	  else
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	  fi
+	;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+	# Neither direct hardcoding nor static linking is supported with a
+	# broken collect2.
+	_LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test "$host_cpu" = ia64; then
+	# On IA64, the linker does run time linking by default, so we don't
+	# have to do anything special.
+	aix_use_runtimelinking=no
+	exp_sym_flag='-Bexport'
+	no_entry_flag=""
+      else
+	# If we're using GNU nm, then we don't want the "-C" option.
+	# -C means demangle to AIX nm, but means don't demangle with GNU nm
+	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	else
+	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	fi
+	aix_use_runtimelinking=no
+
+	# Test if we are trying to use run time linking or normal
+	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+	# need to do runtime linking.
+	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	  for ld_flag in $LDFLAGS; do
+	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+	    aix_use_runtimelinking=yes
+	    break
+	  fi
+	  done
+	  ;;
+	esac
+
+	exp_sym_flag='-bexport'
+	no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+      if test "$GCC" = yes; then
+	case $host_os in aix4.[[012]]|aix4.[[012]].*)
+	# We only want to do this on AIX 4.2 and lower, the check
+	# below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	  # We have reworked collect2
+	  :
+	  else
+	  # We have old collect2
+	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	  # It fails to find uninstalled libraries when the uninstalled
+	  # path is not listed in the libpath.  Setting hardcode_minus_L
+	  # to unsupported forces relinking
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+	  ;;
+	esac
+	shared_flag='-shared'
+	if test "$aix_use_runtimelinking" = yes; then
+	  shared_flag="$shared_flag "'${wl}-G'
+	fi
+	_LT_TAGVAR(link_all_deplibs, $1)=no
+      else
+	# not using gcc
+	if test "$host_cpu" = ia64; then
+	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	# chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+	else
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag='${wl}-G'
+	  else
+	    shared_flag='${wl}-bM:SRE'
+	  fi
+	fi
+      fi
+
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+	# Warning - without using the other runtime loading flags (-brtl),
+	# -berok will link without error, but may produce a broken library.
+	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+	if test "$host_cpu" = ia64; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+	else
+	 # Determine the default libpath from the value encoded in an
+	 # empty executable.
+	 _LT_SYS_MODULE_PATH_AIX
+	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	  # Warning - without using the other run time loading flags,
+	  # -berok will link without error, but may produce a broken library.
+	  _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	  _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	  # Exported symbols can be pulled into shared objects from archives
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	  # This is similar to how AIX traditionally builds its shared libraries.
+	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+	fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext_cmds=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+      _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    freebsd1*)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# hardcode_minus_L: Not really in the search PATH,
+	# but as the default location of the library.
+	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      else
+	case $host_cpu in
+	hppa*64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	ia64*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	esac
+      fi
+      if test "$with_gnu_ld" = no; then
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	case $host_cpu in
+	hppa*64*|ia64*)
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  ;;
+	*)
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+	  # hardcode_minus_L: Not really in the search PATH,
+	  # but as the default location of the library.
+	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	  ;;
+	esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	# Try to use the -exported_symbol ld option, if it does not
+	# work, assume that -exports_file does not work either and
+	# implicitly export all symbols.
+        save_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+        AC_LINK_IFELSE(int foo(void) {},
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+        )
+        LDFLAGS="$save_LDFLAGS"
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+	_LT_TAGVAR(hardcode_direct, $1)=yes
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	else
+	  case $host_os in
+	   openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+	     _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	     ;;
+	   *)
+	     _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+	     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	     ;;
+	  esac
+	fi
+      else
+	_LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+	# Both c and cxx compiler support -rpath directly
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test "$GCC" = yes; then
+	wlarc='${wl}'
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+	case `$CC -V 2>&1` in
+	*"Compilers 5.0"*)
+	  wlarc=''
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+	  ;;
+	*)
+	  wlarc='${wl}'
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+	  ;;
+	esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+	# The compiler driver will combine and reorder linker options,
+	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+	# but is careful enough not to reorder.
+	# Supported since Solaris 2.6 (maybe 2.5.1?)
+	if test "$GCC" = yes; then
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+	else
+	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	fi
+	;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+	# Use $CC to link under sequent, because it throws in some extra .o
+	# files that make .init and .fini sections work.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+	sni)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+	;;
+	siemens)
+	  ## LD is ld it makes a PLAMLIB
+	  ## CC just makes a GrossModule.
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+	  _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+	motorola)
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+	;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	runpath_var=LD_RUN_PATH
+	hardcode_runpath_var=yes
+	_LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+	_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+	;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+      $RM conftest*
+      echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+	pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+        _LT_TAGVAR(allow_undefined_flag, $1)=
+        if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+        then
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        else
+	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+        fi
+        _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $RM conftest*
+      AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
+    [[If ld is used when linking, flag to hardcode $libdir into a binary
+    during linking.  This must work even if $libdir does not exist]])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [fix_srcfile_path], [1],
+    [Fix the shell variable $srcfile for the compiler])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report which library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_PROG_CXX
+# ------------
+# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
+# compiler, we have our own version here.
+m4_defun([_LT_PROG_CXX],
+[
+pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
+AC_PROG_CXX
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_CXX
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_CXX], [])
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[AC_REQUIRE([_LT_PROG_CXX])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test "$GXX" = yes; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test "$GXX" = yes; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test "$with_gnu_ld" = yes; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='${wl}'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+	  $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test "$host_cpu" = ia64; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=""
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # need to do runtime linking.
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+	    for ld_flag in $LDFLAGS; do
+	      case $ld_flag in
+	      *-brtl*)
+	        aix_use_runtimelinking=yes
+	        break
+	        ;;
+	      esac
+	    done
+	    ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+        if test "$GXX" = yes; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+	  collect2name=`${CC} -print-prog-name=collect2`
+	  if test -f "$collect2name" &&
+	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+	  then
+	    # We have reworked collect2
+	    :
+	  else
+	    # We have old collect2
+	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
+	    # It fails to find uninstalled libraries when the uninstalled
+	    # path is not listed in the libpath.  Setting hardcode_minus_L
+	    # to unsupported forces relinking
+	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
+	  fi
+          esac
+          shared_flag='-shared'
+	  if test "$aix_use_runtimelinking" = yes; then
+	    shared_flag="$shared_flag "'${wl}-G'
+	  fi
+        else
+          # not using gcc
+          if test "$host_cpu" = ia64; then
+	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+	  # chokes on -Wl,-G. The following line is correct:
+	  shared_flag='-G'
+          else
+	    if test "$aix_use_runtimelinking" = yes; then
+	      shared_flag='${wl}-G'
+	    else
+	      shared_flag='${wl}-bM:SRE'
+	    fi
+          fi
+        fi
+
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+	# export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+        if test "$aix_use_runtimelinking" = yes; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        else
+          if test "$host_cpu" = ia64; then
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+          else
+	    # Determine the default libpath from the value encoded in an
+	    # empty executable.
+	    _LT_SYS_MODULE_PATH_AIX
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+	    # Warning - without using the other run time loading flags,
+	    # -berok will link without error, but may produce a broken library.
+	    _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+	    _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+	    # Exported symbols can be pulled into shared objects from archives
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+	    # This is similar to how AIX traditionally builds its shared
+	    # libraries.
+	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+          fi
+        fi
+        ;;
+
+      beos*)
+	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+	  # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+	  # support --undefined.  This deserves some investigation.  FIXME
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+	  # FIXME: insert proper C++ library support
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	  ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+        # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+        # as there is no search path for DLLs.
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+        _LT_TAGVAR(always_export_symbols, $1)=no
+        _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+          # If the export-symbols file already is a .def file (1st line
+          # is EXPORTS), use it as is; otherwise, prepend...
+          _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+	    cp $export_symbols $output_objdir/$soname.def;
+          else
+	    echo EXPORTS > $output_objdir/$soname.def;
+	    cat $export_symbols >> $output_objdir/$soname.def;
+          fi~
+          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+        else
+          _LT_TAGVAR(ld_shlibs, $1)=no
+        fi
+        ;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+	;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          ghcx*)
+	    # Green Hills C++ Compiler
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      freebsd[[12]]*)
+        # C++ shared libraries reported to be fairly broken before
+	# switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      gnu*)
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+				             # but as the default
+				             # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+            ;;
+          *)
+            if test "$GXX" = yes; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test $with_gnu_ld = no; then
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+					         # but as the default
+					         # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          aCC*)
+	    case $host_cpu in
+	      hppa*64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      ia64*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	      *)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	        ;;
+	    esac
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test $with_gnu_ld = no; then
+	        case $host_cpu in
+	          hppa*64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          ia64*)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	          *)
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            ;;
+	        esac
+	      fi
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+	_LT_TAGVAR(hardcode_direct, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+	# Instead, shared libraries are loaded at an image base (0x10000000 by
+	# default) and relocated if they conflict, which is a slow very memory
+	# consuming and fragmenting process.  To avoid this, we pick a random,
+	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+	;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+	    # SGI C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    if test "$GXX" = yes; then
+	      if test "$with_gnu_ld" = no; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+	      else
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+	      fi
+	    fi
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+	    ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+	    ;;
+	  icpc* | ecpc* )
+	    # Intel C++
+	    with_gnu_ld=yes
+	    # version 8.0 and above of icpc choke on multiply defined symbols
+	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+	    # earlier do not add the objects themselves.
+	    case `$CC -V 2>&1` in
+	      *"Version 7."*)
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	      *)  # Version 8.0 or newer
+	        tmp_idyn=
+	        case $host_cpu in
+		  ia64*) tmp_idyn=' -i_dynamic';;
+		esac
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+		;;
+	    esac
+	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+	    ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+	    case `$CC -V` in
+	    *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
+	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+		compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+		$RANLIB $oldlib'
+	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+		rm -rf $tpldir~
+		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    *) # Version 6 will use weak symbols
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+	      ;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+            ;;
+	  cxx*)
+	    # Compaq C++
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+	    runpath_var=LD_RUN_PATH
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+	  xl*)
+	    # IBM XL 8.0 on PPC, with GNU ld
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+	    if test "x$supports_anon_versioning" = xyes; then
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+		cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+		echo "local: *; };" >> $output_objdir/$libname.ver~
+		$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+	    fi
+	    ;;
+	  *)
+	    case `$CC -V 2>&1 | sed 5q` in
+	    *Sun\ C*)
+	      # Sun C++ 5.9
+	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	      _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+	      _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+	      # Not sure whether something based on
+	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+	      # would be better.
+	      output_verbose_link_cmd='echo'
+
+	      # Archives containing C++ object files must be created using
+	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	      # necessary to make sure instantiated templates are included
+	      # in the archive.
+	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	      ;;
+	    esac
+	    ;;
+	esac
+	;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	  *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+	esac
+	;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+	  wlarc=
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	fi
+	# Workaround some broken pre-1.5 toolchains
+	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+	;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+	;;
+
+      openbsd2*)
+        # C++ shared libraries are fairly broken
+	_LT_TAGVAR(ld_shlibs, $1)=no
+	;;
+
+      openbsd*)
+	if test -f /usr/libexec/ld.so; then
+	  _LT_TAGVAR(hardcode_direct, $1)=yes
+	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+	    _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+	  fi
+	  output_verbose_link_cmd=echo
+	else
+	  _LT_TAGVAR(ld_shlibs, $1)=no
+	fi
+	;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+	    # KCC will only create a shared library if the output file
+	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+	    # to its proper name (with version) after linking.
+	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Archives containing C++ object files must be created using
+	    # the KAI C++ compiler.
+	    case $host in
+	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+	    esac
+	    ;;
+          RCC*)
+	    # Rational C++ 2.4.1
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          cxx*)
+	    case $host in
+	      osf3*)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+		;;
+	      *)
+	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+	          echo "-hidden">> $lib.exp~
+	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+	          $RM $lib.exp'
+	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+		;;
+	    esac
+
+	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	    # Commands to make compiler produce verbose output that lists
+	    # what "hidden" libraries, object files and flags are used when
+	    # linking a shared library.
+	    #
+	    # There doesn't appear to be a way to prevent this compiler from
+	    # explicitly linking system object files so we need to strip them
+	    # from the output so that they don't get included in the library
+	    # dependencies.
+	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+	    ;;
+	  *)
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+	      case $host in
+	        osf3*)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	        *)
+	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+		  ;;
+	      esac
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+	      # Commands to make compiler produce verbose output that lists
+	      # what "hidden" libraries, object files and flags are used when
+	      # linking a shared library.
+	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+	    else
+	      # FIXME: insert proper C++ library support
+	      _LT_TAGVAR(ld_shlibs, $1)=no
+	    fi
+	    ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.x
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          lcc*)
+	    # Lucid
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC*)
+	    # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+	      $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	    case $host_os in
+	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+	      *)
+		# The compiler driver will combine and reorder linker options,
+		# but understands `-z linker_flag'.
+	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+	        ;;
+	    esac
+	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+	    output_verbose_link_cmd='echo'
+
+	    # Archives containing C++ object files must be created using
+	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+	    # necessary to make sure instantiated templates are included
+	    # in the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+	    ;;
+          gcx*)
+	    # Green Hills C++ Compiler
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+	    # The C++ compiler must be used to create the archive.
+	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+	    ;;
+          *)
+	    # GNU C++ compiler with Solaris linker
+	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+	      _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      else
+	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
+	        # platform.
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+		  $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+	        # Commands to make compiler produce verbose output that lists
+	        # what "hidden" libraries, object files and flags are used when
+	        # linking a shared library.
+	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+	      fi
+
+	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+	      case $host_os in
+		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+		*)
+		  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+		  ;;
+	      esac
+	    fi
+	    ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+	*)
+	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+	# Note: We can NOT use -z defs as we might desire, because we do not
+	# link with -lc, and that would cause any symbols used from libc to
+	# always be unresolved, which means just about no library would
+	# ever link correctly.  If we're not using GNU ld we use -z text
+	# though, which does catch some bad symbols but isn't as heavy-handed
+	# as -z defs.
+	_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+	_LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+	_LT_TAGVAR(link_all_deplibs, $1)=yes
+	_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+	runpath_var='LD_RUN_PATH'
+
+	case $cc_basename in
+          CC*)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	  *)
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+	    ;;
+	esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+	    # NonStop-UX NCC 3.20
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+          *)
+	    # FIXME: insert proper C++ library support
+	    _LT_TAGVAR(ld_shlibs, $1)=no
+	    ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)="$GXX"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" ||
+          test $p = "-R"; then
+	 prev=$p
+	 continue
+       else
+	 prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 case $p in
+	 -L* | -R*)
+	   # Internal compiler library paths should come after those
+	   # provided the user.  The postdeps already come after the
+	   # user supplied libs so there is no need to process them.
+	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+	   else
+	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+	   fi
+	   ;;
+	 # The "-l" case would never come before the object being
+	 # linked, so don't bother handling this case.
+	 esac
+       else
+	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+	   _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+	 else
+	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+	 fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+	 pre_test_object_deps_done=yes
+	 continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+	   _LT_TAGVAR(predep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+	 fi
+       else
+	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+	   _LT_TAGVAR(postdep_objects, $1)="$p"
+	 else
+	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+	 fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_PROG_F77
+# ------------
+# Since AC_PROG_F77 is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_F77],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
+AC_PROG_F77
+if test -z "$F77" || test "X$F77" = "Xno"; then
+  _lt_disable_F77=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_F77
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_F77], [])
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_REQUIRE([_LT_PROG_F77])dnl
+AC_LANG_PUSH(Fortran 77)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${F77-"f77"}
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$G77"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_PROG_FC
+# -----------
+# Since AC_PROG_FC is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_FC],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
+AC_PROG_FC
+if test -z "$FC" || test "X$FC" = "Xno"; then
+  _lt_disable_FC=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_FC
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_FC], [])
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_REQUIRE([_LT_PROG_FC])dnl
+AC_LANG_PUSH(Fortran)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  CC=${FC-"f95"}
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+	if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+	  test "$enable_shared" = yes && enable_static=no
+	fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_XSI_SHELLFNS
+# ---------------------
+# Bourne and XSI compatible variants of some useful shell functions.
+m4_defun([_LT_PROG_XSI_SHELLFNS],
+[case $xsi_shell in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  case ${1} in
+    */*) func_dirname_result="${1%/*}${2}" ;;
+    *  ) func_dirname_result="${3}" ;;
+  esac
+  func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+  # positional parameters, so assign one to ordinary parameter first.
+  func_stripname_result=${3}
+  func_stripname_result=${func_stripname_result#"${1}"}
+  func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=${1%%=*}
+  func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  case ${1} in
+    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+    *)    func_lo2o_result=${1} ;;
+  esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=${#1}
+}
+
+_LT_EOF
+    ;;
+  *) # Bourne compatible functions.
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+}
+
+# func_basename file
+func_basename ()
+{
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+dnl func_dirname_and_basename
+dnl A portable version of this function is already defined in general.m4sh
+dnl so there is no need for it here.
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+  case ${2} in
+    .*) func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+    *)  func_stripname_result=`$ECHO "X${3}" \
+           | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+  esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[[^=]]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+  func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+  func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+  func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+  func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+  func_arith_result=`expr "$[@]"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+  func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+  yes)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]+=\$[2]"
+}
+_LT_EOF
+    ;;
+  *)
+    cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+  eval "$[1]=\$$[1]\$[2]"
+}
+
+_LT_EOF
+    ;;
+  esac
+])
+
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+		      [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl `shared' nor `disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+  		   [_LT_ENABLE_FAST_INSTALL])
+  ])
+])# _LT_SET_OPTIONS
+
+
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [0], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+	[Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_static=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+	[Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+	IFS="$lt_save_ifs"
+	if test "X$pkg" = "X$p"; then
+	  enable_fast_install=yes
+	fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+	 [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic],
+	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+		 [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+		 [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+		 [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+		 [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+		 [m4_define([_LTDL_TYPE], [convenience])])
+
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+	     [m4_foreach([_Lt_suffix],
+		]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+	[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+		 [lt_append([$1], [$2], [$3])$4],
+		 [$5])],
+	  [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+	[$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
+
+# ltversion.m4 -- version numbers			-*- Autoconf -*-
+#
+#   Copyright (C) 2004 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# Generated from ltversion.in.
+
+# serial 3012 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.2.6])
+m4_define([LT_PACKAGE_REVISION], [1.3012])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.2.6'
+macro_revision='1.3012'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
+
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 4 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_RC],		[AC_DEFUN([AC_LIBTOOL_RC])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# 
+# Copyright © 2004 Scott James Remnant <scott at netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=m4_default([$1], [0.9.0])
+	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		AC_MSG_RESULT([yes])
+	else
+		AC_MSG_RESULT([no])
+		PKG_CONFIG=""
+	fi
+		
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+    if test -n "$$1"; then
+        pkg_cv_[]$1="$$1"
+    else
+        PKG_CHECK_EXISTS([$3],
+                         [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+			 [pkg_failed=yes])
+    fi
+else
+	pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+        else 
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+	ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+		[AC_MSG_RESULT([no])
+                $4])
+elif test $pkg_failed = untried; then
+	ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+		[$4])
+else
+	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+	ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.10.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # Grep'ing the whole file is not good either: AIX grep has a line
+  # limit of 2048, but all sed's we know have understand at least 4000.
+  if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+    dirpart=`AS_DIRNAME("$mf")`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`AS_DIRNAME(["$file"])`
+    AS_MKDIR_P([$dirpart/$fdir])
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 13
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+              [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+	      		     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_CC],
+                          defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_CXX],
+                          defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+                  [_AM_DEPENDENCIES(OBJC)],
+                  [define([AC_PROG_OBJC],
+                          defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([acx_pthread.m4])

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,190 @@
+dnl Available from the GNU Autoconf Macro Archive at:
+dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html
+dnl
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread pthread -pthread -pthreads -mthreads --thread-safe -mt"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthread or
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: threads are created detached by default
+        # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+        AC_MSG_CHECKING([for joinable pthread attribute])
+        AC_TRY_LINK([#include <pthread.h>],
+                    [int attr=PTHREAD_CREATE_JOINABLE;],
+                    ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+        if test x"$ok" = xunknown; then
+                AC_TRY_LINK([#include <pthread.h>],
+                            [int attr=PTHREAD_CREATE_UNDETACHED;],
+                            ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+        fi
+        if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+                AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+                          [Define to the necessary symbol if this constant
+                           uses a non-standard name on your system.])
+        fi
+        AC_MSG_RESULT(${ok})
+        if test x"$ok" = xunknown; then
+                AC_MSG_WARN([we do not know how to create joinable pthreads])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+                *-aix* | *-freebsd*)     flag="-D_THREAD_SAFE";;
+                *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+                PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        # More AIX lossage: must compile with cc_r
+        AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,11 @@
+set -x
+
+rm -f configure Makefile.in Makefile config.h.in
+
+aclocal -I .
+libtoolize --force --copy
+
+# we do not use AC_CONFIG_HEADERS
+#autoheader
+automake --add-missing --foreign
+autoconf


Property changes on: trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+if [ -d /usr/local/include/PCSC ]
+then
+	echo "move /usr/local/include/PCSC away and try again"
+	exit
+fi
+
+# we define PKG_CONFIG so that pkg-config is not used and PCSC_CFLAGS
+# and PCSC_LIBS are used instead
+PKG_CONFIG="foobar"
+
+# find pcsc-lite header files in MacOSXCCID/
+PCSC_CFLAGS="-I/System/Library/Frameworks/PCSC.framework/Versions/A/Headers"
+PCSC_LIBS="-framework PCSC"
+
+# Build a Universal Binary
+CFLAGS="$CFLAGS -isysroot /Developer/SDKs/MacOSX10.6.sdk -arch i386 -arch x86_64"
+LDFLAGS="-arch i386 -arch x86_64"
+CONFIGURE_ARGS="--disable-dependency-tracking"
+
+# install in /usr
+CONFIGURE_ARGS="$CONFIGURE_ARGS --prefix=/usr"
+
+set -x
+./configure \
+	PKG_CONFIG="$PKG_CONFIG" \
+	CFLAGS="$CFLAGS" \
+	CXXFLAGS="$CFLAGS" \
+	PCSC_CFLAGS="$PCSC_CFLAGS" \
+	PCSC_LIBS="$PCSC_LIBS" \
+	$CONFIGURE_ARGS \
+	"$@"


Property changes on: trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59)
+AC_INIT(libgtop11dotnet, 2.1.2, hotline at gemalto.com)
+AM_INIT_AUTOMAKE
+AC_CONFIG_SRCDIR([PKCS11Module2/pkcs11.cpp])
+AC_CHECK_PROG([PKGCONFIG], [pkg-config], [yes])
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_LN_S
+AC_PROG_MKDIR_P
+AC_PROG_MAKE_SET
+AC_PROG_CPP
+AC_PROG_LIBTOOL
+
+AC_C_BIGENDIAN
+
+# Select OS specific versions of source files.
+AC_SUBST(DYN_LIB_EXT)
+case "$host" in
+*-*-darwin*)
+	DYN_LIB_EXT="dylib"
+	;;
+*)
+	DYN_LIB_EXT="so"
+esac
+
+# Special check for pthread support
+ACX_PTHREAD(
+[
+	AC_DEFINE(HAVE_PTHREAD, 1,
+		[Define if you have POSIX threads libraries and header files.])
+], [
+	AC_MSG_ERROR([POSIX thread support required])
+])
+
+CC="$PTHREAD_CC"
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+
+# check pcsc-lite version
+OLD_LIBS="$LIBS"
+PKG_CHECK_MODULES(PCSC, libpcsclite, [],
+    [ AC_MSG_WARN([install pcsc-lite]) ])
+LIBS="$OLD_LIBS"
+
+OLD_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS"
+AC_CHECK_HEADER(winscard.h,,
+    [AC_MSG_ERROR([winscard.h not found, install pcsc-lite, or use PCSC_CFLAGS=... ./configure])])
+CPPFLAGS="$OLD_CPPFLAGS"
+
+OLD_LIBS="$LIBS"
+LIBS="$LIBS $PCSC_LIBS"
+AC_MSG_CHECKING([for SCardEstablishContext])
+AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ],
+    [AC_MSG_ERROR([SCardEstablishContext() not found, install pcsc-lite,or use PCSC_LDLIBS=... ./configure])])
+LIBS="$OLD_LIBS"
+
+CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS"
+AC_CHECK_TYPES([LPCTSTR],,,[#include <winscard.h>])
+AC_CHECK_TYPES([LPCSTR],,,[#include <winscard.h>])
+CPPFLAGS="$OLD_CPPFLAGS"
+
+AC_CONFIG_FILES([
+	Makefile
+	PKCS11Module2/Makefile
+	])
+AC_OUTPUT
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,970 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable:4201)
+#endif
+
+#include <string.h>
+#include <winscard.h>
+#include <stdexcept>
+#include "MarshallerCfg.h"
+#include "Except.h"
+#include "Array.h"
+
+// Determine Processor Endianess
+#include <limits.h>
+#if (UINT_MAX == 0xffffffffUL)
+   typedef unsigned int _u4;
+#else
+#  if (ULONG_MAX == 0xffffffffUL)
+     typedef unsigned long _u4;
+#  else
+#    if (USHRT_MAX == 0xffffffffUL)
+       typedef unsigned short _u4;
+#    endif
+#  endif
+#endif
+
+_u4 _endian = 1;
+
+bool isLittleEndian = (*((unsigned char *)(&_endian))) ? true  : false;
+bool isBigEndian    = (*((unsigned char *)(&_endian))) ? false : true;
+MARSHALLER_NS_BEGIN
+
+
+static u4 ToBigEndian(u4 val)
+{
+    if (isBigEndian)
+    {
+	    return val;
+    }
+    else
+    {
+        u4 res;
+        res =  val << 24;
+        res |= (val << 8) & 0x00FF0000;
+        res |= (val >> 8) & 0x0000FF00;
+        res |= val >> 24;
+
+        return res;
+    }
+}
+
+static u2 ToBigEndian(u2 val)
+{
+    if (isBigEndian)
+    {
+    	return val;
+    }
+    else
+    {
+        return (u2)((val << 8) | (val >> 8));
+    }
+}
+
+static u8 ToBigEndian(u8 val)
+{
+    if (isBigEndian)
+    {
+    	return val;
+    }
+    else
+    {
+	    u4 val1 = (u4)(val >> 32);
+	    u4 val2 = (u4)val;
+
+        val1 = ToBigEndian(val1);
+        val2 = ToBigEndian(val2);
+
+	    return (u8)(((u8)val2 << 32) | val1);
+    }
+}
+
+u2 ComputeUTF8Length(M_SAL_IN lpCharPtr str)
+{
+    u4 nCharProcessed = 0;
+    u4 pair;
+    u4 count;
+    u2 leftOver;
+    u4 charIndex;
+
+    count = 0;
+    leftOver = 0;
+    charIndex = 0;
+
+    while (nCharProcessed < (u4)strlen(str)) {
+        u2 ch = (u2)str[charIndex++];
+
+        if (leftOver == 0) {
+			if ((ch >= 0xD800) && (ch <= 0xDBFF)) {
+				// This is a low-part of a surrogate pair.
+				leftOver = (u2)ch;
+                nCharProcessed++;
+				continue;
+			} else {
+				// This is a regular character.
+				pair = (u4)ch;
+			}
+		} else if ((ch >= 0xDC00) && (ch <= 0xDFFF)) {
+			// This is a high-part of a surrogate pair. We now have a complete surrogate pair.
+			pair = ((leftOver - (u4)0xD800) << 10) + (((u4)ch) - (u4)0xDC00) + (u4)0x10000;
+			leftOver = 0;
+		} else {
+            goto error;
+		}
+
+        // Encode the character pair value.
+		if (pair < (u4)0x0080) {
+            count++;
+		} else if (pair < (u4)0x0800) {
+            count += 2;
+		} else if (pair < (u4)0x10000) {
+            count += 3;
+		} else {
+            count += 4;
+		}
+
+        nCharProcessed++;
+    }
+
+    if (leftOver != 0) {
+        goto error;
+    }
+
+	return (u2)count;
+
+error:;
+    throw Exception("Error while compute UTF8 encoding length");
+}
+
+void UTF8Encode(M_SAL_IN lpCharPtr str, u1Array &utf8Data)
+{
+    u4 nCharProcessed = 0;
+    u4 pair;
+    u2 leftOver;
+    u1* bytes = utf8Data.GetBuffer();
+    u4 byteCount;
+    u4 byteIndex = 0;
+    u4 charIndex = 0;
+
+    byteCount = utf8Data.GetLength();
+
+    leftOver = 0;
+
+    while (nCharProcessed < (u4)strlen(str)) {
+        u2 ch = str[charIndex++];
+
+        if (leftOver == 0) {
+			if ((ch >= 0xD800) && (ch <= 0xDBFF)) {
+				// This is a low-part of a surrogate pair.
+				leftOver = (u2)ch;
+                nCharProcessed++;
+				continue;
+			} else {
+				// This is a regular character.
+				pair = (u4)ch;
+			}
+		} else if ((ch >= 0xDC00) && (ch <= 0xDFFF)) {
+			// This is a high-part of a surrogate pair. We now have a complete surrogate pair.
+			pair = ((leftOver - (u4)0xD800) << 10) + (((u4)ch) - (u4)0xDC00) + (u4)0x10000;
+			leftOver = 0;
+		} else {
+            goto error;
+		}
+
+        // Encode the character pair value.
+		if (pair < (u4)0x0080) {
+            if (byteIndex >= byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)pair;
+		} else if (pair < (u4)0x0800) {
+            if ((byteIndex + 2) > byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)(0xC0 | (pair >> 6));
+			bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+		} else if (pair < (u4)0x10000) {
+            if ((byteIndex + 3) > byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)(0xE0 | (pair >> 12));
+			bytes[byteIndex++] = (u1)(0x80 | ((pair >> 6) & 0x3F));
+			bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+		} else {
+            if ((byteIndex + 4) > byteCount) {
+                goto end;
+			}
+            bytes[byteIndex++] = (u1)(0xF0 | (pair >> 18));
+			bytes[byteIndex++] = (u1)(0x80 | ((pair >> 12) & 0x3F));
+			bytes[byteIndex++] = (u1)(0x80 | ((pair >> 6) & 0x3F));
+			bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+		}
+
+        nCharProcessed++;
+    }
+
+end:;
+    // we do accept byteIndex <= byteCount (dest buffer length > what is really necessary).
+    if (byteIndex > byteCount) {
+        goto error;
+    }
+
+    if (leftOver != 0) {
+        goto error;
+    }
+
+    return;
+
+error:;
+    throw Exception("Error while performing UTF8 encoding");
+}
+
+u2 ComputeLPSTRLength(u1Array &array, u4 offset, u4 len)
+{
+	if ((u8)(offset + len) > (u8)array.GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	} else {
+		u2 charlen = 0;
+		u4 i;
+		u1* buff = array.GetBuffer();
+
+		for (i = 0; i < len;) {
+			if ((buff[i + offset] & 0x80) == 0) {
+				i += 1;
+			}
+			else if ((buff[i + offset] & 0xE0) == 0xC0) {
+				i += 2;
+			}
+			else if ((buff[i + offset] & 0xF0) == 0xE0) {
+				i += 3;
+			}
+			else {
+				throw Exception("Error parsing UTF-8 bytes");
+			}
+			charlen++;
+		}
+		return charlen;
+	}
+}
+
+void UTF8Decode(u1Array &array, u4 offset, u4 len, M_SAL_INOUT lpCharPtr &charData)
+{
+	if ((u8)(offset + len) > (u8)array.GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	} else {
+		u4 i = 0;
+		u4 pos = 0;
+		u1* buff = array.GetBuffer();
+
+		for (i = 0; i < len;) {
+			if ((buff[i + offset] & 0x80) == 0) {
+				charData[pos] = buff[i + offset];
+				i += 1;
+			}
+			else if ((buff[i + offset] & 0xE0) == 0xC0) {
+				charData[pos] = ((buff[i + offset] & 0x1F) << 6) | (buff[i+1 + offset] & 0x3F);
+				i += 2;
+			}
+			else if ((buff[i + offset] & 0xF0) == 0xE0) {
+				charData[pos] = ((buff[i + offset] & 0x0F) << 12) | ((buff[i+1 + offset] & 0x3F) << 6) | (buff[i+2 + offset] & 0x3F);
+				i += 3;
+			}
+			else{
+				throw Exception("Error parsing UTF-8 bytes");
+			}
+			pos++;
+		}
+	}
+}
+
+// *******************
+// String Array class
+// *******************
+StringArray::StringArray(s4 nelement)
+{
+    this->_length = nelement;
+
+	if (nelement < 0) {
+        nelement = 0;
+    }
+
+	this->buffer = new std::string*[nelement];
+
+	// we need to initialize the buffer to zeros
+	for(s4 i=0;i<nelement;i++)
+		this->buffer[i] = NULL;
+
+}
+
+StringArray::StringArray(const StringArray &rhs)
+{
+	s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+
+	this->buffer = new std::string*[len];
+
+	for(s4 i=0;i<len;i++)
+		this->buffer[i] = rhs.buffer[i];
+
+}
+
+StringArray::~StringArray(void)
+{
+    // delete the strings in the StringArray
+    for(u4 i = 0; i < GetLength(); i++){
+        if (buffer[i] != NULL) {
+            delete buffer[i];
+            buffer[i] = NULL;
+        }
+    }
+
+	delete[] buffer;
+}
+
+u1 StringArray::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+u4 StringArray::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+std::string* StringArray::GetStringAt(u4 index)
+{
+	if (index >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[index];
+}
+
+void StringArray::SetStringAt(u4 index, M_SAL_IN std::string* str)
+{
+	if (index >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+	this->buffer[index] = str;
+}
+
+// *******************
+// Byte Array class
+// *******************
+
+u1Array::u1Array()
+{
+  this->_length = 0;
+// JCD
+  this->buffer = NULL;//new u1[0];
+// JCD
+}
+
+u1Array::u1Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u1[nelement];
+}
+
+u1Array::u1Array(const u1Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u1[len];
+    memcpy(this->buffer, rhs.buffer, len);
+}
+
+u1Array::u1Array(u1Array &array, u4 offset, u4 len)
+{
+	if ((u8)(offset + len) > array.GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	} else {
+		this->_length = len;
+		this->buffer = new u1[len];
+		memcpy(this->buffer, array.buffer + offset, len);
+	}
+}
+
+u1Array::~u1Array(void)
+{
+    if (this->buffer != NULL) {
+        delete[] this->buffer;
+        this->buffer = NULL;
+    }
+}
+
+u1 u1Array::IsNull(void) const
+{
+    return (this->_length < 0);
+}
+
+void u1Array::SetU1At(u4 pos, u1 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+
+u1 u1Array::ReadU1At(u4 pos) const
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u1Array::GetLength(void) const
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u1Array::SetBuffer(const u1* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength());
+}
+
+const u1* u1Array::GetBuffer(void) const
+{
+    return this->buffer;
+}
+
+u1* u1Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+// 1 byte add
+u1Array& u1Array::operator +(u1 val)
+{
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u1));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u1));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u1 val)
+{
+    u1* tempBuffer = new u1[this->GetLength() + sizeof(u1)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u1));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u1);
+    return *this;
+}
+
+// 2 bytes add
+u1Array& u1Array::operator +(u2 val)
+{
+    val = ToBigEndian(val);
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u2));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u2));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u2 val)
+{
+    val = ToBigEndian(val);
+    u1* tempBuffer = new u1[this->GetLength() + sizeof(u2)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u2));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u2);
+    return *this;
+}
+
+// 4 bytes add
+u1Array& u1Array::operator +(u4 val)
+{
+    val = ToBigEndian(val);
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u4));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u4));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u4 val)
+{
+    val = ToBigEndian(val);
+    u1* tempBuffer = new u1[this->GetLength() + sizeof(u4)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u4));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u4);
+    return *this;
+}
+
+// 8 bytes add
+u1Array& u1Array::operator +(u8 val)
+{
+	val = ToBigEndian(val);
+    u1Array* newArray = new u1Array(this->GetLength() + sizeof(u8));
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u8));
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u8 val)
+{
+	val = ToBigEndian(val);
+	u1* tempBuffer = new u1[this->GetLength() + sizeof(u8)];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u8));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + sizeof(u8);
+    return *this;
+}
+
+
+// bytes array add
+u1Array& u1Array::operator =(const u1Array &bArray)
+{
+    delete[] buffer; buffer = 0;
+    _length = bArray._length;
+    buffer = new u1[_length > 0 ? _length : 0];
+    if(_length>0)
+        memcpy(buffer, bArray.buffer, _length);
+    return *this;
+}
+
+u1Array& u1Array::operator +(u1Array &bArray)
+{
+    s4 len;
+    if (IsNull() && bArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + bArray.GetLength();
+    }
+    u1Array* newArray = new u1Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength());
+    memcpy(&newArray->buffer[this->GetLength()], bArray.buffer, bArray.GetLength());
+    return *newArray;
+}
+
+u1Array& u1Array::operator +=(u1Array &bArray)
+{
+    u1* tempBuffer = new u1[this->GetLength() + bArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength());
+    memcpy(&tempBuffer[this->GetLength()], bArray.buffer, bArray.GetLength());
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && bArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + bArray.GetLength();
+    }
+    return *this;
+}
+
+u1Array& u1Array::Append(std::string* str)
+{
+	if (str == NULL) {
+        *this += (u2)0xFFFF;
+    } else {
+		u2 strLen = ComputeUTF8Length((lpCharPtr)str->c_str());
+        *this += strLen;
+        u1Array strArray(strLen);
+		UTF8Encode((lpCharPtr)str->c_str(), strArray);
+        *this += strArray;
+    }
+    return *this;
+}
+
+// *******************
+// UShort Array class
+// *******************
+u2Array::u2Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u2[nelement];
+}
+
+u2Array::u2Array(const u2Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u2[len];
+    memcpy(this->buffer, rhs.buffer, len * sizeof(u2));
+}
+
+u2Array::~u2Array(void)
+{
+    delete[] this->buffer;
+}
+
+u1 u2Array::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+void u2Array::SetU2At(u4 pos, u2 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+u2 u2Array::ReadU2At(u4 pos)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u2Array::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u2Array::SetBuffer(u2* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength() * sizeof(u2));
+}
+
+u2* u2Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+// 2 bytes add
+u2Array& u2Array::operator +(u2 val)
+{
+    u2Array* newArray = new u2Array(this->GetLength() + 1);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u2));
+	newArray->buffer[this->GetLength()] = val;
+    return *newArray;
+}
+
+u2Array& u2Array::operator +=(u2 val)
+{
+    u2* tempBuffer = new u2[this->GetLength() + 1];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u2));
+	tempBuffer[this->GetLength()] = val;
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + 1;
+    return *this;
+}
+
+// Char array add
+u2Array& u2Array::operator +(u2Array &cArray)
+{
+    s4 len;
+	if (IsNull() && cArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + cArray.GetLength();
+    }
+    u2Array* newArray = new u2Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u2));
+    memcpy(&newArray->buffer[this->GetLength() * sizeof(u2)], cArray.buffer, cArray.GetLength() * sizeof(u2));
+    return *newArray;
+}
+
+u2Array& u2Array::operator +=(u2Array &cArray)
+{
+    u2* tempBuffer = new u2[this->GetLength() + cArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u2));
+    memcpy(&tempBuffer[this->GetLength() * sizeof(u2)], cArray.buffer, cArray.GetLength() * sizeof(u2));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && cArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + cArray.GetLength();
+    }
+    return *this;
+}
+
+// *******************
+// Int Array class
+// *******************
+u4Array::u4Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u4[nelement];
+}
+
+u4Array::u4Array(const u4Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u4[len];
+    memcpy(this->buffer, rhs.buffer, len * sizeof(u4));
+}
+
+u4Array::~u4Array(void)
+{
+    delete[] this->buffer;
+}
+
+u1 u4Array::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+void u4Array::SetU4At(u4 pos, u4 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+u4 u4Array::ReadU4At(u4 pos)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u4Array::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u4Array::SetBuffer(u4* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength() * sizeof(u4));
+}
+
+u4* u4Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+// 4 bytes add
+u4Array& u4Array::operator +(u4 val)
+{
+    u4Array* newArray = new u4Array(this->GetLength() + 1);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u4));
+	newArray->buffer[this->GetLength()] = val;
+    return *newArray;
+}
+
+u4Array& u4Array::operator +=(u4 val)
+{
+    u4* tempBuffer = new u4[this->GetLength() + 1];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u4));
+	tempBuffer[this->GetLength()] = val;
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + 1;
+    return *this;
+}
+
+// UInt array add
+u4Array& u4Array::operator +(u4Array &iArray)
+{
+    s4 len;
+	if (IsNull() && iArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + iArray.GetLength();
+    }
+    u4Array* newArray = new u4Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u4));
+    memcpy(&newArray->buffer[this->GetLength() * sizeof(u4)], iArray.buffer, iArray.GetLength() * sizeof(u4));
+    return *newArray;
+}
+
+u4Array& u4Array::operator +=(u4Array &iArray)
+{
+    u4* tempBuffer = new u4[this->GetLength() + iArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u4));
+    memcpy(&tempBuffer[this->GetLength() * sizeof(u4)], iArray.buffer, iArray.GetLength() * sizeof(u4));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && iArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + iArray.GetLength();
+    }
+    return *this;
+}
+
+
+// *******************
+// Long Array class
+// *******************
+u8Array::u8Array(s4 nelement)
+{
+	this->_length = nelement;
+    if (nelement < 0) {
+        nelement = 0;
+    }
+    this->buffer = new u8[nelement];
+}
+
+u8Array::u8Array(const u8Array &rhs)
+{
+    s4 len = rhs._length;
+    this->_length = len;
+    if (len < 0) {
+        len = 0;
+    }
+    this->buffer = new u8[len];
+    memcpy(this->buffer, rhs.buffer, len * sizeof(u8));
+}
+
+u8Array::~u8Array(void)
+{
+    delete[] this->buffer;
+}
+
+u1 u8Array::IsNull(void)
+{
+    return (this->_length < 0);
+}
+
+void u8Array::SetU8At(u4 pos, u8 val)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    this->buffer[pos] = val;
+}
+
+u8 u8Array::ReadU8At(u4 pos)
+{
+	if (pos >= GetLength()) {
+		throw ArgumentOutOfRangeException((lpCharPtr)"");
+	}
+    return this->buffer[pos];
+}
+
+u4 u8Array::GetLength(void)
+{
+    if (IsNull()) {
+        return (u4)0;
+    } else {
+        return (u4)this->_length;
+    }
+}
+
+void u8Array::SetBuffer(u8* buffer)
+{
+    memcpy(this->buffer, buffer, this->GetLength() * sizeof(u8));
+}
+
+u8* u8Array::GetBuffer(void)
+{
+    return this->buffer;
+}
+
+u8Array& u8Array::operator +(u8 val)
+{
+    u8Array* newArray = new u8Array(this->GetLength() + 1);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u8));
+	newArray->buffer[this->GetLength()] = val;
+    return *newArray;
+}
+
+u8Array& u8Array::operator +=(u8 val)
+{
+    u8* tempBuffer = new u8[this->GetLength() + 1];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u8));
+	tempBuffer[this->GetLength()] = val;
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+    this->_length = this->GetLength() + 1;
+    return *this;
+}
+
+u8Array& u8Array::operator +(u8Array &iArray)
+{
+    s4 len;
+	if (IsNull() && iArray.IsNull()) {
+        len = -1;
+    } else {
+        len = this->GetLength() + iArray.GetLength();
+    }
+    u8Array* newArray = new u8Array(len);
+    memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u8));
+    memcpy(&newArray->buffer[this->GetLength() * sizeof(u8)], iArray.buffer, iArray.GetLength() * sizeof(u8));
+    return *newArray;
+}
+
+u8Array& u8Array::operator +=(u8Array &iArray)
+{
+    u8* tempBuffer = new u8[this->GetLength() + iArray.GetLength()];
+    memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u8));
+    memcpy(&tempBuffer[this->GetLength() * sizeof(u8)], iArray.buffer, iArray.GetLength() * sizeof(u8));
+    delete[] this->buffer;
+    this->buffer = tempBuffer;
+	if (IsNull() && iArray.IsNull()) {
+        this->_length = -1;
+    } else {
+        this->_length = this->GetLength() + iArray.GetLength();
+    }
+    return *this;
+}
+
+MARSHALLER_NS_END
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,180 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_array_h
+#define _include_marshaller_array_h
+
+MARSHALLER_NS_BEGIN
+
+class SMARTCARDMARSHALLER_DLLAPI StringArray
+{
+
+private:
+	std::string** buffer;
+    s4 _length;
+
+public:
+    StringArray(s4 nelement);
+    StringArray(const StringArray &rhs);
+    ~StringArray(void);
+
+    u1 IsNull(void);
+    u4 GetLength(void);
+
+	std::string* GetStringAt(u4 index);
+	void  SetStringAt(u4 index,M_SAL_IN std::string* str);
+};
+
+#define s8Array u8Array
+class SMARTCARDMARSHALLER_DLLAPI u8Array
+{
+
+private:
+    u8* buffer;
+    s4 _length;
+
+public:
+    u8Array(s4 nelement);
+    u8Array(const u8Array &rhs);
+    ~u8Array(void);
+
+    u1 IsNull(void);
+    u4 GetLength(void);
+
+    void  SetBuffer(u8* buffer);
+    u8*   GetBuffer(void);
+
+	u8 ReadU8At(u4 pos);
+    void SetU8At(u4 pos, u8 val);
+
+    u8Array& operator +(u8 val);
+    u8Array& operator +=(u8 val);
+    u8Array& operator +(u8Array &cArray);
+    u8Array& operator +=(u8Array &cArray);
+
+};
+
+#define s4Array u4Array
+class SMARTCARDMARSHALLER_DLLAPI u4Array
+{
+
+private:
+    u4* buffer;
+    s4 _length;
+
+public:
+    u4Array(s4 nelement);
+    u4Array(const u4Array &rhs);
+    ~u4Array(void);
+
+    u1 IsNull(void);
+    u4 GetLength(void);
+
+    void  SetBuffer(u4* buffer);
+    u4*   GetBuffer(void);
+
+	u4 ReadU4At(u4 pos);
+    void SetU4At(u4 pos, u4 val);
+
+    u4Array& operator +(u4 val);
+    u4Array& operator +=(u4 val);
+    u4Array& operator +(u4Array &cArray);
+    u4Array& operator +=(u4Array &cArray);
+};
+
+#define s2Array u2Array
+#define charArray u2Array
+class SMARTCARDMARSHALLER_DLLAPI u2Array
+{
+
+private:
+    u2* buffer;
+    s4 _length;
+
+public:
+    u2Array(s4 nelement);
+    u2Array(const u2Array &rhs);
+    ~u2Array(void);
+
+    u1    IsNull(void);
+    u4    GetLength(void);
+
+    void  SetBuffer(u2* buffer);
+    u2*   GetBuffer(void);
+
+	u2    ReadU2At(u4 pos);
+    void  SetU2At(u4 pos, u2 val);
+
+    u2Array& operator +(u2 val);
+    u2Array& operator +=(u2 val);
+    u2Array& operator +(u2Array &cArray);
+    u2Array& operator +=(u2Array &cArray);
+};
+
+#define s1Array u1Array
+#define MemoryStream u1Array
+class SMARTCARDMARSHALLER_DLLAPI u1Array
+{
+
+private:
+    u1* buffer;
+    s4 _length;
+
+public:
+    u1Array();
+    u1Array(s4 nelement);
+    u1Array(const u1Array &rhs);
+	u1Array(u1Array &array, u4 offset, u4 len);
+    ~u1Array(void);
+
+    u1  IsNull(void) const;
+    u4  GetLength(void) const;
+
+    void  SetBuffer(const u1* buffer);
+    const u1*  GetBuffer(void) const;
+    u1*  GetBuffer(void);
+
+    u1   ReadU1At(u4 pos) const;
+	void SetU1At(u4 pos, u1 val);
+
+	u1Array& Append(std::string* str);
+
+    u1Array& operator +(u1 val);
+    u1Array& operator +=(u1 val);
+    u1Array& operator +(u2 val);
+    u1Array& operator +=(u2 val);
+    u1Array& operator +(u4 val);
+    u1Array& operator +=(u4 val);
+	u1Array& operator +(u8 val);
+    u1Array& operator +=(u8 val);
+    u1Array& operator =(const u1Array &bArray);
+    u1Array& operator +(u1Array &bArray);
+    u1Array& operator +=(u1Array &bArray);
+};
+
+extern u2 ComputeUTF8Length(M_SAL_IN lpCharPtr str);
+extern void UTF8Encode(M_SAL_IN lpCharPtr str, u1Array &utf8Data);
+extern u2 ComputeLPSTRLength(u1Array &array, u4 offset, u4 len);
+extern void UTF8Decode(u1Array &array, u4 offset, u4 len, M_SAL_INOUT lpCharPtr &charData);
+
+MARSHALLER_NS_END
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,338 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_except_h
+#define _include_marshaller_except_h
+
+MARSHALLER_NS_BEGIN
+
+// .NET specific exception classes
+class Exception  : public std::runtime_error{
+
+public:
+	explicit Exception(std::string msg): std::runtime_error(msg) { }
+	const char *what() const throw(){
+		return std::runtime_error::what();
+	}
+};
+
+class SystemException : public Exception{
+
+public:
+	explicit SystemException(std::string msg) : Exception(msg) { }
+	explicit SystemException(char *msg) : Exception(NULL != msg ? msg : "") { }
+};
+
+class ArgumentException : public Exception{
+
+public:
+	explicit ArgumentException(std::string msg) : Exception(msg) { }
+	explicit ArgumentException();
+	explicit ArgumentException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArgumentNullException : public Exception{
+
+public:
+	explicit ArgumentNullException(std::string msg) : Exception(msg) { }
+	explicit ArgumentNullException();
+	explicit ArgumentNullException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArgumentOutOfRangeException : public Exception{
+
+public:
+	explicit ArgumentOutOfRangeException(std::string msg) : Exception(msg) { }
+	explicit ArgumentOutOfRangeException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class IndexOutOfRangeException : public Exception{
+
+public:
+	explicit IndexOutOfRangeException(std::string  msg) : Exception(msg) { }
+	explicit IndexOutOfRangeException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class InvalidCastException : public Exception{
+
+public:
+	explicit InvalidCastException(std::string  msg) : Exception(msg) { }
+	explicit InvalidCastException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class InvalidOperationException : public Exception{
+
+public:
+	explicit InvalidOperationException(std::string msg) : Exception(msg) { }
+	explicit InvalidOperationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NotImplementedException : public Exception{
+
+public:
+	explicit NotImplementedException(std::string msg) : Exception(msg) { }
+	explicit NotImplementedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NotSupportedException : public Exception{
+
+public:
+	explicit NotSupportedException(std::string msg) : Exception(msg) { }
+	explicit NotSupportedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NullReferenceException : public Exception{
+
+public:
+	explicit NullReferenceException(std::string msg) : Exception(msg) { }
+	explicit NullReferenceException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class OutOfMemoryException : public Exception{
+
+public:
+	explicit OutOfMemoryException(std::string msg) : Exception(msg) { }
+	explicit OutOfMemoryException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class UnauthorizedAccessException : public Exception{
+
+public:
+	explicit UnauthorizedAccessException(std::string msg) : Exception(msg) { }
+	explicit UnauthorizedAccessException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ObjectDisposedException : public Exception{
+
+public:
+	explicit ObjectDisposedException(std::string msg) : Exception(msg) { }
+	explicit ObjectDisposedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ApplicationException : public Exception{
+
+public:
+	explicit ApplicationException(std::string msg) : Exception(msg) { }
+	explicit ApplicationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArithmeticException : public Exception{
+
+public:
+	explicit ArithmeticException(std::string msg) : Exception(msg) { }
+	explicit ArithmeticException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArrayTypeMismatchException : public Exception{
+
+public:
+	explicit ArrayTypeMismatchException(std::string msg) : Exception(msg) { }
+	explicit ArrayTypeMismatchException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class BadImageFormatException : public Exception{
+
+public:
+	explicit BadImageFormatException(std::string msg) : Exception(msg) { }
+	explicit BadImageFormatException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class CryptographicException : public Exception{
+
+public:
+	explicit CryptographicException(std::string msg) : Exception(msg) { }
+	explicit CryptographicException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class DirectoryNotFoundException : public Exception{
+
+public:
+	explicit DirectoryNotFoundException(std::string msg) : Exception(msg) { }
+	explicit DirectoryNotFoundException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class DivideByZeroException : public Exception{
+
+public:
+	explicit DivideByZeroException(std::string msg) : Exception(msg) { }
+	explicit DivideByZeroException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class FileNotFoundException : public Exception{
+
+public:
+	explicit FileNotFoundException(std::string msg) : Exception(msg) { }
+	explicit FileNotFoundException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class FormatException : public Exception{
+
+public:
+	explicit FormatException(std::string msg) : Exception(msg) { }
+	explicit FormatException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class IOException : public Exception{
+
+public:
+	explicit IOException(std::string msg) : Exception(msg) { }
+	explicit IOException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class RankException : public Exception{
+
+public:
+	explicit RankException(std::string msg) : Exception(msg) { }
+	explicit RankException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class RemotingException : public Exception{
+
+private:
+	s4 resultCode;	// this code is for PCSC releated error/success codes
+
+public:
+	explicit RemotingException(std::string msg) : Exception(msg) {
+		this->resultCode = 0;
+	}
+	explicit RemotingException(char *msg) : Exception(NULL != msg ? msg : "") {
+		this->resultCode = 0;
+	}
+	explicit RemotingException(std::string msg,s4 resultCode) : Exception(msg){
+		this->resultCode = resultCode;
+	}
+	explicit RemotingException(char *msg,s4 resultCode) : Exception(NULL != msg ? msg : ""){
+		this->resultCode = resultCode;
+	}
+	explicit RemotingException(s4 resultCode) : Exception(""){
+		this->resultCode = resultCode;
+	}
+	s4 getResultCode(){
+		return this->resultCode;
+	}
+};
+
+class StackOverflowException : public Exception{
+
+public:
+	explicit StackOverflowException(std::string msg) : Exception(msg) { }
+	explicit StackOverflowException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class TypeLoadException : public Exception{
+
+public:
+	explicit TypeLoadException(std::string msg) : Exception(msg) { }
+	explicit TypeLoadException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MemberAccessException : public Exception{
+
+public:
+	explicit MemberAccessException(std::string msg) : Exception(msg) { }
+	explicit MemberAccessException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingFieldException : public Exception{
+
+public:
+	explicit MissingFieldException(std::string msg) : Exception(msg) { }
+	explicit MissingFieldException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingMemberException : public Exception{
+
+public:
+	explicit MissingMemberException(std::string msg) : Exception(msg) { }
+	explicit MissingMemberException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingMethodException : public Exception{
+
+public:
+	explicit MissingMethodException(std::string msg) : Exception(msg) { }
+	explicit MissingMethodException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class OverflowException : public Exception{
+
+public:
+	explicit OverflowException(std::string msg) : Exception(msg) { }
+	explicit OverflowException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class SecurityException : public Exception{
+
+public:
+	explicit SecurityException(std::string msg) : Exception(msg) { }
+	explicit SecurityException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class VerificationException : public Exception{
+
+public:
+	explicit VerificationException(std::string msg) : Exception(msg) { }
+	explicit VerificationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class SerializationException : public Exception{
+
+public:
+	explicit SerializationException(std::string msg) : Exception(msg) { }
+	explicit SerializationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,1781 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable:4201)
+#else
+#define DBG_UNREFERENCED_LOCAL_VARIABLE(a)
+#endif
+
+#ifdef INCLUDE_VLD
+#include <vld.h>
+#endif
+
+#ifdef __APPLE__
+#include <pcsclite.h>
+#endif
+
+#ifndef WIN32
+#include <strings.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdexcept>
+#include <winscard.h>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#ifndef _XCL_
+#include "PCSC.h"
+#else // _XCL_
+#include "xcl_broker.h"
+#endif // _XCL_
+#include "Marshaller.h"
+#include "Except.h"
+
+#include "log.h"
+
+MARSHALLER_NS_BEGIN
+
+#define SUPPORT_BETA_VERSION
+
+#define APDU_TO_CARD_MAX_SIZE                                   0xFF
+
+#define HIVECODE_NAMESPACE_SYSTEM                               0x00D25D1C
+#define HIVECODE_NAMESPACE_SYSTEM_IO                            0x00D5E6DB
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CHANNELS     0x0000886E
+#define HIVECODE_NAMESPACE_NETCARD_FILESYSTEM                   0x00A1AC39
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING              0x00EB3DD9
+#define HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY         0x00ACF53B
+#define HIVECODE_NAMESPACE_SYSTEM_COLLECTIONS                   0x00C5A010
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CONTEXTS     0x001F4994
+#define HIVECODE_NAMESPACE_SYSTEM_SECURITY                      0x00964145
+#define HIVECODE_NAMESPACE_SYSTEM_REFLECTION                    0x0008750F
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION         0x008D3B3D
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_MESSAGING    0x00DEB940
+#define HIVECODE_NAMESPACE_SYSTEM_DIAGNOSTICS                   0x0097995F
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_COMPILERSERVICES      0x00F63E11
+#define HIVECODE_NAMESPACE_SYSTEM_TEXT                          0x00702756
+
+#define HIVECODE_TYPE_SYSTEM_VOID           0xCE81
+#define HIVECODE_TYPE_SYSTEM_INT32          0x61C0
+#define HIVECODE_TYPE_SYSTEM_INT32_ARRAY    0x61C1
+#define HIVECODE_TYPE_SYSTEM_BOOLEAN        0x2227
+#define HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY  0x2228
+#define HIVECODE_TYPE_SYSTEM_SBYTE          0x767E
+#define HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY    0x767F
+#define HIVECODE_TYPE_SYSTEM_UINT16         0xD98B
+#define HIVECODE_TYPE_SYSTEM_UINT16_ARRAY   0xD98C
+#define HIVECODE_TYPE_SYSTEM_UINT32         0x95E7
+#define HIVECODE_TYPE_SYSTEM_UINT32_ARRAY   0x95E8
+#define HIVECODE_TYPE_SYSTEM_BYTE           0x45A2
+#define HIVECODE_TYPE_SYSTEM_BYTE_ARRAY     0x45A3
+#define HIVECODE_TYPE_SYSTEM_CHAR           0x958E
+#define HIVECODE_TYPE_SYSTEM_CHAR_ARRAY     0x958F
+#define HIVECODE_TYPE_SYSTEM_INT16          0xBC39
+#define HIVECODE_TYPE_SYSTEM_INT16_ARRAY    0xBC3A
+#define HIVECODE_TYPE_SYSTEM_STRING         0x1127
+#define HIVECODE_TYPE_SYSTEM_STRING_ARRAY   0x1128
+#define HIVECODE_TYPE_SYSTEM_INT64			0xDEFB
+#define HIVECODE_TYPE_SYSTEM_INT64_ARRAY	0xDEFC
+#define HIVECODE_TYPE_SYSTEM_UINT64			0x71AF
+#define HIVECODE_TYPE_SYSTEM_UINT64_ARRAY	0x71B0
+
+#define HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM 0xFED7
+
+// for port discovery lookup.
+#define CARDMANAGER_SERVICE_PORT                                                    1
+#define CARDMANAGER_SERVICE_NAME                                                    "ContentManager"
+#define HIVECODE_NAMESPACE_SMARTCARD                                                0x00F5EFBF
+#define HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER                                      0xB18C
+#define HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT                  0x7616
+
+#define HIVECODE_TYPE_SYSTEM_EXCEPTION                                      0xD4B0
+#define HIVECODE_TYPE_SYSTEM_SYSTEMEXCEPTION                                0x28AC
+#define HIVECODE_TYPE_SYSTEM_OUTOFMEMORYEXCEPTION                           0xE14E
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTEXCEPTION                              0xAB8C
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTNULLEXCEPTION                          0x2138
+#define HIVECODE_TYPE_SYSTEM_NULLREFERENCEEXCEPTION                         0xC5B8
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION                    0x6B11
+#define HIVECODE_TYPE_SYSTEM_NOTSUPPORTEDEXCEPTION                          0xAA74
+#define HIVECODE_TYPE_SYSTEM_INVALIDCASTEXCEPTION                           0xD24F
+#define HIVECODE_TYPE_SYSTEM_INVALIDOPERATIONEXCEPTION                      0xFAB4
+#define HIVECODE_TYPE_SYSTEM_NOTIMPLEMENTEDEXCEPTION                        0x3CE5
+#define HIVECODE_TYPE_SYSTEM_OBJECTDISPOSEDEXCEPTION                        0x0FAC
+#define HIVECODE_TYPE_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION                    0x4697
+#define HIVECODE_TYPE_SYSTEM_INDEXOUTOFRANGEEXCEPTION                       0xBF1D
+#define HIVECODE_TYPE_SYSTEM_FORMATEXCEPTION                                0xF3BF
+#define HIVECODE_TYPE_SYSTEM_ARITHMETICEXCEPTION                            0x6683
+#define HIVECODE_TYPE_SYSTEM_OVERFLOWEXCEPTION                              0x20A0
+#define HIVECODE_TYPE_SYSTEM_BADIMAGEFORMATEXCEPTION                        0x530A
+#define HIVECODE_TYPE_SYSTEM_APPLICATIONEXCEPTION                           0xB1EA
+#define HIVECODE_TYPE_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION                     0x3F88
+#define HIVECODE_TYPE_SYSTEM_DIVIDEBYZEROEXCEPTION                          0xDFCF
+#define HIVECODE_TYPE_SYSTEM_MEMBERACCESSEXCEPTION                          0xF5F3
+#define HIVECODE_TYPE_SYSTEM_MISSINGMEMBEREXCEPTION                         0x20BB
+#define HIVECODE_TYPE_SYSTEM_MISSINGFIELDEXCEPTION                          0x7366
+#define HIVECODE_TYPE_SYSTEM_MISSINGMETHODEXCEPTION                         0x905B
+#define HIVECODE_TYPE_SYSTEM_RANKEXCEPTION                                  0xB2AE
+#define HIVECODE_TYPE_SYSTEM_STACKOVERFLOWEXCEPTION                         0x0844
+#define HIVECODE_TYPE_SYSTEM_TYPELOADEXCEPTION                              0x048E
+#define HIVECODE_TYPE_SYSTEM_IO_IOEXCEPTION                                 0x3BBE
+#define HIVECODE_TYPE_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION                  0x975A
+#define HIVECODE_TYPE_SYSTEM_IO_FILENOTFOUNDEXCEPTION                       0x07EB
+#define HIVECODE_TYPE_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION             0xD52A
+#define HIVECODE_TYPE_SYSTEM_RUNTIME_SERIALIZATION_SERIALIZATIONEXCEPTION   0xA1D2
+#define HIVECODE_TYPE_SYSTEM_SECURITY_SECURITYEXCEPTION						0x31AF
+#define HIVECODE_TYPE_SYSTEM_SECURITY_VERIFICATIONEXCEPTION					0x67F1
+#define HIVECODE_TYPE_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION   0x8FEB
+
+#ifdef SMARTCARDMARSHALLER_EXPORTS
+
+BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
+{
+   UNREFERENCED_PARAMETER(hModule);
+   UNREFERENCED_PARAMETER(lpReserved);
+
+   switch (ul_reason_for_call)
+   {
+   case DLL_PROCESS_ATTACH:
+   case DLL_THREAD_ATTACH:
+   case DLL_THREAD_DETACH:
+   case DLL_PROCESS_DETACH:
+      break;
+   }
+   return TRUE;
+}
+
+#endif
+
+static u2 ComReadU2At(u1Array &array, u4 pos)
+{
+   if ((u8)(pos + sizeof(u2)) > (u8)array.GetLength()) {
+      throw ArgumentOutOfRangeException((lpCharPtr)"");
+   }
+   u1* buff = array.GetBuffer();
+   return (u2)((((u2)buff[pos]) << 8) + buff[pos + 1]);
+}
+
+u4 ComReadU4At(u1Array &array, u4 pos);
+u4 ComReadU4At(u1Array &array, u4 pos)
+{
+   if ((u8)(pos + sizeof(u4)) > (u8)array.GetLength()) {
+      throw ArgumentOutOfRangeException((lpCharPtr)"");
+   }
+   u1* buff = array.GetBuffer();
+   return (u4)((((u4)buff[pos]) << 24) + (((u4)buff[pos + 1]) << 16) + (((u4)buff[pos + 2]) << 8) + buff[pos + 3]);
+}
+
+static u8 ComReadU8At(u1Array &array, u4 pos)
+{
+   if ((u8)(pos + sizeof(u8)) > (u8)array.GetLength()) {
+      throw ArgumentOutOfRangeException((lpCharPtr)"");
+   }
+   u1* buff = array.GetBuffer();
+
+   u1 b1 = buff[pos];
+   u1 b2 = buff[pos + 1];
+   u1 b3 = buff[pos + 2];
+   u1 b4 = buff[pos + 3];
+   u1 b5 = buff[pos + 4];
+   u1 b6 = buff[pos + 5];
+   u1 b7 = buff[pos + 6];
+   u1 b8 = buff[pos + 7];
+
+   return (((u8)b1 << 56) | ((u8)b2 << 48) | ((u8)b3 << 40) | ((u8)b4 << 32) | ((u8)b5 << 24) | ((u8)b6 << 16) | ((u8)b7 << 8) | b8);
+}
+
+static void ProcessException(u1Array answer, u4 protocolOffset)
+{
+   u4 exceptionNamespace;
+   u4 exceptionName;
+   char* chst = NULL;
+
+   try {
+      exceptionNamespace = ComReadU4At(answer, protocolOffset + 0);
+      exceptionName      = ComReadU2At(answer, protocolOffset + 4);
+
+      if (answer.GetLength() > (protocolOffset + 6)) {
+         u2 strLen = ComReadU2At(answer, protocolOffset + 6);
+         if ((strLen > 0) && (strLen != 0xFFFF)) {
+            u2 len = ComputeLPSTRLength(answer, protocolOffset + 8, strLen);
+            chst = new char[len + 1];
+            chst[len] = '\0';
+            UTF8Decode(answer, protocolOffset + 8, strLen, chst);
+         }
+      }
+   } catch (...) {
+      // someone is messing with the protocol
+      if (chst != NULL) {
+         delete[] chst;
+      }
+      throw RemotingException((lpCharPtr)"");
+   }
+
+   if (chst == NULL) {
+      // prepare empty string
+      chst = new char[1];
+      chst[0] = '\0';
+   }
+
+   // create a string object on the stack.
+   // when exception is thrown the exception object is copied on
+   // a temporary location and live till used by catch block
+   //
+   // it is not a good idea to pass chst as a parameter of exception object
+   // as there will be no way to delete it.
+   std::string chstr(chst);
+
+   delete[] chst;
+
+   switch (exceptionNamespace)
+   {
+   case HIVECODE_NAMESPACE_SYSTEM:
+      {
+         switch(exceptionName){
+
+   case (u2)HIVECODE_TYPE_SYSTEM_EXCEPTION:
+      throw Exception(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_SYSTEMEXCEPTION:
+      throw SystemException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_OUTOFMEMORYEXCEPTION:
+      throw OutOfMemoryException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTEXCEPTION:
+      throw ArgumentException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTNULLEXCEPTION:
+      throw ArgumentNullException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_NULLREFERENCEEXCEPTION:
+      throw NullReferenceException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION:
+      throw ArgumentOutOfRangeException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_NOTSUPPORTEDEXCEPTION:
+      throw NotSupportedException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_INVALIDCASTEXCEPTION:
+      throw InvalidCastException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_INVALIDOPERATIONEXCEPTION:
+      throw InvalidOperationException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_NOTIMPLEMENTEDEXCEPTION:
+      throw NotImplementedException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_OBJECTDISPOSEDEXCEPTION:
+      throw ObjectDisposedException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION:
+      throw UnauthorizedAccessException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_INDEXOUTOFRANGEEXCEPTION:
+      throw IndexOutOfRangeException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_FORMATEXCEPTION:
+      throw FormatException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARITHMETICEXCEPTION:
+      throw ArithmeticException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_OVERFLOWEXCEPTION:
+      throw OverflowException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_BADIMAGEFORMATEXCEPTION:
+      throw BadImageFormatException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_APPLICATIONEXCEPTION:
+      throw ApplicationException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION:
+      throw ArrayTypeMismatchException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_DIVIDEBYZEROEXCEPTION:
+      throw DivideByZeroException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MEMBERACCESSEXCEPTION:
+      throw MemberAccessException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MISSINGMEMBEREXCEPTION:
+      throw MissingMemberException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MISSINGFIELDEXCEPTION:
+      throw MissingFieldException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_MISSINGMETHODEXCEPTION:
+      throw MissingMethodException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_RANKEXCEPTION:
+      throw RankException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_STACKOVERFLOWEXCEPTION:
+      throw StackOverflowException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_TYPELOADEXCEPTION:
+      throw TypeLoadException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_IO:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_IO_IOEXCEPTION:
+      throw IOException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION:
+      throw DirectoryNotFoundException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_IO_FILENOTFOUNDEXCEPTION:
+      throw FileNotFoundException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_SECURITY:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_SECURITYEXCEPTION:
+      throw SecurityException(chstr);
+
+   case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_VERIFICATIONEXCEPTION:
+      throw VerificationException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION:
+      throw RemotingException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_RUNTIME_SERIALIZATION_SERIALIZATIONEXCEPTION:
+      throw SerializationException(chstr);
+         }
+      }
+      break;
+
+   case HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY:
+      {
+         switch(exceptionName){
+   case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION:
+      throw CryptographicException(chstr);
+         }
+      }
+      break;
+   }
+
+   // custom exception from the card application or someone is messing with the protocol
+   // no means of translation.
+   throw Exception(chstr);
+}
+
+u4 CheckForException(u1Array answer, u4 nameSpace, u2 type);
+u4 CheckForException(u1Array answer, u4 nameSpace, u2 type)
+{
+   u1 protocolAnswerPrefix = answer.ReadU1At(0);
+
+#ifdef SUPPORT_BETA_VERSION
+   if (protocolAnswerPrefix == 0) {
+      // beta version protocol (namespace & type systematically returned)
+      if ((ComReadU4At(answer, 0) != nameSpace) || (ComReadU2At(answer, 4) != type)) {
+         ProcessException(answer, 0);
+      }
+      // skip namespace & type
+      return (4 + 2);
+   }
+#endif
+
+   // new protocol
+   if (protocolAnswerPrefix != 0x01) {
+      if (protocolAnswerPrefix == 0xFF) {
+         // exception info expected in the buffer
+         ProcessException(answer, 1);
+      } else {
+         // someone is messing with the protocol
+         throw RemotingException((lpCharPtr)"");
+      }
+   }
+
+   // skip return type info (protocolAnswerPrefix: 0x01 = ok, 0xFF = exception)
+   return 1;
+}
+
+SmartCardMarshaller::SmartCardMarshaller(SCARDHANDLE cardHandle, u2 portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode)
+{
+   this->uri = NULL;
+   this->pcsc = NULL;
+   this->portNumber = portNumber;
+   this->nameSpaceHivecode = nameSpaceHivecode;
+   this->typeHivecode = typeHivecode;
+   this->ProcessInputStream  = NULL;
+   this->ProcessOutputStream = NULL;
+
+#ifndef _XCL_
+   this->pcsc = new PCSC(cardHandle);
+#else // _XCL_
+    this->pcsc = new XCLBroker(cardHandle);
+#endif // _XCL_
+
+   try {
+      this->uri = new std::string(uri->c_str());
+   } catch (...) {
+      delete this->pcsc;
+      throw;
+   }
+}
+
+SmartCardMarshaller::SmartCardMarshaller(M_SAL_IN std::string* readerName, u2 portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index)
+{
+   Log::begin( "SmartCardMarshaller::SmartCardMarshaller" );
+
+   this->uri = NULL;
+   this->pcsc = NULL;
+   this->portNumber = portNumber;
+   this->nameSpaceHivecode = nameSpaceHivecode;
+   this->typeHivecode = typeHivecode;
+   this->ProcessInputStream  = NULL;
+   this->ProcessOutputStream = NULL;
+
+#ifdef WIN32
+   if ((readerName == NULL) || (_stricmp("selfdiscover", readerName->c_str()) == 0))
+   {
+#else
+   if ((readerName == NULL) || (strncasecmp("selfdiscover", readerName->c_str(),readerName->length()) == 0))
+   {
+#endif
+      Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index) ..." );
+#ifndef _XCL_
+      this->pcsc = new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index);
+#else // _XCL
+        this->pcsc = new XCLBroker(readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index);
+#endif // _XCL_
+      Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index) ok" );
+   }
+   else
+   {
+      Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName ) ..." );
+#ifndef _XCL_
+      this->pcsc = new PCSC( readerName );
+#else // _XCL_
+        this->pcsc = new XCLBroker(readerName);
+#endif // _XCL_
+      Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new PCSC( readerName ) ok" );
+   }
+
+   try
+   {
+      Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new std::string(uri->c_str()) ..." );
+      this->uri = new std::string(uri->c_str());
+      Log::log( "SmartCardMarshaller::SmartCardMarshaller -  new std::string(uri->c_str()) ok" );
+   }
+   catch (...)
+   {
+      Log::error( "SmartCardMarshaller::SmartCardMarshaller", "(...)" );
+      delete this->pcsc;
+      throw;
+   }
+
+   Log::end( "SmartCardMarshaller::SmartCardMarshaller" );
+}
+
+std::string* SmartCardMarshaller::GetReaderName(void)
+{
+   return this->pcsc->GetReaderName();
+}
+
+SCARDHANDLE SmartCardMarshaller::GetCardHandle(void)
+{
+   return this->pcsc->GetCardHandle();
+}
+
+void SmartCardMarshaller::DoTransact(bool flag)
+{
+   this->pcsc->DoTransact(flag);
+}
+
+SmartCardMarshaller::~SmartCardMarshaller(void)
+{
+   if (this->uri != NULL) {
+      delete this->uri;
+      this->uri = NULL;
+   }
+
+   if (this->pcsc != NULL) {
+      delete this->pcsc;
+      this->pcsc = NULL;
+   }
+}
+
+void SmartCardMarshaller::UpdatePCSCCardHandle(SCARDHANDLE hCard)
+{
+   this->pcsc->SetCardHandle(hCard);
+}
+
+static void ProcessByReferenceArguments(u1 type, u1Array* dataArray, u4* offsetPtr, va_list* markerPtr, u1 isIn)
+{
+   //va_list marker = *markerPtr;
+   u4 offset = *offsetPtr;
+
+   switch (type) {
+
+        case MARSHALLER_TYPE_REF_BOOL:
+        case MARSHALLER_TYPE_REF_U1:
+        case MARSHALLER_TYPE_REF_S1:
+           {
+              u1* val = va_arg(/*marker*/*markerPtr, u1*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = (*dataArray).ReadU1At(offset);
+              }
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_CHAR:
+        case MARSHALLER_TYPE_REF_U2:
+        case MARSHALLER_TYPE_REF_S2:
+           {
+              u2* val = va_arg(/*marker*/*markerPtr, u2*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = ComReadU2At(*dataArray, offset);
+              }
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_U4:
+        case MARSHALLER_TYPE_REF_S4:
+           {
+              u4* val = va_arg(/*marker*/*markerPtr, u4*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = ComReadU4At(*dataArray, offset);
+              }
+              offset += sizeof(u4);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_U8:
+        case MARSHALLER_TYPE_REF_S8:
+           {
+              u8* val = va_arg(/*marker*/*markerPtr, u8*);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 *dataArray += *val;
+              }
+              else {
+                 *val = ComReadU8At(*dataArray, offset);
+              }
+              offset += sizeof(u8);
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_STRING:
+           {
+              std::string** val = va_arg(/*marker*/*markerPtr, std::string**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+              if (isIn == TRUE) {
+                 offset += sizeof(u2);
+                 if (*val != NULL) {
+                    offset += ComputeUTF8Length((lpCharPtr)((*val)->c_str()));
+                 }
+                 (*dataArray).Append(*val);
+              } else {
+                 u2 len = ComReadU2At(*dataArray, offset);
+                 offset += sizeof(u2);
+                 if (len == 0xFFFF) {
+                    *val = NULL;
+                 } else {
+                    // store result
+                    u2 l = ComputeLPSTRLength(*dataArray, offset, len);
+                    char* chstr = new char[l + 1];
+                    try {
+                       chstr[l] = '\0';
+                       UTF8Decode(*dataArray, offset, len, chstr);
+                       *val = new std::string(chstr);
+                    } catch (...) {
+                       delete[] chstr;
+                       throw;
+                    }
+                    delete[] chstr;
+                    offset += len;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S1ARRAY:
+        case MARSHALLER_TYPE_REF_BOOLARRAY:
+        case MARSHALLER_TYPE_REF_U1ARRAY:
+           {
+              u1Array** val = va_arg(/*marker*/*markerPtr, u1Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u1* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u1) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u1Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u1Array(-1);
+                    } else {
+                       refArray = new u1Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU1At(i, dataArray->ReadU1At(offset));
+                          offset += sizeof(u1);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S2ARRAY:
+        case MARSHALLER_TYPE_REF_U2ARRAY:
+           {
+              u2Array** val = va_arg(/*marker*/*markerPtr, u2Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u2* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u2) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u2Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u2Array(-1);
+                    } else {
+                       refArray = new u2Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU2At(i, ComReadU2At(*dataArray, offset));
+                          offset += sizeof(u2);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S4ARRAY:
+        case MARSHALLER_TYPE_REF_U4ARRAY:
+           {
+              u4Array** val = va_arg(/*marker*/*markerPtr, u4Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u4* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u4) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u4Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u4Array(-1);
+                    } else {
+                       refArray = new u4Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU4At(i, ComReadU4At(*dataArray, offset));
+                          offset += sizeof(u4);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_REF_S8ARRAY:
+        case MARSHALLER_TYPE_REF_U8ARRAY:
+           {
+              u8Array** val = va_arg(/*marker*/*markerPtr, u8Array**);
+              if (val == NULL) {
+                 throw NullReferenceException((lpCharPtr)"");
+              }
+
+              if (isIn == TRUE) {
+                 offset += sizeof(u4);
+                 if ((*val)->IsNull() == FALSE) {
+                    u4  valLen = (*val)->GetLength();
+                    u8* valBuf = (*val)->GetBuffer();
+                    *dataArray += valLen;
+                    for(u4 v = 0; v < valLen; v++) {
+                       *dataArray += valBuf[v];
+                    }
+                    offset += (sizeof(u8) * valLen);
+                 } else {
+                    *dataArray += 0xFFFFFFFF;
+                 }
+              } else {
+
+                 u4 len = ComReadU4At(*dataArray, offset);
+                 offset += sizeof(u4);
+
+                 u8Array* refArray = NULL;
+
+                 try {
+                    if (len == 0xFFFFFFFF) {
+                       refArray = new u8Array(-1);
+                    } else {
+                       refArray = new u8Array(len);
+                       for (u4 i = 0; i < len; i++) {
+                          refArray->SetU8At(i, ComReadU8At(*dataArray, offset));
+                          offset += sizeof(u4);
+                       }
+                    }
+                 } catch (...) {
+                    if (refArray != NULL) {
+                       delete refArray;
+                    }
+                    throw;
+                 }
+
+                 if (*val != NULL) {
+                    // perform cleanup
+                    delete *val;
+                 }
+
+                 *val = refArray;
+              }
+           }
+           break;
+
+        default:
+           {
+              if (isIn == TRUE) {
+                 throw Exception("Un-recognized input argument type");
+              } else {
+                 throw Exception("Un-recognized byref argument type");
+              }
+           }
+           break;
+   }
+
+   //*markerPtr = marker;
+   *offsetPtr = offset;
+}
+
+
+static void ProcessOutputArguments(u1 type, u1Array* answerPtr, u4* offsetPtr, va_list* markerPtr)
+{
+   switch (type) {
+
+        case MARSHALLER_TYPE_IN_BOOL:
+        case MARSHALLER_TYPE_IN_S1:
+        case MARSHALLER_TYPE_IN_U1:
+        case MARSHALLER_TYPE_IN_CHAR:
+        case MARSHALLER_TYPE_IN_S2:
+        case MARSHALLER_TYPE_IN_U2:
+        case MARSHALLER_TYPE_IN_S4:
+        case MARSHALLER_TYPE_IN_U4:
+        case MARSHALLER_TYPE_IN_STRING:
+        case MARSHALLER_TYPE_IN_MEMORYSTREAM:
+        case MARSHALLER_TYPE_IN_BOOLARRAY:
+        case MARSHALLER_TYPE_IN_S1ARRAY:
+        case MARSHALLER_TYPE_IN_U1ARRAY:
+        case MARSHALLER_TYPE_IN_CHARARRAY:
+        case MARSHALLER_TYPE_IN_S2ARRAY:
+        case MARSHALLER_TYPE_IN_U2ARRAY:
+        case MARSHALLER_TYPE_IN_S4ARRAY:
+        case MARSHALLER_TYPE_IN_U4ARRAY:
+        case MARSHALLER_TYPE_IN_S8ARRAY:
+        case MARSHALLER_TYPE_IN_U8ARRAY:
+        case MARSHALLER_TYPE_IN_STRINGARRAY:
+           {
+              // ignore input argument (slot size = 4 bytes)
+              //va_list marker = *markerPtr;
+              /*u4 v = */va_arg(/*marker*/*markerPtr, u4);
+              //*markerPtr = marker;
+
+              /*DBG_UNREFERENCED_LOCAL_VARIABLE(v);*/
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S8:
+        case MARSHALLER_TYPE_IN_U8:
+           {
+              // ignore input argument (slot size = 8 bytes)
+              //va_list marker = *markerPtr;
+              /*u8 v = */va_arg(/*marker*/*markerPtr, u8);
+              //*markerPtr = marker;
+
+              /*DBG_UNREFERENCED_LOCAL_VARIABLE(v);*/
+           }
+           break;
+
+        default:
+           ProcessByReferenceArguments(type, answerPtr, offsetPtr, markerPtr, FALSE);
+           break;
+   }
+}
+
+static u4 ProcessReturnType(u1 type, u1Array* answerPtr, va_list* markerPtr)
+{
+   u1Array answer = *answerPtr;
+   u4 offset = 0;
+   //va_list marker = *markerPtr;
+
+   switch (type) {
+
+      // void (can happen for the method return param)
+        case MARSHALLER_TYPE_RET_VOID:
+           {
+              if (answer.GetLength() > 0) {
+#ifdef SUPPORT_BETA_VERSION
+                 if (answer.ReadU1At(0) == 0x00) {
+                    // beta version protocol
+                    ProcessException(answer, 0);
+                 }
+#endif
+                 // new protocol
+                 ProcessException(answer, 1);
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_BOOL:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BOOLEAN);
+              u1* valToReturn = va_arg(/*marker*/*markerPtr, u1*);
+              if (answer.ReadU1At(offset) == 0) {
+                 *valToReturn = FALSE;
+              } else {
+                 *valToReturn = TRUE;
+              }
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S1:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_SBYTE);
+              s1* valToReturn = va_arg(/*marker*/*markerPtr, s1*);
+              *valToReturn = answer.ReadU1At(offset);
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U1:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BYTE);
+              u1* valToReturn = va_arg(/*marker*/*markerPtr, u1*);
+              *valToReturn = answer.ReadU1At(offset);
+              offset += sizeof(u1);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_CHAR:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_CHAR);
+              char* valToReturn = va_arg(/*marker*/*markerPtr, char*);
+              *valToReturn = (char)ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S2:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT16);
+              s2* valToReturn = va_arg(/*marker*/*markerPtr, s2*);
+              *valToReturn = ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U2:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT16);
+              u2* valToReturn = va_arg(/*marker*/*markerPtr, u2*);
+              *valToReturn = ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S4:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
+              s4* valToReturn = va_arg(/*marker*/*markerPtr, s4*);
+              *valToReturn = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U4:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT32);
+              u4* valToReturn = va_arg(/*marker*/*markerPtr, u4*);
+              *valToReturn = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S8:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT64);
+              s8* valToReturn = va_arg(/*marker*/*markerPtr, s8*);
+              *valToReturn = ComReadU8At(answer, offset);
+              offset += sizeof(u8);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U8:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT64);
+              u8* valToReturn = va_arg(/*marker*/*markerPtr, u8*);
+              *valToReturn = ComReadU8At(answer, offset);
+              offset += sizeof(u8);
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_STRING:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_STRING);
+              std::string** valToReturn = va_arg(/*marker*/*markerPtr, std::string**);
+              u2 len = ComReadU2At(answer, offset);
+              offset += sizeof(u2);
+              if (len == 0xFFFF) {
+                 *valToReturn = NULL;
+              } else {
+                 // store result
+                 u2 l = ComputeLPSTRLength(answer, offset, len);
+                 char* chstr = new char[l + 1];
+                 try {
+                    chstr[l] = '\0';
+                    UTF8Decode(answer, offset, len, chstr);
+                    *valToReturn = new std::string(chstr);
+                 } catch (...) {
+                    delete[] chstr;
+                    throw;
+                 }
+                 delete[] chstr;
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_BOOLARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY);
+              u1Array** valToReturn = va_arg(/*marker*/*markerPtr, u1Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u1Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u1Array(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S1ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY);
+              s1Array** valToReturn = va_arg(/*marker*/*markerPtr, s1Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s1Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s1Array(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U1ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY);
+              u1Array** valToReturn = va_arg(/*marker*/*markerPtr, u1Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u1Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u1Array(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_CHARARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_CHAR_ARRAY);
+              charArray** valToReturn = va_arg(/*marker*/*markerPtr, charArray**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new charArray(-1);
+              } else {
+                 // store result
+                 *valToReturn = new charArray(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+                       offset += sizeof(s2);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S2ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT16_ARRAY);
+              s2Array** valToReturn = va_arg(/*marker*/*markerPtr, s2Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s2Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s2Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+                       offset += sizeof(s2);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U2ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT16_ARRAY);
+              u2Array** valToReturn = va_arg(/*marker*/*markerPtr, u2Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u2Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u2Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+                       offset += sizeof(u2);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S4ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32_ARRAY);
+              s4Array** valToReturn = va_arg(/*marker*/*markerPtr, s4Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s4Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s4Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU4At(answer, offset);
+                       offset += sizeof(s4);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U4ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT32_ARRAY);
+              u4Array** valToReturn = va_arg(/*marker*/*markerPtr, u4Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u4Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u4Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU4At(answer, offset);
+                       offset += sizeof(u4);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_S8ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT64_ARRAY);
+              s8Array** valToReturn = va_arg(/*marker*/*markerPtr, s8Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new s8Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new s8Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU8At(answer, offset);
+                       offset += sizeof(s8);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_U8ARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT64_ARRAY);
+              u8Array** valToReturn = va_arg(/*marker*/*markerPtr, u8Array**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new u8Array(-1);
+              } else {
+                 // store result
+                 *valToReturn = new u8Array(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       (*valToReturn)->GetBuffer()[j] = ComReadU8At(answer, offset);
+                       offset += sizeof(u8);
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_STRINGARRAY:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_STRING_ARRAY);
+              StringArray** valToReturn = va_arg(/*marker*/*markerPtr, StringArray**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new StringArray(-1);
+              } else {
+                 // store result
+                 *valToReturn = new StringArray(len);
+                 try {
+                    for (u4 j = 0; j < len; j++) {
+                       u2 lenStr = ComReadU2At(answer, offset);
+                       offset += sizeof(u2);
+                       if (lenStr != 0xFFFF) {
+                          u2 blen = ComputeLPSTRLength(answer, offset, lenStr);
+                          char* lpstr = new char[blen + 1];
+                          try {
+                             lpstr[blen] = '\0';
+                             UTF8Decode(answer, offset, lenStr, lpstr);
+                             offset += lenStr;
+
+                             (*valToReturn)->SetStringAt(j, new std::string(lpstr));
+                          } catch (...) {
+                             delete[] lpstr;
+                             throw;
+                          }
+                          delete[] lpstr;
+                       }
+                    }
+                 } catch (...) {
+                    delete *valToReturn;
+                    throw;
+                 }
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_RET_MEMORYSTREAM:
+           {
+              offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM_IO, HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM);
+              MemoryStream** valToReturn = va_arg(/*marker*/*markerPtr, MemoryStream**);
+              u4 len = ComReadU4At(answer, offset);
+              offset += sizeof(u4);
+              if (len == 0xFFFFFFFF) {
+                 *valToReturn = new MemoryStream(-1);
+              } else {
+                 // store result
+                 *valToReturn = new MemoryStream(answer, offset, len);
+                 offset += len;
+              }
+           }
+           break;
+
+        default:
+           {
+              throw Exception("Un-recognized return type");
+           }
+           break;
+   }
+
+   //*markerPtr = marker;
+   return offset;
+}
+
+static void ProcessInputArguments(u1 type, u1Array* invokeAPDU_data, va_list* markerPtr)
+{
+   //va_list marker = *markerPtr;
+
+   switch (type) {
+
+        case MARSHALLER_TYPE_IN_BOOL:
+        case MARSHALLER_TYPE_IN_S1:
+        case MARSHALLER_TYPE_IN_U1:
+           {
+              u1 val = (u1)va_arg(/*marker*/*markerPtr, s4);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_CHAR:
+        case MARSHALLER_TYPE_IN_S2:
+        case MARSHALLER_TYPE_IN_U2:
+           {
+              u2 val = (u2)va_arg(/*marker*/*markerPtr, s4);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S4:
+        case MARSHALLER_TYPE_IN_U4:
+           {
+              u4 val = (u4)va_arg(/*marker*/*markerPtr, s4);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S8:
+        case MARSHALLER_TYPE_IN_U8:
+           {
+              u8 val = (u8)va_arg(/*marker*/*markerPtr,u8);
+              *invokeAPDU_data += val;
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_STRING:
+           {
+              std::string* val = va_arg(/*marker*/*markerPtr, std::string*);
+              (*invokeAPDU_data).Append(val);
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_MEMORYSTREAM:
+        case MARSHALLER_TYPE_IN_BOOLARRAY:
+        case MARSHALLER_TYPE_IN_S1ARRAY:
+        case MARSHALLER_TYPE_IN_U1ARRAY:
+           {
+              u1Array* val = va_arg(/*marker*/*markerPtr, u1Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u1* valBuf = val->GetBuffer();
+                 // add length
+                 *invokeAPDU_data += valLen;
+                 // add data
+                 for(u4 v = 0; v < valLen; v++)
+                    *invokeAPDU_data += valBuf[v];
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_CHARARRAY:
+        case MARSHALLER_TYPE_IN_S2ARRAY:
+        case MARSHALLER_TYPE_IN_U2ARRAY:
+           {
+              u2Array* val = va_arg(/*marker*/*markerPtr, u2Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u2* valBuf = val->GetBuffer();
+                 *invokeAPDU_data += valLen;
+                 for(u4 v = 0; v < valLen; v++) {
+                    *invokeAPDU_data += valBuf[v];
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S4ARRAY:
+        case MARSHALLER_TYPE_IN_U4ARRAY:
+           {
+              u4Array* val = va_arg(/*marker*/*markerPtr, u4Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u4* valBuf = val->GetBuffer();
+                 *invokeAPDU_data += valLen;
+                 for(u4 v = 0; v < valLen; v++) {
+                    *invokeAPDU_data += valBuf[v];
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_S8ARRAY:
+        case MARSHALLER_TYPE_IN_U8ARRAY:
+           {
+              u8Array* val = va_arg(/*marker*/*markerPtr, u8Array*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 u8* valBuf = val->GetBuffer();
+                 *invokeAPDU_data += valLen;
+                 for(u4 v = 0; v < valLen; v++) {
+                    *invokeAPDU_data += valBuf[v];
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        case MARSHALLER_TYPE_IN_STRINGARRAY:
+           {
+              StringArray* val = va_arg(/*marker*/*markerPtr, StringArray*);
+              if ((val != NULL) && (val->IsNull() == FALSE)) {
+                 u4  valLen = val->GetLength();
+                 *invokeAPDU_data += valLen;
+                 // add data
+                 for (u4 j = 0; j < valLen; j++) {
+                    std::string* str = val->GetStringAt(j);
+                    if(str == NULL){ // add null pointer
+                       *invokeAPDU_data += (u2)0xFFFF;
+                    }else{
+                       (*invokeAPDU_data).Append(str);
+                    }
+                 }
+              } else {
+                 // add null pointer
+                 *invokeAPDU_data += (u4)0xFFFFFFFF;
+              }
+           }
+           break;
+
+        default:
+           u4 offset = 0;
+           ProcessByReferenceArguments(type, invokeAPDU_data, &offset, /*markerPtr*/markerPtr, TRUE);
+           // do not adjust markerPtr.
+           return;
+
+   }
+
+   //*markerPtr = marker;
+}
+
+void SmartCardMarshaller::Invoke(s4 nParam, ...)
+{
+   // Allow selfdiscovery of port
+   if (this->portNumber == 0) {
+      s4 _s4 = 0;
+      u4 nameSpaceHivecode = this->nameSpaceHivecode;
+      u2 typeHivecode      = this->typeHivecode;
+      std::string* uri     = this->uri;
+
+      this->portNumber		= CARDMANAGER_SERVICE_PORT;
+      this->nameSpaceHivecode = HIVECODE_NAMESPACE_SMARTCARD;
+      this->typeHivecode		= HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
+      this->uri				= new std::string(CARDMANAGER_SERVICE_NAME);
+
+      try {
+
+         // call the GetAssociatedPort method.
+         Invoke(3, HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT, MARSHALLER_TYPE_IN_S4, nameSpaceHivecode, MARSHALLER_TYPE_IN_S2, typeHivecode, MARSHALLER_TYPE_IN_STRING, uri, MARSHALLER_TYPE_RET_S4, &_s4);
+
+      } catch (...) {
+
+         delete this->uri;
+
+         this->portNumber		= (u2)_s4;
+         this->nameSpaceHivecode = nameSpaceHivecode;
+         this->typeHivecode		= typeHivecode;
+         this->uri				= uri;
+
+         throw;
+      }
+
+      delete this->uri;
+
+      this->portNumber		= (u2)_s4;
+      this->nameSpaceHivecode = nameSpaceHivecode;
+      this->typeHivecode		= typeHivecode;
+      this->uri				= uri;
+   }
+
+   u1Array invokeAPDU(0);
+
+   va_list marker;
+
+   va_start(marker, nParam);
+
+   // add 0xD8
+   invokeAPDU += (u1)0xD8;
+
+   // add port number
+   invokeAPDU += (u2)this->portNumber;
+
+   // add 0x6F
+   invokeAPDU += (u1)0x6F;
+
+   // add namespace Hivecode
+   invokeAPDU += this->nameSpaceHivecode;
+
+   // add type hivecode
+   invokeAPDU += this->typeHivecode;
+
+   // NOTE : va_arg(marker,type)
+   // As per ISO C++ if the pritives types
+   // char,short,byte are passed as argument to varidic method
+   // they are upcasted to int.
+   //
+   // On windows if you use va_arg(marker,u2), no warning will be issued
+   // and there will be no complain at run time, whereas
+   // On Linux (with g++) if you use va_arg(markey,u2), a warning will be issued
+   // saying that it is invalid to do this and run time will fail and it does fail
+   // with message "Segmentation fault".
+   //
+   // So va_arg for all int primitive types (char, short, byte and their unsigned values)
+   // should have s4 as the type.
+
+   // add method name
+   u2 methodID = (u2)va_arg(marker, s4);
+   invokeAPDU += methodID;
+
+   // add uri
+   u1Array uriArray(ComputeUTF8Length((lpCharPtr)this->uri->c_str()));
+   UTF8Encode((lpCharPtr)this->uri->c_str(), uriArray);
+   invokeAPDU += (u2)uriArray.GetLength();
+   invokeAPDU += uriArray;
+
+   u1Array invokeAPDU_data(0);
+
+   // process input arguments
+   for (s4 iParam = 0; iParam < nParam; iParam++) {
+      u1 type = (u1)va_arg(marker, s4);
+      ProcessInputArguments(type, &invokeAPDU_data, &marker);
+   }
+
+   if(ProcessInputStream != NULL){
+      u1Array invokeAPDU_data_Modified(0);
+      ProcessInputStream(invokeAPDU_data,invokeAPDU_data_Modified);
+      invokeAPDU += invokeAPDU_data_Modified;
+   }else{
+      invokeAPDU += invokeAPDU_data;
+   }
+
+   u1Array answer_o(0);
+
+   this->pcsc->BeginTransaction();
+
+   try {
+
+      if(invokeAPDU.GetLength() > (s4)APDU_TO_CARD_MAX_SIZE)
+      {
+         u4 offset = 0;
+         u4 size = invokeAPDU.GetLength() -1 - 2 - 1 - 4 - 2 - 2 - 2 -  uriArray.GetLength();
+
+         u1 first = TRUE;
+
+         u4 dataToSendLength = invokeAPDU.GetLength();
+         u4 invokeApduStartOffset = 0;
+
+         while(dataToSendLength > 0){
+
+            u4 encodedSize = size;
+            u4 encodedOffset = (u4)offset;
+
+            u4 subCommandMaxAllowed = APDU_TO_CARD_MAX_SIZE -1 - 2 - 8;
+
+            u4 length = dataToSendLength > subCommandMaxAllowed ? subCommandMaxAllowed : dataToSendLength;
+
+            u1Array subApdu(0);
+
+            if(first == TRUE){
+               u4 usefulDataLength = length -1 - 2 -1 -4 -2 -2 -2 - uriArray.GetLength();
+
+               subApdu += (u1)0xD8;
+               subApdu += (u2)0xFFFF;
+               subApdu += encodedSize;
+               subApdu += usefulDataLength;
+
+               if ((u8)(invokeApduStartOffset + length) > (u8)invokeAPDU.GetLength()) {
+                  throw ArgumentOutOfRangeException((lpCharPtr)"");
+               }
+
+               for(u4 j = invokeApduStartOffset; j < (invokeApduStartOffset + length); j++) {
+                  subApdu += invokeAPDU.GetBuffer()[j];
+               }
+
+               first = FALSE;
+               offset += usefulDataLength;
+
+            }else{
+
+               subApdu += (u1)0xD8;
+               subApdu += (u2)0xFFFF;
+               subApdu += encodedOffset;
+               subApdu += length;
+
+               if ((u8)(invokeApduStartOffset + length) > (u8)invokeAPDU.GetLength()) {
+                  throw ArgumentOutOfRangeException((lpCharPtr)"");
+               }
+
+               for(u4 j = invokeApduStartOffset; j < (invokeApduStartOffset + length); j++) {
+                  subApdu += invokeAPDU.GetBuffer()[j];
+               }
+
+               offset += length;
+            }
+
+            size = 0;
+            invokeApduStartOffset = invokeApduStartOffset + length;
+            dataToSendLength = dataToSendLength - length;
+
+            u1Array apduToSend(5);
+
+            apduToSend.GetBuffer()[0] = 0x80;
+            apduToSend.GetBuffer()[1] = 0xC2;
+            apduToSend.GetBuffer()[2] = 0x00;
+            apduToSend.GetBuffer()[3] = 0x00;
+            apduToSend.GetBuffer()[4] = (u1)subApdu.GetLength();
+            apduToSend += subApdu;
+
+            this->pcsc->ExchangeData(apduToSend, answer_o);
+         }
+      }else{
+
+         // construct call
+         u1Array apdu(5);
+         apdu.GetBuffer()[0] = 0x80;
+         apdu.GetBuffer()[1] = 0xC2;
+         apdu.GetBuffer()[2] = 0x00;
+         apdu.GetBuffer()[3] = 0x00;
+         apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
+         apdu += invokeAPDU;
+
+         this->pcsc->ExchangeData(apdu, answer_o);
+      }
+   } catch (...) {
+      this->pcsc->EndTransaction();
+      throw;
+   }
+
+   this->pcsc->EndTransaction();
+
+   u1Array answer(0);
+
+   if ((ProcessOutputStream != NULL) && (answer_o.GetLength() > 0) && (answer_o.ReadU1At(0) == 0x01)){
+      u1Array answerI(0);
+      u1Array answerM(0);
+
+      for(u4 i = 1; i < answer_o.GetLength(); i++){
+         answerI += answer_o.GetBuffer()[i];
+      }
+
+      ProcessOutputStream(answerI, answerM);
+
+      answer += answer_o.GetBuffer()[0];
+
+      for(u4 i=0;i<answerM.GetLength();i++){
+         answer += answerM.GetBuffer()[i];
+      }
+
+   } else {
+      for(u4 i=0;i<answer_o.GetLength();i++)
+         answer += answer_o.GetBuffer()[i];
+   }
+
+   // analyze return type
+   u4 offset = ProcessReturnType((u1)va_arg(marker, s4), &answer, &marker);
+
+   va_end(marker);
+
+   // process byref types
+   va_start(marker, nParam);
+
+   // skip method name param
+   u2 methodID2 = (u2)va_arg(marker, s4);
+
+   if (methodID2 == methodID) {
+      for (s4 iParam = 0; iParam < nParam; iParam++) {
+         u1 type = (u1)va_arg(marker, s4);
+         ProcessOutputArguments(type, &answer, &offset, &marker);
+      }
+   }
+
+   va_end(marker);
+}
+
+void SmartCardMarshaller::SetInputStream(pCommunicationStream inStream){
+   this->ProcessInputStream = inStream;
+}
+
+void  SmartCardMarshaller::SetOutputStream(pCommunicationStream outStream){
+   this->ProcessOutputStream = outStream;
+}
+
+MARSHALLER_NS_END
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,77 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_h
+#define _include_marshaller_h
+
+#ifdef _XCL_
+#include "xcl_broker.h"
+#endif // _XCL_
+
+MARSHALLER_NS_BEGIN
+
+typedef void (*pCommunicationStream)(u1Array& st,u1Array& stM);
+
+class SMARTCARDMARSHALLER_DLLAPI SmartCardMarshaller
+{
+
+private:
+    u4            nameSpaceHivecode;
+    u2            typeHivecode;
+    u2            portNumber;
+    std::string*  uri;
+#ifndef _XCL_
+    PCSC*         pcsc;
+#else 	// _XCL_
+    XCLBroker*    pcsc;
+#endif 	// _XCL_
+
+    pCommunicationStream ProcessInputStream;
+    pCommunicationStream ProcessOutputStream;
+
+public:
+    // Existing PCSC connection
+    SmartCardMarshaller(SCARDHANDLE pcscCardHandle, u2 portNumber,M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode);
+
+    // PCSC compatible readers
+    SmartCardMarshaller(M_SAL_IN std::string* readerName, u2 portNumber,M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index);
+
+    // destructor
+    ~SmartCardMarshaller(void);
+
+    // Remoting marshalling method
+    void Invoke(s4 nParam, ...);
+
+    void UpdatePCSCCardHandle(SCARDHANDLE hCard);
+
+    void SetInputStream(pCommunicationStream inStream);
+    void SetOutputStream(pCommunicationStream outStream);
+
+    std::string* GetReaderName();
+    SCARDHANDLE GetCardHandle();
+    void DoTransact(bool flag);
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,167 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshallercfg_h
+#define _include_marshallercfg_h
+
+#ifdef SMARTCARDMARSHALLER_EXPORTS
+	#define SMARTCARDMARSHALLER_DLLAPI __declspec(dllexport)
+#else
+	#define SMARTCARDMARSHALLER_DLLAPI
+#endif
+
+#ifdef M_SAL_ANNOTATIONS
+#include <specstrings.h>
+#define M_SAL_IN		__in
+#define M_SAL_OUT		__out
+#define M_SAL_INOUT		__inout
+#else
+#define M_SAL_IN
+#define M_SAL_OUT
+#define M_SAL_INOUT
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef WIN32
+#include <inttypes.h>
+#endif
+
+// data types
+typedef unsigned char       u1;
+typedef unsigned short      u2;
+typedef unsigned int        u4;
+typedef char                s1;
+typedef short               s2;
+typedef int                 s4;
+
+#ifdef WIN32
+typedef unsigned __int64    u8;
+typedef __int64             s8;
+typedef LPSTR               lpCharPtr;
+typedef LPTSTR				lpTCharPtr;
+typedef LPBYTE				lpByte;
+typedef const lpByte        lpCByte;
+#else
+typedef uint64_t u8;
+typedef int64_t s8;
+typedef char*				 lpTCharPtr;
+typedef char*                lpCharPtr;
+typedef unsigned char*       lpByte;
+typedef const lpByte		 lpCByte;
+#endif
+
+// Marshaller argument type constants
+#define MARSHALLER_TYPE_IN_VOID				0
+#define MARSHALLER_TYPE_IN_BOOL				1
+#define MARSHALLER_TYPE_IN_S1				2
+#define MARSHALLER_TYPE_IN_U1				3
+#define MARSHALLER_TYPE_IN_CHAR				4
+#define MARSHALLER_TYPE_IN_S2				5
+#define MARSHALLER_TYPE_IN_U2				6
+#define MARSHALLER_TYPE_IN_S4				7
+#define MARSHALLER_TYPE_IN_U4				8
+#define MARSHALLER_TYPE_IN_S8				9
+#define MARSHALLER_TYPE_IN_U8				10
+#define MARSHALLER_TYPE_IN_STRING			11
+
+#define MARSHALLER_TYPE_IN_BOOLARRAY		21
+#define MARSHALLER_TYPE_IN_S1ARRAY			22
+#define MARSHALLER_TYPE_IN_U1ARRAY			23
+#define MARSHALLER_TYPE_IN_CHARARRAY		24
+#define MARSHALLER_TYPE_IN_S2ARRAY			25
+#define MARSHALLER_TYPE_IN_U2ARRAY			26
+#define MARSHALLER_TYPE_IN_S4ARRAY			27
+#define MARSHALLER_TYPE_IN_U4ARRAY			28
+#define MARSHALLER_TYPE_IN_S8ARRAY			29
+#define MARSHALLER_TYPE_IN_U8ARRAY			30
+#define MARSHALLER_TYPE_IN_STRINGARRAY		31
+
+#define MARSHALLER_TYPE_IN_MEMORYSTREAM     40
+
+#define MARSHALLER_TYPE_REF_BOOL			50
+#define MARSHALLER_TYPE_REF_S1				51
+#define MARSHALLER_TYPE_REF_U1				52
+#define MARSHALLER_TYPE_REF_CHAR			53
+#define MARSHALLER_TYPE_REF_S2				54
+#define MARSHALLER_TYPE_REF_U2				55
+#define MARSHALLER_TYPE_REF_S4				56
+#define MARSHALLER_TYPE_REF_U4				57
+#define MARSHALLER_TYPE_REF_S8				58
+#define MARSHALLER_TYPE_REF_U8				59
+#define MARSHALLER_TYPE_REF_STRING			60
+
+#define MARSHALLER_TYPE_REF_BOOLARRAY		61
+#define MARSHALLER_TYPE_REF_S1ARRAY			62
+#define MARSHALLER_TYPE_REF_U1ARRAY			63
+#define MARSHALLER_TYPE_REF_CHARARRAY		64
+#define MARSHALLER_TYPE_REF_S2ARRAY			65
+#define MARSHALLER_TYPE_REF_U2ARRAY			66
+#define MARSHALLER_TYPE_REF_S4ARRAY			67
+#define MARSHALLER_TYPE_REF_U4ARRAY			68
+#define MARSHALLER_TYPE_REF_S8ARRAY			69
+#define MARSHALLER_TYPE_REF_U8ARRAY			70
+#define MARSHALLER_TYPE_REF_STRINGARRAY		71
+
+// Marshaller return type arguments
+#define MARSHALLER_TYPE_RET_VOID			MARSHALLER_TYPE_IN_VOID
+#define MARSHALLER_TYPE_RET_BOOL			MARSHALLER_TYPE_IN_BOOL
+#define MARSHALLER_TYPE_RET_S1				MARSHALLER_TYPE_IN_S1
+#define MARSHALLER_TYPE_RET_U1				MARSHALLER_TYPE_IN_U1
+#define MARSHALLER_TYPE_RET_CHAR			MARSHALLER_TYPE_IN_CHAR
+#define MARSHALLER_TYPE_RET_S2				MARSHALLER_TYPE_IN_S2
+#define MARSHALLER_TYPE_RET_U2				MARSHALLER_TYPE_IN_U2
+#define MARSHALLER_TYPE_RET_S4				MARSHALLER_TYPE_IN_S4
+#define MARSHALLER_TYPE_RET_U4				MARSHALLER_TYPE_IN_U4
+#define MARSHALLER_TYPE_RET_S8				MARSHALLER_TYPE_IN_S8
+#define MARSHALLER_TYPE_RET_U8				MARSHALLER_TYPE_IN_U8
+#define MARSHALLER_TYPE_RET_STRING			MARSHALLER_TYPE_IN_STRING
+
+#define MARSHALLER_TYPE_RET_BOOLARRAY		MARSHALLER_TYPE_IN_BOOLARRAY
+#define MARSHALLER_TYPE_RET_S1ARRAY			MARSHALLER_TYPE_IN_S1ARRAY
+#define MARSHALLER_TYPE_RET_U1ARRAY			MARSHALLER_TYPE_IN_U1ARRAY
+#define MARSHALLER_TYPE_RET_CHARARRAY		MARSHALLER_TYPE_IN_CHARARRAY
+#define MARSHALLER_TYPE_RET_S2ARRAY			MARSHALLER_TYPE_IN_S2ARRAY
+#define MARSHALLER_TYPE_RET_U2ARRAY			MARSHALLER_TYPE_IN_U2ARRAY
+#define MARSHALLER_TYPE_RET_S4ARRAY			MARSHALLER_TYPE_IN_S4ARRAY
+#define MARSHALLER_TYPE_RET_U4ARRAY			MARSHALLER_TYPE_IN_U4ARRAY
+#define MARSHALLER_TYPE_RET_S8ARRAY			MARSHALLER_TYPE_IN_S8ARRAY
+#define MARSHALLER_TYPE_RET_U8ARRAY			MARSHALLER_TYPE_IN_U8ARRAY
+#define MARSHALLER_TYPE_RET_STRINGARRAY		MARSHALLER_TYPE_IN_STRINGARRAY
+
+#define MARSHALLER_TYPE_RET_MEMORYSTREAM    MARSHALLER_TYPE_IN_MEMORYSTREAM
+
+// namespace for the module
+// in case compiler does not support namespace, the defines can be undefined
+#define MARSHALLER_NS_BEGIN namespace Marshaller {
+#define MARSHALLER_NS_END }
+
+#endif
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,557 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable : 4201)
+#else
+#define DBG_UNREFERENCED_LOCAL_VARIABLE(a)
+#endif
+
+//#ifdef _MAC_OS_X
+#ifdef __APPLE__
+#include <wintypes.h>
+#include <pcsclite.h>
+#endif
+
+#ifndef WIN32
+#include <strings.h>
+#endif
+#include <string.h>
+#include <winscard.h>
+#include <stdexcept>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#include "PCSC.h"
+#include "Except.h"
+
+
+#ifdef __sun
+typedef LPSTR LPTSTR;
+#endif
+
+// JCD
+#include "log.h"
+
+
+
+MARSHALLER_NS_BEGIN
+
+extern u4 CheckForException(u1Array answer, u4 nameSpace, u2 type);
+extern u4 ComReadU4At(u1Array &array, u4 pos);
+
+#define SUPPORT_BETA_VERSION
+
+const u1 isNetCardAPDU[] = {0x80,0xC2,0x00,0x00,0x1C,0xD8,0x00,0x01,0x6F,0x00,0xF5,0xEF,0xBF,0xB1,0x8C,0xDD,0xC2,0x00,0x0E,0x43,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x4D,0x61,0x6E,0x61,0x67,0x65,0x72};
+
+#define APDU_TO_CARD_MAX_SIZE                                                       0xFF
+#define CARDMANAGER_SERVICE_PORT                                                    1
+#define CARDMANAGER_SERVICE_NAME                                                    "ContentManager"
+
+#define HIVECODE_NAMESPACE_SMARTCARD                                                0x00F5EFBF
+#define HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER                                      0xB18C
+#define HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT                  0x7616
+#define HIVECODE_NAMESPACE_SYSTEM                                                   0x00D25D1C
+#define HIVECODE_TYPE_SYSTEM_INT32                                                  0x61C0
+
+
+// *******************
+// PCSC class
+// *******************
+PCSC::PCSC(M_SAL_IN std::string* readerName)
+{
+   DWORD activeProtocol;
+   LONG lReturn;
+
+   this->hContext      = 0;
+   this->hCard	        = 0;
+
+   lReturn = SCardEstablishContext(0, NULL, NULL, &this->hContext);
+   if(lReturn != SCARD_S_SUCCESS) {
+      throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
+   }
+
+   lReturn = SCardConnect(this->hContext, (LPTSTR)readerName->c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &this->hCard, &activeProtocol);
+   if (lReturn != SCARD_S_SUCCESS) {
+      throw RemotingException((lpCharPtr)"PCSC: SCardConnect error",lReturn);
+   }
+
+   this->readerName = new std::string(readerName->c_str());
+}
+
+PCSC::PCSC(M_SAL_IN std::string* inputReaderName, u2* portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index)
+{
+   Log::begin( "PCSC::PCSC" );
+
+   std::string selfDiscover("selfdiscover");
+   std::string* identifiedReaderName;
+   LPTSTR pReaderList = NULL;
+   LONG lReturn;
+
+   if (inputReaderName == NULL) {
+      inputReaderName = &selfDiscover;
+   }
+
+   identifiedReaderName = NULL;
+   this->hContext    = 0;
+   this->hCard       = 0;
+
+   lReturn = SCardEstablishContext(0, NULL, NULL, &this->hContext);
+   Log::log( "PCSC::PCSC - SCardEstablishContext <%#02x>", lReturn );
+   if(lReturn != SCARD_S_SUCCESS)
+   {
+      Log::log( "PCSC::PCSC - ## ERROR ## SCardEstablishContext <%#02x>", lReturn );
+      throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
+   }
+
+   // self-discovery mechanism
+#ifdef WIN32
+   if (_stricmp("selfdiscover", inputReaderName->c_str()) == 0) {
+#else
+   if (strncasecmp("selfdiscover", inputReaderName->c_str(),inputReaderName->length()) == 0) {
+#endif
+      // In Windows SCARD_AUTOALLOCATE (-1) as a value of readerListChatLength
+      // would signal the SCardListReaders to determine the size of reader string
+      // This is not available in Linux so we call the SCardListReaders twice. First
+      // to get the length and then the reader names.
+#ifdef WIN32
+      DWORD readerListCharLength = SCARD_AUTOALLOCATE;
+      lReturn = SCardListReaders(this->hContext, NULL, (LPTSTR)&pReaderList, &readerListCharLength);
+      Log::log( "PCSC::PCSC - SCardListReaders <%#02x>", lReturn );
+
+#else
+      DWORD readerListCharLength = 0;
+
+      lReturn = SCardListReaders(this->hContext,NULL,NULL,&readerListCharLength);
+      if(lReturn != SCARD_S_SUCCESS)
+         throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);
+
+      pReaderList = (lpCharPtr)malloc(sizeof(char)*readerListCharLength);
+      lReturn = SCardListReaders(this->hContext, NULL,pReaderList, &readerListCharLength);
+#endif
+
+
+      if(lReturn != SCARD_S_SUCCESS)
+      {
+         Log::log( "PCSC::PCSC - ## ERROR ## SCardListReaders <%#02x>", lReturn );
+         throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);
+      }
+      else
+      {
+         u4 count = 0;
+         u1 foundReader = FALSE;
+         SCARDHANDLE finalCardHandle = 0;
+         try
+         {
+            lpTCharPtr pReader = pReaderList;
+            while ('\0' != *pReader )
+            {
+               size_t readerNameLen = strlen((const char*)pReader);
+               SCARD_READERSTATE readerStates[1];
+               readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
+               readerStates[0].szReader = pReader;
+               if (SCardGetStatusChange(this->hContext, 0, readerStates, 1) == SCARD_S_SUCCESS)
+               {
+                  if ((readerStates[0].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+                  {
+                     // we found a card in this reader
+                     if (identifiedReaderName != NULL)
+                     {
+                        delete identifiedReaderName;
+                        identifiedReaderName = NULL;
+                     }
+
+                     identifiedReaderName = new std::string((lpCharPtr)pReader);
+                     DWORD activeProtocol;
+
+                     Log::log( "PCSC::PCSC SCardConnect..." );
+                     lReturn = SCardConnect(this->hContext, (LPTSTR)identifiedReaderName->c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &this->hCard, &activeProtocol);
+                     Log::log( "PCSC::PCSC - SCardConnect <%#02x>", lReturn );
+
+                     if (lReturn == SCARD_S_SUCCESS)
+                     {
+                        // try to identify if we're dealing with a .NetCard
+                        u1 answerData[258];
+                        DWORD answerLen = 258;
+
+                        Log::log( "PCSC::PCSC SCardTransmit..." );
+                        lReturn = SCardTransmit(hCard, SCARD_PCI_T0, isNetCardAPDU, sizeof(isNetCardAPDU), NULL, (LPBYTE)answerData, &answerLen);
+                        Log::log( "PCSC::PCSC - SCardTransmit <%#02x>", lReturn );
+
+                        if (lReturn == SCARD_S_SUCCESS)
+                        {
+                           u1 rethrowException = FALSE;
+                           try {
+                              if (answerData[answerLen - 2] == 0x61)
+                              {
+                                 if (answerData[answerLen - 1] > 10)
+                                 {
+                                    u1Array invokeAPDU(0);
+                                    invokeAPDU += (u1)0xD8;
+                                    invokeAPDU += (u2)CARDMANAGER_SERVICE_PORT;
+                                    invokeAPDU += (u1)0x6F;
+                                    invokeAPDU += (u4)HIVECODE_NAMESPACE_SMARTCARD;
+                                    invokeAPDU += (u2)HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
+                                    invokeAPDU += (u2)HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT;
+                                    std::string* cmServiceUri = new std::string(CARDMANAGER_SERVICE_NAME);
+                                    invokeAPDU.Append(cmServiceUri);
+                                    delete cmServiceUri;
+                                    invokeAPDU += (u4)nameSpaceHivecode;
+                                    invokeAPDU += (u2)typeHivecode;
+                                    invokeAPDU.Append(uri);
+
+                                    // construct call
+                                    if(invokeAPDU.GetLength() <= (s4)APDU_TO_CARD_MAX_SIZE) {
+                                       u1Array apdu(5);
+                                       apdu.GetBuffer()[0] = 0x80;
+                                       apdu.GetBuffer()[1] = 0xC2;
+                                       apdu.GetBuffer()[2] = 0x00;
+                                       apdu.GetBuffer()[3] = 0x00;
+                                       apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
+                                       apdu += invokeAPDU;
+
+                                       u1Array answer(0);
+
+                                       Log::log( "PCSC::PCSC - ExchangeData..." );
+                                       this->ExchangeData(apdu, answer);
+                                       Log::log( "PCSC::PCSC - ExchangeData ok" );
+
+                                       Log::log( "PCSC::PCSC - CheckForException..." );
+                                       u4 protocolOffset = CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
+                                       Log::log( "PCSC::PCSC - CheckForException ok" );
+
+                                       u4 discoveredPortNumber = ComReadU4At(answer, protocolOffset);
+                                       if ((*portNumber == 0) || (discoveredPortNumber == *portNumber))
+                                       {
+                                          *portNumber = (u2)discoveredPortNumber;
+
+                                          if (foundReader == TRUE)
+                                          {
+                                             if (index == 0)
+                                             {
+                                                // this is the second reader/card/app that matches - we error at this point
+                                                rethrowException = TRUE;
+                                                char errorMessage[255];
+                                                strcpy(errorMessage, "At least 2 cards posses \"");
+                                                strcat(errorMessage, uri->c_str());
+                                                strcat(errorMessage, "\" service\r\nRemove conflicting cards from your system");
+
+                                                Log::error( "PCSC::PCSC", errorMessage );
+
+                                                throw RemotingException(errorMessage);
+                                             }
+                                          }
+
+                                          foundReader = TRUE;
+                                          finalCardHandle = this->hCard;
+
+                                          // Advance to the next value.
+                                          count++;
+
+                                          if (count == index)
+                                          {
+                                             // we enumerate one by one the valid readers - so stop here
+                                             break;
+                                          }
+
+                                          pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+                                          continue;
+                                       }
+                                    }
+                                 }
+                              }
+                           }
+                           catch (...)
+                           {
+                              if (rethrowException == TRUE)
+                              {
+                                 throw;
+                              }
+                              else
+                              {
+                                 // swallow exception
+                              }
+                           }
+
+                           SCardDisconnect(this->hCard, SCARD_LEAVE_CARD);
+                           this->hCard = 0;
+                        }
+                        // this is not a .NetCard, or the service was not found - let's try another reader/card
+                        else
+                        {
+                           Log::error( "PCSC::PCSC", "SCardTransmit failed" );
+                        }
+                     }
+                     else
+                     {
+                        Log::error( "PCSC::PCSC", "SCardConnect failed" );
+                     }
+                  }
+                  else
+                  {
+                     Log::error( "PCSC::PCSC", "SCARD_STATE_PRESENT not present" );
+                  }
+               }
+               else
+               {
+                  Log::error( "PCSC::PCSC", "SCardGetStatusChange != SCARD_S_SUCCESS" );
+               }
+
+               // Advance to the next value.
+               pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+            }
+         } catch (...) {
+            if (identifiedReaderName != NULL) {
+               delete identifiedReaderName;
+            }
+
+#ifdef WIN32
+            lReturn = SCardFreeMemory(this->hContext, pReaderList);
+            if(lReturn != SCARD_S_SUCCESS) {
+               throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
+            }
+#else
+            if(pReaderList != NULL)
+               free(pReaderList);
+#endif
+            throw;
+         }
+
+         // have we found anything ?
+         if (foundReader == FALSE) {
+            if (identifiedReaderName != NULL) {
+               delete identifiedReaderName;
+            }
+
+#ifdef WIN32
+            lReturn = SCardFreeMemory(this->hContext, pReaderList);
+            if(lReturn != SCARD_S_SUCCESS) {
+               throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
+            }
+#else
+            if(pReaderList != NULL)
+               free(pReaderList);
+#endif
+
+            throw RemotingException((lpCharPtr)"Could not find any Cryptoflex .NET smart card",SCARD_E_NO_SMARTCARD);
+         }
+
+         this->hCard = finalCardHandle;
+      }
+
+      this->readerName = new std::string(identifiedReaderName->c_str());
+
+      delete identifiedReaderName;
+
+   } else {
+      this->readerName = new std::string(inputReaderName->c_str());
+   }
+
+   Log::end( "PCSC::PCSC" );
+}
+
+PCSC::PCSC(SCARDHANDLE cardHandle)
+{
+   this->hContext   = 0;
+   this->hCard		 = cardHandle;
+   this->readerName = NULL;
+   this->fDoTransact = true;
+}
+
+std::string* PCSC::GetReaderName(void)
+{
+   return this->readerName;
+}
+
+void PCSC::BeginTransaction(void)
+{
+   if(fDoTransact) // TODO: TEST RETURN CODE!!
+      SCardBeginTransaction(this->hCard);
+}
+
+void PCSC::EndTransaction(void)
+{
+   if(fDoTransact) // TODO: TEST RETURN CODE!!
+      SCardEndTransaction(this->hCard, SCARD_LEAVE_CARD);
+}
+
+SCARDHANDLE PCSC::GetCardHandle(void)
+{
+   return this->hCard;
+}
+
+void PCSC::SetCardHandle(SCARDHANDLE hCard)
+{
+   this->hCard = hCard;
+}
+
+void PCSC::DoTransact(bool flag)
+{
+   this->fDoTransact = flag;
+}
+
+void PCSC::ExchangeData(u1Array &dataIn, u1Array &dataout)
+{
+   u1 answerData[258];
+
+   // check validity of handle
+   if (this->hCard == 0) {
+      throw RemotingException((lpCharPtr)"PCSC: Invalid card handle", SCARD_E_INVALID_HANDLE);
+   }
+
+#ifdef __DEBUG_APDU__
+   FILE *pFile = fopen("C:\\AxaltoProtocolAnalyzer.txt","a");
+#endif
+
+   try {
+
+      BeginTransaction();
+
+      DWORD answerLen = sizeof(answerData);
+
+#ifdef __DEBUG_APDU__
+      fprintf(pFile, "APDU DataIn Buffer\n");
+      for(int i=0; i < (s4)dataIn.GetLength(); i++) {
+         fprintf(pFile, "%02x",dataIn.GetBuffer()[i]);
+      }
+      fprintf(pFile, "\n");
+#endif
+
+      s4 lReturn = SCardTransmit(hCard, SCARD_PCI_T0, dataIn.GetBuffer(), dataIn.GetLength(), NULL, (lpByte)answerData, &answerLen);
+      if (lReturn != SCARD_S_SUCCESS) {
+         throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error",lReturn);
+      }
+
+      if (answerLen < 2) {
+         throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
+      }
+
+      if (answerLen > 2) {
+         u1Array temp(answerLen - 2);
+         temp.SetBuffer(answerData);
+         dataout += temp;
+#ifdef __DEBUG_APDU__
+         fprintf(pFile, "APDU DataOut Buffer\n");
+         for(int i=0; i< (s4)temp.GetLength(); i++) {
+            fprintf(pFile, "%02x",temp.GetBuffer()[i]);
+         }
+         fprintf(pFile, "\n");
+#endif
+      }
+
+      u1 sw1 = answerData[answerLen - 2];
+      u1 sw2 = answerData[answerLen - 1];
+
+#ifdef __DEBUG_APDU__
+      fprintf(pFile, "APDU Status Buffer\n");
+      fprintf(pFile, "%02x%02x",sw1,sw2);
+      fprintf(pFile, "\n");
+#endif
+
+      while ((sw1 == 0x61) || (sw1 == 0x9F))
+      {
+         u1 GetResponse[5];
+         if (sw1 == 0x9F) {
+            GetResponse[0] = 0xA0;
+         } else {
+            GetResponse[0] = 0x00;
+         }
+         GetResponse[1] = 0xC0;
+         GetResponse[2] = 0x00;
+         GetResponse[3] = 0x00;
+         GetResponse[4] = sw2;
+         answerLen = 258;
+
+#ifdef __DEBUG_APDU__
+         fprintf(pFile, "APDU DataIn Buffer\n");
+         for(int i=0; i<5; i++) {
+            fprintf(pFile, "%02x",GetResponse[i]);
+         }
+         fprintf(pFile, "\n");
+#endif
+
+         lReturn = SCardTransmit(hCard, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen);
+         if (lReturn != SCARD_S_SUCCESS) {
+            throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error",lReturn);
+         }
+
+         if (answerLen < 2) {
+            throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
+         }
+
+         if (answerLen > 2) {
+            u1Array temp(answerLen - 2);
+            temp.SetBuffer(answerData);
+            dataout += temp;
+#ifdef __DEBUG_APDU__
+            fprintf(pFile, "APDU DataOut Buffer\n");
+            for(int i=0; i< (s4)temp.GetLength(); i++) {
+               fprintf(pFile, "%02x",temp.GetBuffer()[i]);
+            }
+            fprintf(pFile, "\n");
+#endif
+         }
+         sw1 = answerData[answerLen - 2];
+         sw2 = answerData[answerLen - 1];
+
+#ifdef __DEBUG_APDU__
+         fprintf(pFile, "APDU Status Buffer\n");
+         fprintf(pFile, "%02x%02x",sw1,sw2);
+         fprintf(pFile, "\n");
+#endif
+      }
+   } catch (...) {
+#ifdef __DEBUG_APDU__
+      fflush(pFile);
+      fclose(pFile);
+#endif
+      EndTransaction();
+      throw;
+   }
+
+#ifdef __DEBUG_APDU__
+   fflush(pFile);
+   fclose(pFile);
+#endif
+
+   EndTransaction();
+}
+
+PCSC::~PCSC(void)
+{
+   // we cleanup the various context and card handle only if we allocated it (depends of constructor)
+   if (hContext != 0) {
+      if (hCard != 0) {
+         SCardDisconnect(hCard, SCARD_LEAVE_CARD);
+         hCard = 0;
+      }
+      SCardReleaseContext(hContext);
+      hContext = 0;
+   }
+
+   if (this->readerName != NULL) {
+      delete this->readerName;
+      this->readerName = NULL;
+   }
+}
+
+MARSHALLER_NS_END
+

Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h	                        (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h	2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+/*
+ *  PKCS#11 library for .Net smart cards
+ *  Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _include_marshaller_pcsc_h
+#define _include_marshaller_pcsc_h
+
+MARSHALLER_NS_BEGIN
+
+class PCSC
+{
+
+private:
+    SCARDCONTEXT hContext;
+    SCARDHANDLE  hCard;
+    std::string*    readerName;
+    bool fDoTransact;
+
+public:
+    PCSC(SCARDHANDLE cardHandle);
+	PCSC(M_SAL_IN std::string* readerName);
+	PCSC(M_SAL_IN std::string* readerName, u2* portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index);
+    SCARDHANDLE GetCardHandle(void);
+    void SetCardHandle(SCARDHANDLE hCard);
+    void DoTransact(bool flag);
+    std::string* GetReaderName(void);
+    void BeginTransaction(void);
+    void EndTransaction(void);
+    void ExchangeData(u1Array &dataIn, u1Array &dataout);
+    ~PCSC(void);
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/smartcardservices-changes/attachments/20091217/80e29782/attachment-0001.html>


More information about the SmartcardServices-Changes mailing list