gnome-keyring r1175 - in trunk: . daemon/pk daemon/pkcs11 gp11 gp11/tests tests



Author: nnielsen
Date: Mon Jul 14 19:54:11 2008
New Revision: 1175
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1175&view=rev

Log:
        * daemon/pk/gkr-pk-cert.c:
        * daemon/pk/gkr-pk-import.c:
        * daemon/pk/gkr-pk-object.c:
        * daemon/pk/gkr-pk-privkey.c:
        * daemon/pk/gkr-pk-pubkey.c:
        * daemon/pkcs11/gkr-pkcs11-daemon-session.c:
        * daemon/pkcs11/gkr-pkcs11-dsa.c:
        * daemon/pkcs11/gkr-pkcs11-rsa.c: Only use CKR_GENERAL_ERROR
        when it's really quite dire.
        
        * gp11/gp11.h: (added)
        * gp11/gp11.pc.in: (added)
        * gp11/gp11-attributes.c: (added)
        * gp11/gp11-call.c: (added)
        * gp11/gp11-misc.c: (added)
        * gp11/gp11-module.c: (added)
        * gp11/gp11-object.c: (added)
        * gp11/gp11-private.h: (added)
        * gp11/gp11-session.c: (added)
        * gp11/gp11-slot.c: (added)
        * gp11/Makefile.am: (added)
        * gp11/pkcs11.h: (added)
        * gp11/tests/gp11-test.h: (added)
        * gp11/tests/gp11-test-module.c: (added)
        * gp11/tests/Makefile.am: (added)
        * gp11/tests/unit-test-gp11-attributes.c: (added)
        * gp11/tests/unit-test-gp11-module.c: (added)
        * gp11/tests/unit-test-gp11-object.c: (added)
        * gp11/tests/unit-test-gp11-session.c: (added)
        * gp11/tests/unit-test-gp11-slot.c: (added)
        * tests/check.make: (added)
        * tests/check-helpers.c: (added)
        * tests/check-helpers.h: (added)
        * tests/prep-check.sh: (added)
        * configure.in:
        * Makefile.am: Added new GP11 library



Added:
   trunk/gp11/   (props changed)
   trunk/gp11/Makefile.am
   trunk/gp11/gp11-attributes.c
   trunk/gp11/gp11-call.c
   trunk/gp11/gp11-misc.c
   trunk/gp11/gp11-module.c
   trunk/gp11/gp11-object.c
   trunk/gp11/gp11-private.h
   trunk/gp11/gp11-session.c
   trunk/gp11/gp11-slot.c
   trunk/gp11/gp11.h
   trunk/gp11/gp11.pc.in
   trunk/gp11/pkcs11.h
   trunk/gp11/tests/   (props changed)
   trunk/gp11/tests/Makefile.am
   trunk/gp11/tests/gp11-test-module.c
   trunk/gp11/tests/gp11-test.h
   trunk/gp11/tests/unit-test-gp11-attributes.c
   trunk/gp11/tests/unit-test-gp11-module.c
   trunk/gp11/tests/unit-test-gp11-object.c
   trunk/gp11/tests/unit-test-gp11-session.c
   trunk/gp11/tests/unit-test-gp11-slot.c
   trunk/tests/check-helpers.c
   trunk/tests/check-helpers.h
   trunk/tests/check.make
   trunk/tests/prep-check.sh   (contents, props changed)
Modified:
   trunk/ChangeLog
   trunk/HACKING
   trunk/Makefile.am
   trunk/configure.in
   trunk/daemon/pk/gkr-pk-cert.c
   trunk/daemon/pk/gkr-pk-import.c
   trunk/daemon/pk/gkr-pk-object.c
   trunk/daemon/pk/gkr-pk-privkey.c
   trunk/daemon/pk/gkr-pk-pubkey.c
   trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c
   trunk/daemon/pkcs11/gkr-pkcs11-dsa.c
   trunk/daemon/pkcs11/gkr-pkcs11-rsa.c

Modified: trunk/HACKING
==============================================================================
--- trunk/HACKING	(original)
+++ trunk/HACKING	Mon Jul 14 19:54:11 2008
@@ -10,27 +10,30 @@
 daemon 
    The main daemon startup code and gnome-keyring password protocol operations. 
    
-keyrings
+daemon/keyrings
    Code that manages the user's password keyrings 
+
+daemon/pk 
+   General public key / certificate code, management of objects.
+
+daemon/pkcs11
+   The PKCS#11 part of the daemon.
+
+daemon/pkix
+   Nitty gritty handling of various PKCS#?? standards, parsing, ASN.1 stuff.
+
+daemon/ui 
+   Prompting the user, asking for passwords. 
    
 library
    The gnome-keyring library for accessing passwords and secrets. 
 
-pk 
-   General public key / certificate code, management of objects.
-
 pkcs11
    The PKCS#11 module, provider and headers.
-
-pkix
-   Nitty gritty handling of various PKCS#?? standards, parsing, ASN.1 stuff.
       
 tests  
    Test tools and unit tests.
    
-ui 
-   Prompting the user, asking for passwords. 
-   
 
 --------------------------------------------------------------------------------
                     USING 'LOCATIONS' INSTEAD OF FILE PATHS

Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am	(original)
+++ trunk/Makefile.am	Mon Jul 14 19:54:11 2008
@@ -12,6 +12,7 @@
 
 SUBDIRS = \
 	. \
+	gp11 \
 	common \
 	library \
 	pkcs11 \

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Mon Jul 14 19:54:11 2008
@@ -3,6 +3,15 @@
 AM_INIT_AUTOMAKE(gnome-keyring, 2.22.3)
 AM_CONFIG_HEADER(config.h)
 	
+dnl ****************************************************************************
+dnl GP11 library libtool versioning
+
+GP11_MAJOR=0		# Increment for major version number, breaks old apps.
+GP11_REVISION=0		# Increment for internal changes, nothing affected.
+GP11_AGE=0		# Increment for interface that doesn't break anything
+
+dnl ****************************************************************************
+
 AM_SANITY_CHECK
 AM_MAINTAINER_MODE
 
@@ -44,6 +53,10 @@
 AC_SUBST(GOBJECT_CFLAGS)
 AC_SUBST(GOBJECT_LIBS)
 
+PKG_CHECK_MODULES(GIO, glib-2.0 >= 2.8.0 gio-2.0)
+AC_SUBST(GIO_CFLAGS)
+AC_SUBST(GIO_LIBS)
+
 PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6.0)
 AC_SUBST(GTK_CFLAGS)
 AC_SUBST(GTK_LIBS)
@@ -80,24 +93,6 @@
 fi
 
 # --------------------------------------------------------------------
-# Tests and Unit Tests
-
-AC_ARG_ENABLE(tests, 
-	    AC_HELP_STRING([--enable-tests],
-	    [Build test tools and unit tests]))
-
-if test "$enable_tests" = "yes"; then
-  echo "building tests and unit tests"
-  AC_DEFINE_UNQUOTED(WITH_TESTS, 1, [Build with unit test support])
-  tests_status="yes"
-else 
-  echo "not building tests and unit tests"
-  tests_status="no"
-fi
-
-AM_CONDITIONAL(WITH_TESTS, test "$enable_tests" == "yes")
-
-# --------------------------------------------------------------------
 # Check for socklen_t
 # 
 
@@ -452,6 +447,47 @@
 	AC_MSG_RESULT(no)
 fi
 
+# --------------------------------------------------------------------
+# Tests and Unit Tests
+
+AC_ARG_ENABLE(tests, 
+	    AC_HELP_STRING([--enable-tests],
+	    [Build test tools and unit tests]))
+
+if test "$enable_tests" == "yes"; then
+	PKG_CHECK_MODULES(CHECK, check >= 0.9, [have_check=yes], [have_check=no])
+	if test "$have_check" == "yes"; then
+		echo "building tests and unit tests"
+  		AC_DEFINE_UNQUOTED(WITH_TESTS, 1, [Build with unit test support])
+  		tests_status="yes"
+		enable_tests="yes"
+	else 
+		echo "The 'check' libraries are missing, cannot build tests"
+		tests_status="missing"
+		enable_tests="no"
+	fi
+else
+	echo "not building tests and unit tests"
+  	tests_status="no"
+fi
+
+AM_CONDITIONAL(WITH_TESTS, test "$enable_tests" == "yes")
+
+AC_ARG_ENABLE(coverage,
+		AC_HELP_STRING([--enable-coverage],
+			[Build coverage testing into gnome-keyring]))
+			
+if test "$enable_coverage" == "yes"; then
+	CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
+	LDFLAGS="$LDFLAGS -fprofile-arcs -ftest-coverage"
+fi
+
+# ----------------------------------------------------------------------
+
+GP11_LT_RELEASE=$GP11_MAJOR:$GP11_REVISION:$GP11_AGE
+AC_SUBST(GP11_LT_RELEASE)
+AC_SUBST(GP11_MAJOR)
+
 AC_SUBST(DAEMON_CFLAGS)
 AC_SUBST(DAEMON_LIBS)
 
@@ -474,6 +510,9 @@
 daemon/ssh/Makefile
 daemon/ssh/tests/Makefile
 daemon/ui/Makefile
+gp11/gp11.pc
+gp11/Makefile
+gp11/tests/Makefile
 library/Makefile
 library/tests/Makefile
 pam/Makefile
@@ -486,6 +525,9 @@
 library/gnome-keyring-1-uninstalled.pc
 ])
 
+# 
+# gp11/tests/module/Makefile
+
 # ------------------------------------------------------------------------------
 # Summary
 # 

Modified: trunk/daemon/pk/gkr-pk-cert.c
==============================================================================
--- trunk/daemon/pk/gkr-pk-cert.c	(original)
+++ trunk/daemon/pk/gkr-pk-cert.c	Mon Jul 14 19:54:11 2008
@@ -130,7 +130,7 @@
 		           g_quark_to_string (obj->location),
 		           err && err->message ? err->message : "");
 		g_error_free (err);
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 	}
 
 	/* This can happen if the user cancels out of a dialog */
@@ -474,7 +474,7 @@
 			res = gkr_pkix_der_read_basic_constraints (data, n_data, &is_ca, NULL);
 			g_free (data);
 			if (res != GKR_PKIX_SUCCESS)
-				return CKR_GENERAL_ERROR;
+				return CKR_FUNCTION_FAILED;
 			if (is_ca)
 				value = 2; /* authority */
 		}
@@ -505,7 +505,7 @@
 			return ret;
 		keyid = gkr_pk_cert_get_keyid (cert);
 		if (!keyid) 
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		data = (CK_VOID_PTR)gkr_id_get_raw (keyid, &n_data);
 		gkr_pk_attribute_set_data (attr, data, n_data);
 		return CKR_OK;
@@ -517,7 +517,7 @@
 		cdata = gkr_pkix_asn1_read_element (cert->data->asn1, cert->data->raw, cert->data->n_raw, 
 		                                    "tbsCertificate.subject", &n_data);
 		if (!cdata)
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		gkr_pk_attribute_set_data (attr, cdata, n_data);
 		return CKR_OK;
 		
@@ -527,7 +527,7 @@
 		cdata = gkr_pkix_asn1_read_element (cert->data->asn1, cert->data->raw, cert->data->n_raw, 
 		                                    "tbsCertificate.issuer", &n_data);
 		if (!cdata)
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		gkr_pk_attribute_set_data (attr, cdata, n_data);
 		return CKR_OK;
 		
@@ -536,7 +536,7 @@
 			return ret;
 		data = gkr_pkix_asn1_read_value (cert->data->asn1, "tbsCertificate.serialNumber", &n_data, NULL);
 		if (!data)
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		gkr_pk_attribute_set_data (attr, data, n_data);
 		g_free (data);
 		return CKR_OK;
@@ -569,7 +569,7 @@
 		                                       "tbsCertificate.validity.notBefore" : 
 		                                       "tbsCertificate.validity.notAfter",
 		                              &time))
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		gkr_pk_attribute_set_date (attr, time);
 		return CKR_OK;
 	

Modified: trunk/daemon/pk/gkr-pk-import.c
==============================================================================
--- trunk/daemon/pk/gkr-pk-import.c	(original)
+++ trunk/daemon/pk/gkr-pk-import.c	Mon Jul 14 19:54:11 2008
@@ -532,7 +532,7 @@
 		if (err->domain == GKR_PKIX_PARSE_ERROR)
 			ret = CKR_DATA_INVALID;
 		else
-			ret = CKR_GENERAL_ERROR;
+			ret = CKR_FUNCTION_FAILED;
 
 		g_message ("couldn't import data: %s", err && err->message ? err->message : "");
 		g_clear_error (&err);

Modified: trunk/daemon/pk/gkr-pk-object.c
==============================================================================
--- trunk/daemon/pk/gkr-pk-object.c	(original)
+++ trunk/daemon/pk/gkr-pk-object.c	Mon Jul 14 19:54:11 2008
@@ -558,12 +558,12 @@
 	res = gkr_pk_storage_store (the_storage, *object, &err);
 	
 	if (!res) {
-		g_warning ("couldn't store created object: %s", 
+		g_message ("couldn't store created object: %s", 
 		           err && err->message ? err->message : "");
 		g_clear_error (&err);
 		g_object_unref (*object);
 		*object = NULL;
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 	}
 
 	/* Register it with the object manager if necessary */

Modified: trunk/daemon/pk/gkr-pk-privkey.c
==============================================================================
--- trunk/daemon/pk/gkr-pk-privkey.c	(original)
+++ trunk/daemon/pk/gkr-pk-privkey.c	Mon Jul 14 19:54:11 2008
@@ -194,7 +194,7 @@
 	/* TODO: We should be mapping better return codes */
 	if (gcry != 0) {
 		g_message ("couldn't create RSA key from passed attributes");
-		ret = CKR_GENERAL_ERROR;
+		ret = CKR_FUNCTION_FAILED;
 		goto done;
 	}
 	
@@ -244,7 +244,7 @@
 	/* TODO: We should be mapping better return codes */
 	if (gcry != 0) {
 		g_message ("couldn't create DSA key from passed attributes");
-		ret = CKR_GENERAL_ERROR;
+		ret = CKR_FUNCTION_FAILED;
 		goto done;
 	}
 
@@ -300,7 +300,7 @@
 {
 	GkrPkPubkey *pub = get_public_key (key, TRUE);
 	if (pub == NULL)
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 	return gkr_pk_object_get_attribute (GKR_PK_OBJECT (pub), attr);
 }
 
@@ -312,7 +312,7 @@
 	
 	keyid = gkr_pk_privkey_get_keyid (key);
 	if (!keyid)
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 		
 	obj = GKR_PK_OBJECT (key);
 	crt = gkr_pk_manager_find_by_id (obj->manager, GKR_TYPE_PK_CERT, keyid); 
@@ -334,7 +334,7 @@
 		
 	/* Load our key */
 	if (!load_private_key (key))
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 	
 	if (key->priv->algorithm != algorithm)
 		return CKR_ATTRIBUTE_TYPE_INVALID;
@@ -449,7 +449,7 @@
 	case CKA_ID:
 		keyid = gkr_pk_privkey_get_keyid (key);
 		if (!keyid) 
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		value = (CK_VOID_PTR)gkr_id_get_raw (keyid, &len);
 		gkr_pk_attribute_set_data (attr, value, len);
 		return CKR_OK;

Modified: trunk/daemon/pk/gkr-pk-pubkey.c
==============================================================================
--- trunk/daemon/pk/gkr-pk-pubkey.c	(original)
+++ trunk/daemon/pk/gkr-pk-pubkey.c	Mon Jul 14 19:54:11 2008
@@ -148,7 +148,7 @@
 	/* TODO: We should be mapping better return codes */
 	if (gcry != 0) {
 		g_message ("couldn't create RSA key from passed attributes");
-		ret = CKR_GENERAL_ERROR;
+		ret = CKR_FUNCTION_FAILED;
 		goto done;
 	}
 	
@@ -186,7 +186,7 @@
 	/* TODO: We should be mapping better return codes */
 	if (gcry != 0) {
 		g_message ("couldn't create DSA key from passed attributes");
-		ret = CKR_GENERAL_ERROR;
+		ret = CKR_FUNCTION_FAILED;
 		goto done;
 	}
 	
@@ -208,13 +208,13 @@
 	GkrPkObject *crt, *obj;
 	
 	if (!load_public_key (key))
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 	
 	obj = GKR_PK_OBJECT (key);	
 	crt = gkr_pk_manager_find_by_id (obj->manager, type, key->pub->keyid);
 	
 	if (crt == NULL)
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 		
 	return gkr_pk_object_get_attribute (crt, attr);
 }
@@ -226,7 +226,7 @@
 	gboolean ret;
 	
 	if (!load_public_key (key))
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 	
 	if (key->pub->algorithm != algorithm)
 		return CKR_ATTRIBUTE_TYPE_INVALID;
@@ -246,7 +246,7 @@
 	gsize n_data;
 	
 	if (!load_public_key (key))
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 	
 	switch (gkr_pk_pubkey_get_algorithm (key)) {
 	case GCRY_PK_RSA:
@@ -346,7 +346,7 @@
 		
 	case CKA_KEY_TYPE:
 		if (!load_public_key (key))
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		switch (key->pub->algorithm) {
 		case GCRY_PK_RSA:
 			gkr_pk_attribute_set_ulong (attr, CKK_RSA);
@@ -362,7 +362,7 @@
 	
 	case CKA_MODULUS_BITS:
 		if (!load_public_key (key))
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		if (key->pub->algorithm != GCRY_PK_RSA)
 			return CKR_ATTRIBUTE_TYPE_INVALID;
 		g_assert (key->pub->numbers);
@@ -379,7 +379,7 @@
 	case CKA_ID:
 		/* Always a SHA-1 hash output buffer */
 		if (!load_public_key (key) || !key->pub->keyid)
-			return CKR_GENERAL_ERROR;
+			return CKR_FUNCTION_FAILED;
 		gkr_pk_attribute_set_id (attr, key->pub->keyid);
 		return CKR_OK;
 

Modified: trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c
==============================================================================
--- trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c	(original)
+++ trunk/daemon/pkcs11/gkr-pkcs11-daemon-session.c	Mon Jul 14 19:54:11 2008
@@ -391,7 +391,7 @@
 	 * not accept a PIN, but instead prompt for it. 
 	 */
 	if (!gkr_keyring_login_unlock (NULL))
-		return CKR_GENERAL_ERROR;
+		return CKR_FUNCTION_FAILED;
 
 	return CKR_OK;
 }
@@ -522,10 +522,10 @@
 	g_return_val_if_fail (object->storage, CKR_GENERAL_ERROR);
 	res = gkr_pk_storage_remove (object->storage, object, &err);
 	if (!res) {
-		g_warning ("couldn't remove object from disk: %s", 
+		g_message ("couldn't remove object from disk: %s", 
 		           err && err->message ? err->message : "");
 		g_clear_error (&err);
-		ret = CKR_GENERAL_ERROR;
+		ret = CKR_FUNCTION_FAILED;
 	}
 	
 	return ret;

Modified: trunk/daemon/pkcs11/gkr-pkcs11-dsa.c
==============================================================================
--- trunk/daemon/pkcs11/gkr-pkcs11-dsa.c	(original)
+++ trunk/daemon/pkcs11/gkr-pkcs11-dsa.c	Mon Jul 14 19:54:11 2008
@@ -47,8 +47,8 @@
 	*s_key = gkr_pk_pubkey_get_key (key);
 	if (!*s_key) {
 		/* TODO: This happens when the user doesn't unlock key, proper code */
-		g_warning ("couldn't get public key");
-		return CKR_GENERAL_ERROR;
+		g_message ("couldn't get public key");
+		return CKR_FUNCTION_FAILED;
 	}
 	
 	return CKR_OK;
@@ -70,8 +70,8 @@
 	*s_key = gkr_pk_privkey_get_key (key);
 	if (!*s_key) {
 		/* TODO: This happens when the user doesn't unlock key, proper code */
-		g_warning ("couldn't get private key");
-		return CKR_GENERAL_ERROR;
+		g_message ("couldn't get private key");
+		return CKR_FUNCTION_FAILED;
 	}
 	
 	return CKR_OK;
@@ -116,8 +116,8 @@
 	
 	/* TODO: Certain codes should be returned (data too big etc... ) */
 	if (gcry) {
-		g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
-		return CKR_GENERAL_ERROR;
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
 	}
 
 	*signature = g_new0 (guchar, 40);
@@ -182,8 +182,8 @@
 	if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) {
 		return CKR_SIGNATURE_INVALID;
 	} else if (gcry) {
-		g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
-		return CKR_GENERAL_ERROR;
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
 	}
 
 	return CKR_OK;

Modified: trunk/daemon/pkcs11/gkr-pkcs11-rsa.c
==============================================================================
--- trunk/daemon/pkcs11/gkr-pkcs11-rsa.c	(original)
+++ trunk/daemon/pkcs11/gkr-pkcs11-rsa.c	Mon Jul 14 19:54:11 2008
@@ -46,8 +46,8 @@
 	*s_key = gkr_pk_pubkey_get_key (key);
 	if (!*s_key) {
 		/* TODO: This happens when the user doesn't unlock key, proper code */
-		g_warning ("couldn't get public key");
-		return CKR_GENERAL_ERROR;
+		g_message ("couldn't get public key");
+		return CKR_FUNCTION_FAILED;
 	}
 	
 	return CKR_OK;
@@ -69,8 +69,8 @@
 	*s_key = gkr_pk_privkey_get_key (key);
 	if (!*s_key) {
 		/* TODO: This happens when the user doesn't unlock key, proper code */
-		g_warning ("couldn't get private key");
-		return CKR_GENERAL_ERROR;
+		g_message ("couldn't get private key");
+		return CKR_FUNCTION_FAILED;
 	}
 	
 	return CKR_OK;
@@ -167,8 +167,8 @@
 	
 	/* TODO: Certain codes should be returned (data too big etc... ) */
 	if (gcry) {
-		g_warning ("encrypting of the data failed: %s", gcry_strerror (gcry));
-		return CKR_GENERAL_ERROR;
+		g_message ("encrypting of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
 	}
 
 	/* Now extract and send it back out */
@@ -218,8 +218,8 @@
 	
 	/* TODO: Certain codes should be returned (data too big etc... ) */
 	if (gcry) {
-		g_warning ("decrypting of the data failed: %s", gcry_strerror (gcry));
-		return CKR_GENERAL_ERROR;
+		g_message ("decrypting of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
 	}
 gkr_crypto_sexp_dump (splain);
 
@@ -266,8 +266,8 @@
 	
 	/* TODO: Certain codes should be returned (data too big etc... ) */
 	if (gcry) {
-		g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
-		return CKR_GENERAL_ERROR;
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
 	}
 
 	/* Now extract and send it back out */
@@ -326,8 +326,8 @@
 	if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) {
 		return CKR_SIGNATURE_INVALID;
 	} else if (gcry) {
-		g_warning ("signing of the data failed: %s", gcry_strerror (gcry));
-		return CKR_GENERAL_ERROR;
+		g_message ("signing of the data failed: %s", gcry_strerror (gcry));
+		return CKR_FUNCTION_FAILED;
 	}
 
 	return CKR_OK;

Added: trunk/gp11/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/gp11/Makefile.am	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,52 @@
+incdir = $(includedir)/gp11
+
+inc_HEADERS = \
+	gp11.h \
+	pkcs11.h
+
+INCLUDES = \
+	-I$(top_builddir) \
+    	-I$(top_srcdir) \
+    	$(GOBJECT_CFLAGS) \
+	$(GTHREAD_CFLAGS) \
+	$(GLIB_CFLAGS)
+
+lib_LTLIBRARIES = libgp11.la
+
+libgp11_la_SOURCES = \
+	gp11.h gp11-private.h \
+	gp11-attributes.c \
+	gp11-call.c \
+	gp11-misc.c \
+	gp11-module.c \
+	gp11-object.c \
+	gp11-session.c \
+	gp11-slot.c 
+    
+libgp11_la_LDFLAGS = \
+    	-version-info $(GP11_LT_RELEASE) \
+	-no-undefined -export-symbols-regex 'gp11_*'
+    
+libgp11_la_LIBADD = \
+	$(GOBJECT_LIBS) \
+	$(GTHREAD_LIBS) \
+	$(GIO_LIBS) \
+	$(GLIB_LIBS)
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gp11-$(GP11_MAJOR).pc
+
+EXTRA_DIST = \
+    gp11.pc.in
+    
+gp11-$(GP11_MAJOR).pc: gp11.pc
+	cp gp11.pc gp11-$(GP11_MAJOR).pc
+
+if WITH_TESTS
+TESTS_DIR = tests
+else
+TESTS_DIR = 
+endif
+
+SUBDIRS = . $(TESTS_DIR)
+	
\ No newline at end of file

Added: trunk/gp11/gp11-attributes.c
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-attributes.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,508 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void
+gp11_attribute_init (GP11Attribute *attr, guint attr_type, 
+                     gconstpointer value, gsize length)
+{
+	g_assert (sizeof (GP11Attribute) == sizeof (CK_ATTRIBUTE));
+	memset (attr, 0, sizeof (GP11Attribute));
+	attr->type = attr_type;
+	attr->length = length;
+	attr->value = value && length ? g_memdup (value, length) : NULL;
+}
+
+void
+_gp11_attribute_init_take (GP11Attribute *attr, guint attr_type,
+                           gpointer value, gsize length)
+{
+	g_assert (sizeof (GP11Attribute) == sizeof (CK_ATTRIBUTE));
+	memset (attr, 0, sizeof (GP11Attribute));
+	attr->type = attr_type;
+	attr->length = length;
+	attr->value = value && length ? value : NULL;	
+}
+
+void 
+gp11_attribute_init_boolean (GP11Attribute *attr, guint attr_type, 
+                             gboolean value)
+{
+	CK_BBOOL bvalue = value ? CK_TRUE : CK_FALSE;
+	gp11_attribute_init (attr, attr_type, &bvalue, sizeof (bvalue));
+}
+
+void
+gp11_attribute_init_date (GP11Attribute *attr, guint attr_type, 
+                          const GDate *value)
+{
+	gchar buffer[9];
+	CK_DATE date;
+	g_return_if_fail (value);
+	g_snprintf (buffer, sizeof (buffer), "%04d%02d%02d",
+	            (int)g_date_get_year (value), 
+	            (int)g_date_get_month (value),
+	            (int)g_date_get_day (value));
+	memcpy (&date.year, buffer + 0, 4);
+	memcpy (&date.month, buffer + 4, 2);
+	memcpy (&date.day, buffer + 6, 2);
+	gp11_attribute_init (attr, attr_type, &date, sizeof (CK_DATE));
+}
+
+void
+gp11_attribute_init_ulong (GP11Attribute *attr, guint attr_type,
+                           gulong value)
+{
+	CK_ULONG uvalue = value;
+	gp11_attribute_init (attr, attr_type, &uvalue, sizeof (uvalue));
+}
+
+void
+gp11_attribute_init_string (GP11Attribute *attr, guint attr_type, 
+                            const gchar *value)
+{
+	gsize len = value ? strlen (value) : 0;
+	gp11_attribute_init (attr, attr_type, (gpointer)value, len);
+}
+
+
+GP11Attribute*
+gp11_attribute_new (guint attr_type, gpointer value, gsize length)
+{
+	GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+	gp11_attribute_init (attr, attr_type, value, length);
+	return attr;
+}
+
+GP11Attribute*
+gp11_attribute_new_boolean (guint attr_type, gboolean value)
+{
+	GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+	gp11_attribute_init_boolean (attr, attr_type, value);
+	return attr;	
+}
+
+GP11Attribute*
+gp11_attribute_new_date (guint attr_type, const GDate *value)
+{
+	GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+	gp11_attribute_init_date (attr, attr_type, value);
+	return attr;		
+}
+
+GP11Attribute*
+gp11_attribute_new_ulong (guint attr_type, gulong value)
+{
+	GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+	gp11_attribute_init_ulong (attr, attr_type, value);
+	return attr;			
+}
+
+GP11Attribute*
+gp11_attribute_new_string (guint attr_type, const gchar *value)
+{
+	GP11Attribute *attr = g_slice_new0 (GP11Attribute);
+	gp11_attribute_init_string (attr, attr_type, value);
+	return attr;		
+}
+
+gboolean
+gp11_attribute_get_boolean (GP11Attribute *attr)
+{
+	g_return_val_if_fail (attr, FALSE);
+	g_return_val_if_fail (attr->length == sizeof (CK_BBOOL), FALSE);
+	g_return_val_if_fail (attr->value, FALSE);
+	return *((CK_BBOOL*)attr->value) == CK_TRUE ? TRUE : FALSE;
+}
+
+gulong
+gp11_attribute_get_ulong (GP11Attribute *attr)
+{
+	g_return_val_if_fail (attr, FALSE);
+	g_return_val_if_fail (attr->length == sizeof (CK_ULONG), (gulong)-1);
+	g_return_val_if_fail (attr->value, (gulong)-1);
+	return *((CK_ULONG*)attr->value);
+}
+
+gchar*
+gp11_attribute_get_string (GP11Attribute *attr)
+{
+	g_return_val_if_fail (attr, NULL);
+	
+	if (!attr->value)
+		return NULL;
+
+	return g_strndup (attr->value, attr->length);
+}
+
+GDate*
+gp11_attribute_get_date (GP11Attribute *attr)
+{
+	guint year, month, day;
+	gchar buffer[5];
+	CK_DATE *date;
+	gchar *end;
+	
+	g_return_val_if_fail (attr, NULL);
+	g_return_val_if_fail (attr->length == sizeof (CK_DATE), NULL);
+	g_return_val_if_fail (attr->value, NULL);
+	date = (CK_DATE*)attr->value;
+	
+	memset (&buffer, 0, sizeof (buffer));
+	memcpy (buffer, date->year, 4);
+	year = strtol (buffer, &end, 10);
+	g_return_val_if_fail (end != buffer && !*end, NULL); 
+	
+	memset (&buffer, 0, sizeof (buffer));
+	memcpy (buffer, date->month, 2);
+	month = strtol (buffer, &end, 10);
+	g_return_val_if_fail (end != buffer && !*end, NULL); 
+
+	memset (&buffer, 0, sizeof (buffer));
+	memcpy (buffer, date->day, 2);
+	day = strtol (buffer, &end, 10);
+	g_return_val_if_fail (end != buffer && !*end, NULL); 
+	
+	return g_date_new_dmy (day, month, year);	
+}
+
+GP11Attribute*
+gp11_attribute_dup (GP11Attribute *attr)
+{
+	GP11Attribute *copy;
+	
+	if (!attr)
+		return NULL;
+	
+	copy = g_slice_new0 (GP11Attribute);
+	gp11_attribute_init_copy (copy, attr);
+	return copy;
+}
+
+void
+gp11_attribute_init_copy (GP11Attribute *dest, GP11Attribute *src)
+{
+	g_return_if_fail (dest);
+	g_return_if_fail (src);
+
+	/* 
+	 * TODO: Handle stupid, dumb, broken, special cases like
+	 * CKA_WRAP_TEMPLATE and CKA_UNWRAP_TEMPLATE. 
+	 */
+	
+	memcpy (dest, src, sizeof (GP11Attribute));
+	dest->value = src->value && src->length ? g_memdup (src->value, src->length) : NULL;
+}
+
+void
+gp11_attribute_clear (GP11Attribute *attr)
+{
+	g_return_if_fail (attr);
+	g_free (attr->value);
+	memset (attr, 0, sizeof (GP11Attribute));
+}
+
+void
+gp11_attribute_free (GP11Attribute *attr)
+{
+	if (attr) {
+		gp11_attribute_clear (attr);
+		g_slice_free (GP11Attribute, attr);
+	}
+}
+
+struct _GP11Attributes {
+	GArray *array;
+	gint immutable;
+	gint refs;
+};
+
+GP11Attributes*
+gp11_attributes_new (void)
+{
+	GP11Attributes *attrs;
+	
+	g_assert (sizeof (GP11Attribute) == sizeof (CK_ATTRIBUTE));
+	attrs = g_slice_new0 (GP11Attributes);
+	attrs->array = g_array_new (0, 1, sizeof (GP11Attribute));
+	attrs->refs = 1;
+	attrs->immutable = 0;
+	return attrs;
+}
+
+static GP11Attributes*
+initialize_from_valist (guint type, va_list va)
+{
+	GP11Attributes *attrs;
+	gssize length;
+	gpointer value;
+	
+	attrs = gp11_attributes_new ();
+	
+	/* No attributes */
+	if (type == (guint)-1)
+		return attrs;
+	
+	do {
+		length = va_arg (va, gssize);
+		
+		/* All the different set types */
+		switch (length) {
+		case GP11_BOOLEAN:
+			gp11_attributes_add_boolean (attrs, type, va_arg (va, gboolean));
+			break;
+		case GP11_ULONG:
+			gp11_attributes_add_ulong (attrs, type, va_arg (va, gulong));
+			break;
+		case GP11_STRING:
+			gp11_attributes_add_string (attrs, type, va_arg (va, const gchar*));
+			break;
+		case GP11_DATE:
+			gp11_attributes_add_date (attrs, type, va_arg (va, const GDate*));
+			break;
+
+		/* Otherwise it should be data */
+		default:
+			value = va_arg (va, gpointer);
+			
+			/* But not this long */
+			if (length < 0 || length >= G_MAXSSIZE)
+				g_warning ("length passed to attributes varargs is invalid or too large: %d", length);
+			else
+				gp11_attributes_add_data (attrs, type, value, length);
+			break;
+		};
+		
+		type = va_arg (va, guint);
+			
+	} while (type != (guint)-1);
+		
+	return attrs;
+}
+
+GP11Attributes*
+gp11_attributes_newv (guint first_type, ...)
+{
+	GP11Attributes *attrs;
+	va_list va;
+	
+	va_start (va, first_type);
+	attrs = initialize_from_valist (first_type, va);
+	va_end (va);
+	
+	return attrs;
+}
+
+GP11Attributes*
+gp11_attributes_new_valist (va_list va)
+{
+	guint type = va_arg (va, guint);
+	return initialize_from_valist (type, va);
+}
+
+GP11Attribute*
+gp11_attributes_at (GP11Attributes *attrs, guint index)
+{
+	g_return_val_if_fail (attrs && attrs->array, NULL);
+	g_return_val_if_fail (index < attrs->array->len, NULL);
+	g_return_val_if_fail (g_atomic_int_get (&attrs->immutable) == 0, NULL);
+	return &g_array_index (attrs->array, GP11Attribute, index);
+}
+
+CK_ATTRIBUTE_PTR
+_gp11_attributes_raw (GP11Attributes *attrs)
+{
+	g_return_val_if_fail (attrs && attrs->array, NULL);
+	return (CK_ATTRIBUTE_PTR)attrs->array->data;
+}
+
+static GP11Attribute*
+attributes_push (GP11Attributes *attrs)
+{
+	GP11Attribute attr;
+	g_assert (g_atomic_int_get (&attrs->immutable) == 0);
+	
+	memset (&attr, 0, sizeof (attr));
+	g_array_append_val (attrs->array, attr);
+	return &g_array_index (attrs->array, GP11Attribute, attrs->array->len - 1);
+}
+
+void
+gp11_attributes_add (GP11Attributes *attrs, GP11Attribute *attr)
+{
+	GP11Attribute *added;
+	g_return_if_fail (attrs && attrs->array);
+	g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+	g_return_if_fail (attr);
+	added = attributes_push (attrs);
+	gp11_attribute_init_copy (added, attr);
+}
+
+void
+_gp11_attributes_add_take (GP11Attributes *attrs, guint attr_type,
+                           gpointer value, gsize length)
+{
+	GP11Attribute *added;
+	g_return_if_fail (attrs);
+	g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+	added = attributes_push (attrs);
+	_gp11_attribute_init_take (added, attr_type, (gpointer)value, length);
+}
+
+void 
+gp11_attributes_add_data (GP11Attributes *attrs, guint attr_type,
+                          gconstpointer value, gsize length)
+{
+	GP11Attribute *added;
+	g_return_if_fail (attrs);
+	g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+	added = attributes_push (attrs);
+	gp11_attribute_init (added, attr_type, value, length);
+}
+
+void
+gp11_attributes_add_boolean (GP11Attributes *attrs, guint attr_type, gboolean value)
+{
+	GP11Attribute *added;
+	g_return_if_fail (attrs);
+	g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+	added = attributes_push (attrs);
+	gp11_attribute_init_boolean (added, attr_type, value);
+}
+
+void
+gp11_attributes_add_string (GP11Attributes *attrs, guint attr_type, const gchar *value)
+{
+	GP11Attribute *added;
+	g_return_if_fail (attrs);
+	g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+	added = attributes_push (attrs);
+	gp11_attribute_init_string (added, attr_type, value);
+}
+
+void
+gp11_attributes_add_date (GP11Attributes *attrs, guint attr_type, const GDate *value)
+{
+	GP11Attribute *added;
+	g_return_if_fail (attrs);
+	g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+	added = attributes_push (attrs);
+	gp11_attribute_init_date (added, attr_type, value);
+}
+
+void
+gp11_attributes_add_ulong (GP11Attributes *attrs, guint attr_type, gulong value)
+{
+	GP11Attribute *added;
+	g_return_if_fail (attrs);
+	g_return_if_fail (g_atomic_int_get (&attrs->immutable) == 0);
+	added = attributes_push (attrs);
+	gp11_attribute_init_ulong (added, attr_type, value);
+}
+
+gulong
+gp11_attributes_count (GP11Attributes *attrs)
+{
+	g_return_val_if_fail (attrs, 0);
+	return attrs->array->len;
+}
+
+
+GP11Attribute*
+gp11_attributes_find (GP11Attributes *attrs, guint attr_type)
+{
+	GP11Attribute *attr;
+	guint i;
+	
+	g_return_val_if_fail (attrs && attrs->array, NULL);
+	
+	for (i = 0; i < attrs->array->len; ++i) {
+		attr = gp11_attributes_at (attrs, i);
+		if (attr->type == attr_type)
+			return attr;
+	}
+	
+	return NULL;
+}
+
+gboolean
+gp11_attributes_find_boolean (GP11Attributes *attrs, guint attr_type, gboolean *value)
+{
+	GP11Attribute *attr;
+	g_return_val_if_fail (value, FALSE);
+
+	attr = gp11_attributes_find (attrs, attr_type);
+	if (!attr)
+		return FALSE;
+	*value = gp11_attribute_get_boolean (attr);
+	return TRUE;
+}
+
+gboolean
+gp11_attributes_find_ulong (GP11Attributes *attrs, guint attr_type, gulong *value)
+{
+	GP11Attribute *attr;
+	g_return_val_if_fail (value, FALSE);
+
+	attr = gp11_attributes_find (attrs, attr_type);
+	if (!attr)
+		return FALSE;
+	*value = gp11_attribute_get_ulong (attr);
+	return TRUE;
+}
+
+gboolean
+gp11_attributes_find_string (GP11Attributes *attrs, guint attr_type, gchar **value)
+{
+	GP11Attribute *attr;
+	g_return_val_if_fail (value, FALSE);
+
+	attr = gp11_attributes_find (attrs, attr_type);
+	if (!attr)
+		return FALSE;
+	*value = gp11_attribute_get_string (attr);
+	return TRUE;
+}
+
+gboolean
+gp11_attributes_find_date (GP11Attributes *attrs, guint attr_type, GDate **value)
+{
+	GP11Attribute *attr;
+	g_return_val_if_fail (value, FALSE);
+
+	attr = gp11_attributes_find (attrs, attr_type);
+	if (!attr)
+		return FALSE;
+	*value = gp11_attribute_get_date (attr);
+	return TRUE;
+}
+
+void 
+gp11_attributes_ref (GP11Attributes *attrs)
+{
+	g_return_if_fail (attrs);
+	g_atomic_int_inc (&attrs->refs);
+}
+
+void
+gp11_attributes_unref (GP11Attributes *attrs)
+{
+	guint i;
+	
+	if (!attrs)
+		return;
+	
+	if (g_atomic_int_dec_and_test (&attrs->refs)) {
+		g_return_if_fail (attrs->array);
+		for (i = 0; i < attrs->array->len; ++i)
+			gp11_attribute_clear (gp11_attributes_at (attrs, i));
+		g_array_free (attrs->array, TRUE);
+		attrs->array = NULL;
+		g_slice_free (GP11Attributes, attrs);
+	}
+}

Added: trunk/gp11/gp11-call.c
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-call.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,341 @@
+
+#include "gp11-private.h"
+
+
+static GThreadPool *thread_pool = NULL;
+static GAsyncQueue *completed_queue = NULL;
+static guint completed_id = 0;
+
+static void _gp11_call_implement_async_result (GAsyncResultIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GP11Call, _gp11_call, G_TYPE_OBJECT, 0,
+        G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, _gp11_call_implement_async_result));
+
+/* ----------------------------------------------------------------------------
+ * HELPER FUNCTIONS
+ */
+
+static CK_RV
+perform_call (GP11CallFunc func, GCancellable *cancellable, GP11Arguments *args)
+{
+	CK_RV rv;
+	
+	/* Double check a few things */
+	g_assert (func);
+	g_assert (args);
+
+	if (cancellable) {
+		if (g_cancellable_is_cancelled (cancellable)) { 
+			return CKR_FUNCTION_CANCELED;
+		}
+		
+		/* Push for the notify callback */
+		g_object_ref (cancellable);
+		g_cancellable_push_current (cancellable);
+	}
+	
+	rv = (func) (args);
+	
+	if (cancellable) {
+		g_cancellable_pop_current (cancellable);
+		g_object_unref (cancellable);
+	}
+	
+	return rv;
+}
+
+static void
+process_async_call (gpointer data, gpointer unused)
+{
+	GP11Call *call = GP11_CALL (data);
+	g_assert (GP11_IS_CALL (call));
+
+	g_assert (call->rv == CKR_OK);
+	
+	call->rv = perform_call (call->func, call->cancellable, 
+	                         call->args);
+	
+	g_async_queue_push (completed_queue, call);
+	
+	/* Wakeup main thread if on a separate thread */
+	g_main_context_wakeup (NULL);
+}
+static void 
+process_result (GP11Call *call, gpointer unused)
+{
+	/* Double check a few things */
+	g_assert (GP11_IS_CALL (call));
+	
+	if (call->cancellable) {
+		/* Don't call the callback when cancelled */
+		if (g_cancellable_is_cancelled (call->cancellable))
+			return;
+	}
+	
+	if (call->callback) {
+		g_assert (G_IS_OBJECT (call->object));
+		(call->callback) (G_OBJECT (call->object), G_ASYNC_RESULT (call), 
+				  call->user_data);
+	}
+}
+
+static gboolean
+completed_prepare(GSource* source, gint *timeout)
+{
+	gboolean have;
+	g_assert (completed_queue);
+	have = g_async_queue_length (completed_queue) > 0;
+	*timeout = have ? 0 : -1;
+	return have;
+}
+
+static gboolean
+completed_check(GSource* source)
+{
+	g_assert (completed_queue);
+	return g_async_queue_length (completed_queue) > 0;
+}
+
+static gboolean
+completed_dispatch(GSource* source, GSourceFunc callback, gpointer user_data)
+{
+	gpointer *call;
+	
+	g_assert (completed_queue);
+	g_assert (callback);
+	
+	call = g_async_queue_try_pop (completed_queue);
+	if (call) {
+		((GFunc)callback) (call, user_data);
+		g_object_unref (call);
+	}
+
+	return TRUE;
+}
+
+static void
+completed_finalize(GSource* source)
+{
+	
+}
+
+static GSourceFuncs completed_functions = {
+	completed_prepare,
+	completed_check,
+	completed_dispatch,
+	completed_finalize
+};
+
+/* ----------------------------------------------------------------------------
+ * OBJECT 
+ */
+
+static void
+_gp11_call_init (GP11Call *call)
+{
+	call->rv = CKR_OK;
+}
+
+static void
+_gp11_call_finalize (GObject *obj)
+{
+	GP11Call *call = GP11_CALL (obj);
+
+	if (call->object)
+		g_object_unref (call->object);
+	call->object = NULL;
+	
+	if (call->cancellable)
+		g_object_unref (call->cancellable);
+	call->cancellable = NULL;
+
+	if (call->destroy)
+		(call->destroy) (call->args);
+	call->destroy = NULL;
+	call->args = NULL;
+	
+	G_OBJECT_CLASS (_gp11_call_parent_class)->finalize (obj);
+}
+
+static gpointer
+_gp11_call_get_user_data (GAsyncResult *async_result)
+{
+	g_return_val_if_fail (GP11_IS_CALL (async_result), NULL);
+	return GP11_CALL (async_result)->user_data;
+}
+
+static GObject*  
+_gp11_call_get_source_object (GAsyncResult *async_result)
+{
+	g_return_val_if_fail (GP11_IS_CALL (async_result), NULL);
+	return GP11_CALL (async_result)->object;	
+}
+
+static void 
+_gp11_call_implement_async_result (GAsyncResultIface *iface)
+{
+	iface->get_user_data = _gp11_call_get_user_data;
+	iface->get_source_object = _gp11_call_get_source_object;
+}
+
+static void
+_gp11_call_class_init (GP11CallClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*)klass;
+	GMainContext *context;
+	GError *err = NULL;
+	GSource *src;
+
+	_gp11_call_parent_class = g_type_class_peek_parent (klass);
+	gobject_class->finalize = _gp11_call_finalize;
+	
+	g_assert (!thread_pool);
+	thread_pool = g_thread_pool_new ((GFunc)process_async_call, NULL, -1, FALSE, &err);
+	if (!thread_pool) {
+		g_critical ("couldn't create thread pool: %s", 
+		            err && err->message ? err->message : "");
+		return;
+	}
+	
+	g_assert (!completed_queue);
+	completed_queue = g_async_queue_new_full (g_object_unref);
+	g_assert (completed_queue);
+	
+	context = g_main_context_default ();
+	g_assert (context);
+	
+	/* Add our idle handler which processes other tasks */
+	g_assert (!completed_id);
+	src = g_source_new (&completed_functions, sizeof (GSource));
+	completed_id = g_source_attach (src, context);
+	g_source_set_callback (src, (GSourceFunc)process_result, NULL, NULL);
+	g_source_unref (src);
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+void
+_gp11_call_uninitialize (void)
+{
+	GMainContext *context;
+	GSource *src;
+
+	if (thread_pool) {
+		g_thread_pool_free (thread_pool, FALSE, TRUE);
+		thread_pool = NULL;
+	}
+	
+	if (completed_id) {
+		context = g_main_context_default ();
+		g_return_if_fail (context);
+		
+		src = g_main_context_find_source_by_id (context, completed_id);
+		g_assert (src);
+		g_source_destroy (src);
+		completed_id = 0;
+	}
+	if (completed_queue) {
+		g_async_queue_unref (completed_queue);
+		completed_queue = NULL;
+	}
+}
+
+gboolean
+_gp11_call_sync (gpointer object, gpointer func, gpointer data, 
+                 GCancellable *cancellable, GError **err)
+{
+	GP11Arguments *args = (GP11Arguments*)data;
+	GP11Module *module;
+	CK_RV rv;
+	
+	g_assert (G_IS_OBJECT (object));
+	g_assert (func);
+	g_assert (args);
+	
+	g_object_get (object, "module", &module, "handle", &args->handle, NULL);
+	g_assert (GP11_IS_MODULE (module));
+	
+	args->pkcs11 = module->funcs;
+	g_object_unref (module);
+	
+	rv = perform_call ((GP11CallFunc)func, cancellable, args);
+	if (rv == CKR_OK)
+		return TRUE;
+	
+	g_set_error (err, GP11_ERROR, rv, gp11_message_from_rv (rv));
+	return FALSE;
+}
+
+gpointer
+_gp11_call_async_prep (gpointer object, gpointer func, gsize args_size, gpointer destroy)
+{
+	GP11Arguments *args;
+	GP11Module *module;
+	GP11Call *call;
+
+	g_assert (G_IS_OBJECT (object));
+	g_assert (func);
+	
+	if (!destroy)
+		destroy = g_free;
+
+	if (args_size == 0)
+		args_size = sizeof (GP11Arguments);
+	g_assert (args_size >= sizeof (GP11Arguments));
+	
+	args = g_malloc0 (args_size);
+	g_object_get (object, "module", &module, "handle", &args->handle, NULL);
+	g_assert (GP11_IS_MODULE (module));
+	args->pkcs11 = module->funcs;
+	g_object_unref (module);
+	
+	call = g_object_new (GP11_TYPE_CALL, NULL);
+	call->destroy = (GDestroyNotify)destroy;
+	call->func = (GP11CallFunc)func;
+	call->object = object;
+	g_object_ref (object);
+
+	/* Hook the two together */
+	call->args = args;
+	call->args->call = call;
+
+	return args;
+}
+
+void
+_gp11_call_async_go (gpointer data, GCancellable *cancellable, 
+                     GAsyncReadyCallback callback, gpointer user_data)
+{
+	GP11Arguments *args = (GP11Arguments*)data;
+	
+	g_assert (GP11_IS_CALL (args->call));
+	
+	args->call->cancellable = cancellable;
+	if (cancellable) {
+		g_assert (G_IS_CANCELLABLE (cancellable));
+		g_object_ref (cancellable);
+	}
+	
+	args->call->callback = callback;
+	args->call->user_data = user_data;
+	
+	g_assert (thread_pool);
+	g_thread_pool_push (thread_pool, args->call, NULL);
+}
+
+gboolean
+_gp11_call_basic_finish (gpointer object, GAsyncResult *result, GError **err)
+{
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_CALL (result), FALSE);
+	
+	rv = GP11_CALL (result)->rv;
+	if (rv == CKR_OK)
+		return TRUE;
+	
+	g_set_error (err, GP11_ERROR, rv, gp11_message_from_rv (rv));
+	return FALSE;	
+}

Added: trunk/gp11/gp11-misc.c
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-misc.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,218 @@
+
+#include "gp11.h"
+
+#include <glib/gi18n.h>
+
+GQuark
+gp11_get_error_quark (void)
+{
+	static GQuark domain = 0;
+	if (domain == 0)
+		domain = g_quark_from_static_string ("gp11-error");
+	return domain;
+}
+
+void
+gp11_list_unref_free (GList *reflist)
+{
+	GList *l;
+	for (l = reflist; l; l = g_list_next (l)) {
+		g_return_if_fail (G_IS_OBJECT (l->data));
+		g_object_unref (l->data);
+	}
+	g_list_free (reflist);
+}
+
+const gchar*
+gp11_message_from_rv (CK_RV rv)
+{
+	switch (rv) {
+	
+	/* These are not really errors, or not current */
+	case CKR_OK:
+	case CKR_NO_EVENT:
+	case CKR_FUNCTION_NOT_PARALLEL:
+	case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
+		g_return_val_if_reached ("");
+		
+	case CKR_CANCEL:
+	case CKR_FUNCTION_CANCELED:
+		return _("The operation was cancelled");
+		
+	case CKR_HOST_MEMORY:
+		return _("Insufficient memory available");
+	case CKR_SLOT_ID_INVALID:
+		return _("The specified slot ID is not valid");
+	case CKR_GENERAL_ERROR:
+		return _("Internal error");
+	case CKR_FUNCTION_FAILED:
+		return _("The operation failed");
+	case CKR_ARGUMENTS_BAD:
+		return _("Invalid arguments");
+	case CKR_NEED_TO_CREATE_THREADS:
+		return _("The module cannot created needed threads");
+	case CKR_CANT_LOCK:
+		return _("The module cannot lock data properly");
+	case CKR_ATTRIBUTE_READ_ONLY:
+		return _("The field is read-only");
+	case CKR_ATTRIBUTE_SENSITIVE:
+		return _("The field is sensitive and cannot be revealed");
+	case CKR_ATTRIBUTE_TYPE_INVALID:
+		return _("The field is invalid or does not exist");
+	case CKR_ATTRIBUTE_VALUE_INVALID:
+		return _("Invalid value for field");
+	case CKR_DATA_INVALID:
+		return _("The data is not valid or unrecognized");
+	case CKR_DATA_LEN_RANGE:
+		return _("The data is too long");
+	case CKR_DEVICE_ERROR:
+		return _("An error occurred on the device");
+	case CKR_DEVICE_MEMORY:
+		return _("Insufficient memory available on device");
+	case CKR_DEVICE_REMOVED:
+		return _("The device was removed or unplugged");
+	case CKR_ENCRYPTED_DATA_INVALID:
+		return _("The encrypted data is not valid or unrecognized");
+	case CKR_ENCRYPTED_DATA_LEN_RANGE:
+		return _("The encrypted data is too long");
+	case CKR_FUNCTION_NOT_SUPPORTED:
+		return _("This operation is not supported");
+	case CKR_KEY_HANDLE_INVALID:
+		return _("The key is missing or invalid");
+	case CKR_KEY_SIZE_RANGE:
+		return _("The key is the wrong size");
+	case CKR_KEY_TYPE_INCONSISTENT:
+		return _("The key is of the wrong type");
+	case CKR_KEY_NOT_NEEDED:
+		return _("No key is needed");
+	case CKR_KEY_CHANGED:
+		return _("The key is different than before");
+	case CKR_KEY_NEEDED:
+		return _("A key is needed");
+	case CKR_KEY_INDIGESTIBLE:
+		return _("Cannot include the key in digest");
+	case CKR_KEY_FUNCTION_NOT_PERMITTED:
+		return _("This operation cannot be done with this key");
+	case CKR_KEY_NOT_WRAPPABLE:
+		return _("The key cannot be wrapped");
+	case CKR_KEY_UNEXTRACTABLE:
+		return _("Cannot export this key");
+	case CKR_MECHANISM_INVALID:
+		return _("The crypto mechanism is invalid or unrecognized");
+	case CKR_MECHANISM_PARAM_INVALID:
+		return _("The crypto mechanism has an invalid argument");
+	case CKR_OBJECT_HANDLE_INVALID:
+		return _("The object is missing or invalid");
+	case CKR_OPERATION_ACTIVE:
+		return _("Another operation is already taking place");
+	case CKR_OPERATION_NOT_INITIALIZED:
+		return _("No operation is taking place");
+	case CKR_PIN_INCORRECT:
+		return _("The password or PIN is incorrect");
+	case CKR_PIN_INVALID:
+		return _("The password or PIN is invalid");
+	case CKR_PIN_LEN_RANGE:
+		return _("The password or PIN is of an invalid length");
+	case CKR_PIN_EXPIRED:
+		return _("The password or PIN has expired");
+	case CKR_PIN_LOCKED:
+		return _("The password or PIN is locked");
+	case CKR_SESSION_CLOSED:
+		return _("The session is closed");
+	case CKR_SESSION_COUNT:
+		return _("Too many sessions are active");
+	case CKR_SESSION_HANDLE_INVALID:
+		return _("The session is invalid");
+	case CKR_SESSION_READ_ONLY:
+		return _("The session is read-only");
+	case CKR_SESSION_EXISTS:
+		return _("An open session exists");
+	case CKR_SESSION_READ_ONLY_EXISTS:
+		return _("A read-only session exists");
+	case CKR_SESSION_READ_WRITE_SO_EXISTS:
+		return _("An administrator session exists");
+	case CKR_SIGNATURE_INVALID:
+		return _("The signature is bad or corrupted");
+	case CKR_SIGNATURE_LEN_RANGE:
+		return _("The signature is unrecognized or corrupted");
+	case CKR_TEMPLATE_INCOMPLETE:
+		return _("Certain required fields are missing");
+	case CKR_TEMPLATE_INCONSISTENT:
+		return _("Certain fields have invalid values");
+	case CKR_TOKEN_NOT_PRESENT:
+		return _("The device is not present or unplugged");
+	case CKR_TOKEN_NOT_RECOGNIZED:
+		return _("The device is invalid or unregocnizable");
+	case CKR_TOKEN_WRITE_PROTECTED:
+		return _("The device is write protected");
+	case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
+		return _("Cannot import because the key is invalid");
+	case CKR_UNWRAPPING_KEY_SIZE_RANGE:
+		return _("Cannot import because the key is of the wrong size");
+	case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
+		return _("Cannot import because the key is of the wrong type");
+	case CKR_USER_ALREADY_LOGGED_IN:
+		return _("You are already logged in");
+	case CKR_USER_NOT_LOGGED_IN:
+		return _("No user has logged in");
+	case CKR_USER_PIN_NOT_INITIALIZED:
+		return _("The user's password or PIN is not set");
+	case CKR_USER_TYPE_INVALID:
+		return _("The user is of an invalid type");
+	case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
+		return _("Another user is already logged in");
+	case CKR_USER_TOO_MANY_TYPES:
+		return _("Too many users of different types logged in");
+	case CKR_WRAPPED_KEY_INVALID:
+		return _("Cannot import an invalid key");
+	case CKR_WRAPPED_KEY_LEN_RANGE:
+		return _("Cannot import a key of the wrong size");
+	case CKR_WRAPPING_KEY_HANDLE_INVALID:
+		return _("Cannot export because the key is invalid");
+	case CKR_WRAPPING_KEY_SIZE_RANGE:
+		return _("Cannot export because the key is of the wrong size");
+	case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
+		return _("Cannot export because the key is of the wrong type");
+	case CKR_RANDOM_SEED_NOT_SUPPORTED:
+		return _("Cannot set a random seed");
+	case CKR_RANDOM_NO_RNG:
+		return _("No random number generator available");
+	case CKR_DOMAIN_PARAMS_INVALID:
+		return _("The crypto mechanism has an invalid parameter");
+	case CKR_BUFFER_TOO_SMALL:
+		return _("Not enough space to store the result");
+	case CKR_SAVED_STATE_INVALID:
+		return _("The saved state is invalid");
+	case CKR_INFORMATION_SENSITIVE:
+		return _("The information is sensitive and cannot be revealed");
+	case CKR_STATE_UNSAVEABLE:
+		return _("The state cannot be saved");
+	case CKR_CRYPTOKI_NOT_INITIALIZED:
+		return _("The module has not been initialized");
+	case CKR_CRYPTOKI_ALREADY_INITIALIZED:
+		return _("The module has already been initialized");
+	case CKR_MUTEX_BAD:
+		return _("Cannot lock data");
+	case CKR_MUTEX_NOT_LOCKED:
+		return _("The data cannot be locked");
+	case CKR_FUNCTION_REJECTED:
+		return _("The signature request was rejected by the user");
+		
+	default:
+		g_message ("unknown error: %u", (guint)rv);
+		return _("Unknown error");
+	}
+}
+
+gchar*
+gp11_string_from_chars (const guchar *data, gsize max)
+{
+	gchar *string;
+	
+	g_return_val_if_fail (data, NULL);
+	g_return_val_if_fail (max, NULL);
+	
+	string = g_strndup ((gchar*)data, max);
+	g_strstrip (string);
+	return string;
+}

Added: trunk/gp11/gp11-module.c
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-module.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,319 @@
+
+#include "config.h"
+
+#include "gp11.h"
+
+#include <string.h>
+
+enum {
+	PROP_0,
+	PROP_MODULE_PATH
+};
+
+typedef struct _GP11ModulePrivate {
+	GModule *module;
+} GP11ModulePrivate;
+
+#define GP11_MODULE_GET_PRIVATE(o) \
+      (G_TYPE_INSTANCE_GET_PRIVATE((o), GP11_TYPE_MODULE, GP11ModulePrivate))
+
+G_DEFINE_TYPE (GP11Module, gp11_module, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * HELPERS
+ */
+
+static CK_RV
+create_mutex (void **mutex)
+{
+	if (!mutex)
+		return CKR_ARGUMENTS_BAD;
+	
+	if (!g_thread_supported ()) {
+		g_warning ("cannot create pkcs11 mutex, threading has not been initialized");
+		return CKR_GENERAL_ERROR;
+	}
+		
+	*mutex = g_mutex_new ();
+	g_return_val_if_fail (*mutex, CKR_GENERAL_ERROR);
+	return CKR_OK;
+}
+
+static CK_RV
+destroy_mutex (void *mutex)
+{
+	if (!mutex)
+		return CKR_MUTEX_BAD;
+	g_mutex_free ((GMutex*)mutex);
+	return CKR_OK;
+}
+
+static CK_RV
+lock_mutex (void *mutex)
+{
+	if (!mutex)
+		return CKR_MUTEX_BAD;
+	g_mutex_lock ((GMutex*)mutex);
+	return CKR_OK;
+}
+
+static CK_RV
+unlock_mutex (void *mutex)
+{
+	if (!mutex)
+		return CKR_MUTEX_BAD;
+	g_mutex_unlock ((GMutex*)mutex);
+	return CKR_OK;
+}
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_module_init (GP11Module *module)
+{
+	
+}
+
+static void
+gp11_module_get_property (GObject *obj, guint prop_id, GValue *value, 
+                          GParamSpec *pspec)
+{
+	GP11Module *module = GP11_MODULE (obj);
+
+	switch (prop_id) {
+	case PROP_MODULE_PATH:
+		g_value_set_string (value, module->path);
+		break;
+	}
+}
+
+static void
+gp11_module_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                          GParamSpec *pspec)
+{
+	GP11ModulePrivate *pv = GP11_MODULE_GET_PRIVATE (obj);
+	GP11Module *module = GP11_MODULE (obj);
+
+	switch (prop_id) {
+	case PROP_MODULE_PATH:
+		g_return_if_fail (!pv->module);
+		module->path = g_value_dup_string (value);
+		g_return_if_fail (module->path);
+		break;
+	}
+}
+
+static void
+gp11_module_dispose (GObject *obj)
+{
+	GP11Module *module = GP11_MODULE (obj);
+	CK_RV rv;
+	
+	if (module->funcs) {
+		rv = (module->funcs->C_Finalize) (NULL);
+		if (rv != CKR_OK) {
+			g_warning ("C_Finalize on module '%s' failed: %s", 
+			           module->path, gp11_message_from_rv (rv));
+		}
+		module->funcs = NULL;
+	}
+}
+
+static void
+gp11_module_finalize (GObject *obj)
+{
+	GP11ModulePrivate *pv = GP11_MODULE_GET_PRIVATE (obj);
+	GP11Module *module = GP11_MODULE (obj);
+
+	g_assert (module->funcs == NULL);
+	
+	if (pv->module) {
+		if (!g_module_close (pv->module))
+			g_warning ("failed to close the pkcs11 module: %s", 
+			           g_module_error ());
+		pv->module = NULL;
+	}
+	
+	g_free (module->path);
+	module->path = NULL;
+	
+	G_OBJECT_CLASS (gp11_module_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_module_class_init (GP11ModuleClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*)klass;
+	gp11_module_parent_class = g_type_class_peek_parent (klass);
+	
+	gobject_class->get_property = gp11_module_get_property;
+	gobject_class->set_property = gp11_module_set_property;
+	gobject_class->dispose = gp11_module_dispose;
+	gobject_class->finalize = gp11_module_finalize;
+	
+	g_object_class_install_property (gobject_class, PROP_MODULE_PATH,
+		g_param_spec_string ("module-path", "Module Path", "Path to the PKCS11 Module",
+		                     NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_type_class_add_private (gobject_class, sizeof (GP11ModulePrivate));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+void
+gp11_module_info_free (GP11ModuleInfo *module_info)
+{
+	if (!module_info)
+		return;
+	g_free (module_info->library_description);
+	g_free (module_info->manufacturer_id);
+	g_free (module_info);
+}
+
+GP11Module*
+gp11_module_initialize (const gchar *path, GError **err)
+{
+	CK_C_INITIALIZE_ARGS init_args;
+	CK_C_GetFunctionList get_function_list;
+	GP11ModulePrivate *pv;
+	GP11Module *mod;
+	CK_RV rv;
+	
+	g_return_val_if_fail (path != NULL, NULL);
+	g_return_val_if_fail (!err || !*err, NULL);
+	
+	mod = g_object_new (GP11_TYPE_MODULE, "module-path", path, NULL);
+	pv = GP11_MODULE_GET_PRIVATE (mod);
+	
+	/* Load the actual module */
+	pv->module = g_module_open (path, 0);
+	if (!pv->module) {
+		g_set_error (err, GP11_ERROR, CKR_GP11_MODULE_PROBLEM,
+		             "Error loading pkcs11 module: %s", g_module_error ());
+		g_object_unref (mod);
+		return NULL;
+	}
+	
+	/* Get the entry point */
+	if (!g_module_symbol (pv->module, "C_GetFunctionList", (void**)&get_function_list)) {
+		g_set_error (err, GP11_ERROR, CKR_GP11_MODULE_PROBLEM,
+		             "Invalid pkcs11 module: %s", g_module_error ());
+		g_object_unref (mod);
+		return NULL;
+	}
+	
+	/* Get the function list */
+	rv = (get_function_list) (&mod->funcs);
+	if (rv != CKR_OK) {
+		g_set_error (err, GP11_ERROR, rv, "Couldn't get pkcs11 function list: %s",
+		             gp11_message_from_rv (rv));
+		g_object_unref (mod);
+		return NULL;
+	}
+	
+	/* Make sure we have a compatible version */
+	if (mod->funcs->version.major != CRYPTOKI_VERSION_MAJOR) {
+		g_set_error (err, GP11_ERROR, CKR_GP11_MODULE_PROBLEM,
+		             "Incompatible version of pkcs11 module: %d.%d",
+		             (int)mod->funcs->version.major,
+		             (int)mod->funcs->version.minor);
+		g_object_unref (mod);
+		return NULL;
+	}
+	
+	memset (&init_args, 0, sizeof (init_args));
+	init_args.flags = CKF_OS_LOCKING_OK;
+	init_args.CreateMutex = create_mutex;
+	init_args.DestroyMutex = destroy_mutex;
+	init_args.LockMutex = lock_mutex;
+	init_args.UnlockMutex = unlock_mutex;
+	init_args.pReserved = NULL;
+	
+	/* Now initialize the module */
+	rv = (mod->funcs->C_Initialize) (&init_args);
+	if (rv != CKR_OK) {
+		g_set_error (err, GP11_ERROR, rv, "Couldn't initialize module: %s",
+		             gp11_message_from_rv (rv));
+		g_object_unref (mod);
+		return NULL;
+	}
+
+	return mod;
+}
+
+GP11ModuleInfo*
+gp11_module_get_info (GP11Module *module)
+{
+	GP11ModuleInfo *modinfo;
+	CK_INFO info;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_MODULE (module), NULL);
+	g_return_val_if_fail (module->funcs, NULL);
+	
+	memset (&info, 0, sizeof (info));
+	rv = (module->funcs->C_GetInfo (&info));
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get module info: %s", gp11_message_from_rv (rv));
+		return NULL;
+	}
+	
+	modinfo = g_new0 (GP11ModuleInfo, 1);
+	modinfo->flags = info.flags;
+	modinfo->library_description = gp11_string_from_chars (info.libraryDescription, 
+	                                                       sizeof (info.libraryDescription));
+	modinfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID,
+	                                                   sizeof (info.manufacturerID));
+	modinfo->library_version_major = info.libraryVersion.major;
+	modinfo->library_version_minor = info.libraryVersion.minor;
+	modinfo->pkcs11_version_major = info.cryptokiVersion.major;
+	modinfo->pkcs11_version_minor = info.cryptokiVersion.minor;
+	
+	return modinfo;
+}
+
+GList*
+gp11_module_get_slots (GP11Module *module, gboolean token_present)
+{
+	CK_SLOT_ID_PTR slot_list;
+	CK_ULONG count, i;
+	GList *result;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_MODULE (module), NULL);
+	g_return_val_if_fail (module->funcs, NULL);
+
+	rv = (module->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, NULL, &count);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get slot count: %s", gp11_message_from_rv (rv));
+		return NULL;
+	}
+	
+	if (!count)
+		return NULL;
+	
+	slot_list = g_new (CK_SLOT_ID, count);
+	rv = (module->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, slot_list, &count);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get slot list: %s", gp11_message_from_rv (rv));
+		g_free (slot_list);
+		return NULL;
+	}
+	
+	result = NULL;
+	for (i = 0; i < count; ++i) {
+		/* TODO: Should we be looking these up somewhere? */
+		result = g_list_prepend (result, g_object_new (GP11_TYPE_SLOT, 
+		                                               "handle", slot_list[i],
+		                                               "module", module, NULL));
+	}
+	
+	g_free (slot_list);
+	return g_list_reverse (result);
+}
+

Added: trunk/gp11/gp11-object.c
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-object.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,458 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <string.h>
+
+enum {
+	PROP_0,
+	PROP_MODULE,
+	PROP_SESSION,
+	PROP_HANDLE
+};
+
+G_DEFINE_TYPE (GP11Object, gp11_object, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_object_init (GP11Object *object)
+{
+	
+}
+
+static void
+gp11_object_get_property (GObject *obj, guint prop_id, GValue *value, 
+                           GParamSpec *pspec)
+{
+	GP11Object *object = GP11_OBJECT (obj);
+
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_value_set_object (value, object->module);
+		break;
+	case PROP_SESSION:
+		g_value_set_object (value, object->session);
+		break;
+	case PROP_HANDLE:
+		g_value_set_uint (value, object->handle);
+		break;
+	}
+}
+
+static void
+gp11_object_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                          GParamSpec *pspec)
+{
+	GP11Object *object = GP11_OBJECT (obj);
+	
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_return_if_fail (!object->module);
+		object->module = g_value_get_object (value);
+		g_return_if_fail (object->module);
+		g_object_ref (object->module);
+		break;
+	case PROP_SESSION:
+		g_return_if_fail (!object->session);
+		object->session = g_value_get_object (value);
+		g_return_if_fail (object->session);
+		g_object_ref (object->session);
+		break;
+	case PROP_HANDLE:
+		g_return_if_fail (!object->handle);
+		object->handle = g_value_get_uint (value);
+		break;
+	}
+}
+
+static void
+gp11_object_dispose (GObject *obj)
+{
+	GP11Object *object = GP11_OBJECT (obj);
+	
+	if (object->session)
+		g_object_unref (object->session);
+	object->session = NULL;
+	
+	if (object->module)
+		g_object_unref (object->module);
+	object->module = NULL;
+
+	G_OBJECT_CLASS (gp11_object_parent_class)->dispose (obj);
+}
+
+static void
+gp11_object_finalize (GObject *obj)
+{
+	GP11Object *object = GP11_OBJECT (obj);
+
+	g_assert (object->session == NULL);
+	g_assert (object->module == NULL);
+	object->handle = 0;
+	
+	G_OBJECT_CLASS (gp11_object_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_object_class_init (GP11ObjectClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*)klass;
+	gp11_object_parent_class = g_type_class_peek_parent (klass);
+	
+	gobject_class->get_property = gp11_object_get_property;
+	gobject_class->set_property = gp11_object_set_property;
+	gobject_class->dispose = gp11_object_dispose;
+	gobject_class->finalize = gp11_object_finalize;
+	
+	g_object_class_install_property (gobject_class, PROP_MODULE,
+		g_param_spec_object ("module", "Module", "PKCS11 Module",
+		                     GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_SESSION,
+		g_param_spec_object ("session", "Session", "PKCS11 Session",
+		                     GP11_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_HANDLE,
+		g_param_spec_uint ("handle", "Object Handle", "PKCS11 Object Handle",
+		                   0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+GP11Object*
+gp11_object_from_handle (GP11Session *session, CK_OBJECT_HANDLE handle)
+{
+	g_return_val_if_fail (GP11_IS_SESSION (session), NULL);
+	return g_object_new (GP11_TYPE_OBJECT, "module", session->module, "handle", handle, "session", session, NULL);
+}
+
+/* DESTROY */
+
+typedef struct _Destroy {
+	GP11Arguments base;
+	CK_OBJECT_HANDLE object;
+} Destroy;
+
+static CK_RV
+perform_destroy (Destroy *args)
+{
+	return (args->base.pkcs11->C_DestroyObject) (args->base.handle, args->object);
+}
+
+gboolean
+gp11_object_destroy (GP11Object *object, GError **err)
+{
+	return gp11_object_destroy_full (object, NULL, err);
+}
+
+gboolean
+gp11_object_destroy_full (GP11Object *object, GCancellable *cancellable, GError **err)
+{
+	Destroy args = { GP11_ARGUMENTS_INIT, 0 };
+	g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+	g_return_val_if_fail (GP11_IS_SESSION (object->session), FALSE);
+	args.object = object->handle;
+	return _gp11_call_sync (object->session, perform_destroy, &args, cancellable, err);
+}
+
+void
+gp11_object_destroy_async (GP11Object *object, GCancellable *cancellable,
+                           GAsyncReadyCallback callback, gpointer user_data)
+{
+	Destroy* args;
+
+	g_return_if_fail (GP11_IS_OBJECT (object));
+	g_return_if_fail (GP11_IS_SESSION (object->session));
+
+	args = _gp11_call_async_prep (object->session, perform_destroy, sizeof (*args), NULL);
+	args->object = object->handle;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_object_destroy_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+	return _gp11_call_basic_finish (object, result, err);
+}
+
+typedef struct _SetAttributes {
+	GP11Arguments base;
+	GP11Attributes *attrs;
+	CK_OBJECT_HANDLE object;
+} SetAttributes;
+
+static void
+free_set_attributes (SetAttributes *args)
+{
+	gp11_attributes_unref (args->attrs);
+	g_free (args);
+}
+
+static CK_RV
+perform_set_attributes (SetAttributes *args)
+{
+	return (args->base.pkcs11->C_SetAttributeValue) (args->base.handle, args->object, 
+	                                                 _gp11_attributes_raw (args->attrs),
+	                                                 gp11_attributes_count (args->attrs));
+}
+
+gboolean
+gp11_object_set (GP11Object *object, GError **err, ...)
+{
+	GP11Attributes *attrs;
+	va_list va;
+	CK_RV rv;
+	
+	va_start (va, err);
+	attrs = gp11_attributes_new_valist (va);
+	va_end (va);
+	
+	rv = gp11_object_set_full (object, attrs, NULL, err);
+	
+	gp11_attributes_unref (attrs);
+	return rv;
+}
+
+gboolean
+gp11_object_set_full (GP11Object *object, GP11Attributes *attrs,
+                      GCancellable *cancellable, GError **err)
+{
+	SetAttributes args;
+	
+	g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+	
+	memset (&args, 0, sizeof (args));
+	args.attrs = attrs;
+	args.object = object->handle;
+
+	return _gp11_call_sync (object->session, perform_set_attributes, &args, cancellable, err);
+}
+
+void
+gp11_object_set_async (GP11Object *object, GP11Attributes *attrs, GCancellable *cancellable,
+                       GAsyncReadyCallback callback, gpointer user_data)
+{
+	SetAttributes *args;
+
+	g_return_if_fail (GP11_IS_OBJECT (object));
+
+	args = _gp11_call_async_prep (object->session, perform_set_attributes, 
+	                              sizeof (*args), free_set_attributes);
+	args->attrs = attrs;
+	gp11_attributes_ref (attrs);
+	args->object = object->handle;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_object_set_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+	return _gp11_call_basic_finish (object, result, err);
+}
+
+typedef struct _GetAttributes {
+	GP11Arguments base;
+	guint *attr_types;
+	gsize n_attr_types;
+	CK_OBJECT_HANDLE object;
+	GP11Attributes *results;
+} GetAttributes;
+
+static void
+free_get_attributes (GetAttributes *args)
+{
+	g_free (args->attr_types);
+	if (args->results)
+		gp11_attributes_unref (args->results);
+	g_free (args);
+}
+
+static CK_RV
+perform_get_attributes (GetAttributes *args)
+{
+	CK_ATTRIBUTE_PTR attrs;
+	CK_ULONG i, n_attrs;
+	CK_RV rv;
+	
+	/* Allocate the CK_ATTRIBUTE's */
+	n_attrs = args->n_attr_types;
+	if (n_attrs) {
+		attrs = g_new0 (CK_ATTRIBUTE, n_attrs);
+		for (i = 0; i < n_attrs; ++i)
+			attrs[i].type = args->attr_types[i];
+	} else {
+		attrs = NULL;
+	}
+
+	/* Get the size of each value */
+	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
+	                                               attrs, n_attrs);
+	if (rv != CKR_OK) {
+		g_free (attrs);
+		return rv;
+	}
+	
+	/* Allocate memory for each value */
+	for (i = 0; i < n_attrs; ++i) {
+		if (attrs[i].ulValueLen > 0 && attrs[i].ulValueLen != (CK_ULONG)-1)
+			attrs[i].pValue = g_malloc0 (attrs[i].ulValueLen);
+	}
+	
+	/* Now get the actual values */
+	rv = (args->base.pkcs11->C_GetAttributeValue) (args->base.handle, args->object,
+	                                               attrs, n_attrs);
+	
+	/* Transfer over the memory to the results */
+	if (rv == CKR_OK) {
+		g_assert (!args->results);
+		args->results = gp11_attributes_new ();
+		for (i = 0; i < n_attrs; ++i) {
+			_gp11_attributes_add_take (args->results, attrs[i].type,
+			                           attrs[i].pValue, attrs[i].ulValueLen);
+			memset (&attrs[i], 0, sizeof (attrs[0]));
+		}
+	}
+
+	/* Free any memory we didn't use */
+	for (i = 0; i < n_attrs; ++i)
+		g_free (attrs[i].pValue);
+	g_free (attrs);
+	return rv;
+}
+
+GP11Attributes*
+gp11_object_get (GP11Object *object, GError **err, ...)
+{
+	GP11Attributes *result;
+	GArray *array;
+	va_list va;
+	guint type;
+	
+	array = g_array_new (0, 1, sizeof (guint));
+	va_start (va, err);
+	for (;;) {
+		type = va_arg (va, guint);
+		if (type == (guint)-1)
+			break;
+		g_array_append_val (array, type);
+	}
+	va_end (va);
+	
+	result = gp11_object_get_full (object, (guint*)array->data, array->len, NULL, err);
+	g_array_free (array, TRUE);
+	return result;
+}
+
+GP11Attributes*
+gp11_object_get_full (GP11Object *object, guint *attr_types, gsize n_attr_types,
+                      GCancellable *cancellable, GError **err)
+{
+	GetAttributes args;
+	
+	g_return_val_if_fail (GP11_IS_OBJECT (object), FALSE);
+	
+	memset (&args, 0, sizeof (args));
+	args.attr_types = attr_types;
+	args.n_attr_types = n_attr_types;
+	args.object = object->handle;
+
+	if (!_gp11_call_sync (object->session, perform_get_attributes, &args, cancellable, err)) {
+		gp11_attributes_unref (args.results);
+		return NULL;
+	}
+	
+	return args.results;
+}
+
+void
+gp11_object_get_async (GP11Object *object, guint *attr_types, gsize n_attr_types,
+                       GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
+{
+	GetAttributes *args;
+
+	g_return_if_fail (GP11_IS_OBJECT (object));
+
+	args = _gp11_call_async_prep (object->session, perform_get_attributes, 
+	                              sizeof (*args), free_get_attributes);
+	args->n_attr_types = n_attr_types;
+	if (n_attr_types)
+		args->attr_types = g_memdup (attr_types, sizeof (guint) * n_attr_types);
+	args->object = object->handle;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GP11Attributes*
+gp11_object_get_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+	GP11Attributes *results;
+	GetAttributes *args;
+	
+	if (!_gp11_call_basic_finish (object, result, err))
+		return NULL;
+	
+	args = _gp11_call_arguments (result, GetAttributes);
+	
+	results = args->results;
+	args->results = NULL;
+	
+	return results;
+}
+
+GP11Attribute*
+gp11_object_get_one (GP11Object *object, guint attr_type, GError **err)
+{
+	return gp11_object_get_one_full (object, attr_type, NULL, err);
+}
+
+GP11Attribute*
+gp11_object_get_one_full (GP11Object *object, guint attr_type, 
+                          GCancellable *cancellable, GError **err)
+{
+	GP11Attributes *attrs;
+	GP11Attribute *attr;
+	
+	attrs = gp11_object_get_full (object, &attr_type, 1, cancellable, err);
+	if (!attrs || !gp11_attributes_count (attrs))
+		return NULL;
+	
+	attr = gp11_attributes_at (attrs, 0);
+	g_return_val_if_fail (attr, NULL);
+	attr = gp11_attribute_dup (attr);
+	gp11_attributes_unref (attrs);
+	return attr;
+}
+
+void
+gp11_object_get_one_async (GP11Object *object, guint attr_type, GCancellable *cancellable,
+                           GAsyncReadyCallback callback, gpointer user_data)
+{
+	gp11_object_get_async (object, &attr_type, 1, cancellable, callback, user_data);
+}
+
+GP11Attribute*
+gp11_object_get_one_finish (GP11Object *object, GAsyncResult *result, GError **err)
+{
+	GP11Attributes *attrs;
+	GP11Attribute *attr;
+	
+	attrs = gp11_object_get_finish (object, result, err);
+	if (!attrs)
+		return NULL;
+	
+	attr = gp11_attributes_at (attrs, 0);
+	g_return_val_if_fail (attr, NULL);
+	attr = gp11_attribute_dup (attr);
+	gp11_attributes_unref (attrs);
+	return attr;
+}

Added: trunk/gp11/gp11-private.h
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-private.h	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,99 @@
+#ifndef GP11_PRIVATE_H_
+#define GP11_PRIVATE_H_
+
+#include "gp11.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+void                _gp11_attribute_init_take               (GP11Attribute *attr, 
+                                                             guint attr_type,
+                                                             gpointer value,
+                                                             gsize length);
+
+void                _gp11_attributes_add_take               (GP11Attributes *attr, 
+                                                             guint attr_type,
+                                                             gpointer value,
+                                                             gsize length);
+
+CK_ATTRIBUTE_PTR    _gp11_attributes_raw                    (GP11Attributes *attrs);
+
+/* ----------------------------------------------------------------------------
+ * CALL
+ */
+
+typedef CK_RV (*GP11CallFunc) (gpointer call_data); 
+
+typedef struct _GP11Call GP11Call;
+
+typedef struct _GP11Arguments {
+	GP11Call *call;
+	
+	/* For the call function to use */
+	CK_FUNCTION_LIST_PTR pkcs11;
+	CK_ULONG handle;
+	
+} GP11Arguments;
+
+#define GP11_ARGUMENTS_INIT 	{ NULL, NULL, 0 }
+
+#define GP11_TYPE_CALL             (_gp11_call_get_type())
+#define GP11_CALL(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_CALL, GP11Call))
+#define GP11_CALL_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_CALL, GP11Call))
+#define GP11_IS_CALL(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_CALL))
+#define GP11_IS_CALL_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_CALL))
+#define GP11_CALL_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_CALL, GP11CallClass))
+
+typedef struct _GP11CallClass GP11CallClass;
+
+struct _GP11Call {
+	GObject parent;
+	
+	/* For making the call */
+	GP11CallFunc func;
+	GP11Arguments *args;
+	GCancellable *cancellable;
+	GDestroyNotify destroy;
+	CK_RV rv;
+	
+	/* For result callback only */
+	gpointer object;
+	GAsyncReadyCallback callback;
+	gpointer user_data;
+};
+
+struct _GP11CallClass {
+	GObjectClass parent;
+};
+
+GType              _gp11_call_get_type                    (void) G_GNUC_CONST;
+
+#define            _gp11_call_arguments(call, type) \
+			(type*)(GP11_CALL (call)->args)
+
+void               _gp11_call_uninitialize                (void);
+
+gboolean           _gp11_call_sync                        (gpointer object, 
+                                                           gpointer func, 
+                                                           gpointer args, 
+                                                           GCancellable *cancellable, 
+                                                           GError **err);
+
+gpointer           _gp11_call_async_prep                  (gpointer object, 
+                                                           gpointer func, 
+                                                           gsize args_size,
+                                                           gpointer destroy_func);
+
+void               _gp11_call_async_go                    (gpointer args, 
+                                                           GCancellable *cancellable, 
+                                                           GAsyncReadyCallback callback, 
+                                                           gpointer user_data);
+
+gboolean           _gp11_call_basic_finish                (gpointer object,
+                                                           GAsyncResult *result,
+                                                           GError **err);
+
+#endif /* GP11_PRIVATE_H_ */

Added: trunk/gp11/gp11-session.c
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-session.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,864 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <string.h>
+
+enum {
+	PROP_0,
+	PROP_MODULE,
+	PROP_HANDLE
+};
+
+G_DEFINE_TYPE (GP11Session, gp11_session, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_session_init (GP11Session *session)
+{
+	
+}
+
+static void
+gp11_session_get_property (GObject *obj, guint prop_id, GValue *value, 
+                           GParamSpec *pspec)
+{
+	GP11Session *session = GP11_SESSION (obj);
+
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_value_set_object (value, session->module);
+		break;
+	case PROP_HANDLE:
+		g_value_set_uint (value, session->handle);
+		break;
+	}
+}
+
+static void
+gp11_session_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                        GParamSpec *pspec)
+{
+	GP11Session *session = GP11_SESSION (obj);
+
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_return_if_fail (!session->module);
+		session->module = g_value_dup_object (value);
+		g_return_if_fail (session->module);
+		break;
+	case PROP_HANDLE:
+		g_return_if_fail (!session->handle);
+		session->handle = g_value_get_uint (value);
+		break;
+	}
+}
+
+static void
+gp11_session_dispose (GObject *obj)
+{
+	GP11Session *session = GP11_SESSION (obj);
+	CK_RV rv;
+	
+	if (session->handle) {
+		g_return_if_fail (session->module && session->module->funcs);
+		rv = (session->module->funcs->C_CloseSession) (session->handle);
+		if (rv != CKR_OK) {
+			g_warning ("couldn't close session properly: %s",
+			           gp11_message_from_rv (rv));
+		}
+		session->handle = 0;
+	}
+	
+	if (session->module)
+		g_object_unref (session->module);
+	session->module = NULL;
+
+	G_OBJECT_CLASS (gp11_session_parent_class)->dispose (obj);
+}
+
+static void
+gp11_session_finalize (GObject *obj)
+{
+	GP11Session *session = GP11_SESSION (obj);
+
+	g_assert (session->module == NULL);
+	g_assert (session->handle == 0);
+	
+	G_OBJECT_CLASS (gp11_session_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_session_class_init (GP11SessionClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*)klass;
+	gp11_session_parent_class = g_type_class_peek_parent (klass);
+	
+	gobject_class->get_property = gp11_session_get_property;
+	gobject_class->set_property = gp11_session_set_property;
+	gobject_class->dispose = gp11_session_dispose;
+	gobject_class->finalize = gp11_session_finalize;
+	
+	g_object_class_install_property (gobject_class, PROP_MODULE,
+		g_param_spec_object ("module", "Module", "PKCS11 Module",
+		                     GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_HANDLE,
+		g_param_spec_uint ("handle", "Session Handle", "PKCS11 Session Handle",
+		                   0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+void
+gp11_session_info_free (GP11SessionInfo *session_info)
+{
+	if (!session_info)
+		return;
+	g_free (session_info);
+}
+
+GP11Session*
+gp11_session_from_handle (GP11Slot *slot, CK_SESSION_HANDLE handle)
+{
+	g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+	return g_object_new (GP11_TYPE_SESSION, "module", slot->module, "handle", handle, NULL);
+}
+
+GP11SessionInfo*
+gp11_session_get_info (GP11Session *session)
+{
+	GP11SessionInfo *sessioninfo;
+	CK_SESSION_INFO info;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_SESSION (session), NULL);
+	g_return_val_if_fail (GP11_IS_MODULE (session->module), NULL);
+	g_return_val_if_fail (session->module->funcs, NULL);
+	
+	memset (&info, 0, sizeof (info));
+	rv = (session->module->funcs->C_GetSessionInfo) (session->handle, &info);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get session info: %s", gp11_message_from_rv (rv));
+		return NULL;
+	}
+	
+	sessioninfo = g_new0 (GP11SessionInfo, 1);
+	sessioninfo->flags = info.flags;
+	sessioninfo->slot_id = info.slotID;
+	sessioninfo->state = info.state;
+	sessioninfo->device_error = info.ulDeviceError;
+
+	return sessioninfo;
+}
+
+
+
+/* LOGIN */
+
+typedef struct _Login {
+	GP11Arguments base;
+	guint32 user_type;
+	guchar *pin;
+	gsize n_pin;
+} Login;
+
+static void
+free_login (Login *args)
+{
+	g_free (args->pin);
+	g_free (args);
+}
+
+static CK_RV
+perform_login (Login *args)
+{
+	return (args->base.pkcs11->C_Login) (args->base.handle, args->user_type,
+	                                     (CK_BYTE_PTR)args->pin, args->n_pin);
+}
+
+gboolean
+gp11_session_login (GP11Session *session, guint32 user_type, const guchar *pin,
+                    gsize n_pin, GError **err)
+{
+	return gp11_session_login_full (session, user_type, pin, n_pin, NULL, err);
+}
+
+gboolean
+gp11_session_login_full (GP11Session *session, guint32 user_type, const guchar *pin,
+                         gsize n_pin, GCancellable *cancellable, GError **err)
+{
+	Login args = { GP11_ARGUMENTS_INIT, user_type, (guchar*)pin, n_pin };
+	return _gp11_call_sync (session, perform_login, &args, cancellable, err);
+	
+}
+
+void
+gp11_session_login_async (GP11Session *session, guint32 user_type, const guchar *pin,
+                          gsize n_pin, GCancellable *cancellable, GAsyncReadyCallback callback,
+                          gpointer user_data)
+{
+	Login* args = _gp11_call_async_prep (session, perform_login, sizeof (*args), free_login);
+	
+	args->user_type = user_type;
+	args->pin = pin && n_pin ? g_memdup (pin, n_pin) : NULL;
+	args->n_pin = n_pin;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+
+}
+
+gboolean
+gp11_session_login_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+	return _gp11_call_basic_finish (session, result, err);
+}
+
+
+
+
+/* LOGOUT */
+
+static CK_RV
+perform_logout (GP11Arguments *args)
+{
+	return (args->pkcs11->C_Logout) (args->handle);
+}
+
+gboolean
+gp11_session_logout (GP11Session *session, GError **err)
+{
+	return gp11_session_logout_full (session, NULL, err);
+}
+
+gboolean
+gp11_session_logout_full (GP11Session *session, GCancellable *cancellable, GError **err)
+{
+	GP11Arguments args = GP11_ARGUMENTS_INIT;
+	return _gp11_call_sync (session, perform_logout, &args, cancellable, err);	
+}
+
+void
+gp11_session_logout_async (GP11Session *session, GCancellable *cancellable,
+                           GAsyncReadyCallback callback, gpointer user_data)
+{
+	GP11Arguments *args = _gp11_call_async_prep (session, perform_logout, 0, NULL);
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_session_logout_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+	return _gp11_call_basic_finish (session, result, err);
+}
+
+
+
+
+/* CREATE OBJECT */
+
+typedef struct _CreateObject {
+	GP11Arguments base;
+	GP11Attributes *attrs;
+	CK_OBJECT_HANDLE object;
+} CreateObject;
+
+static void
+free_create_object (CreateObject *args)
+{
+	gp11_attributes_unref (args->attrs);
+	g_free (args);
+}
+
+static CK_RV
+perform_create_object (CreateObject *args)
+{
+	return (args->base.pkcs11->C_CreateObject) (args->base.handle, 
+	                                            _gp11_attributes_raw (args->attrs),
+	                                            gp11_attributes_count (args->attrs),
+	                                            &args->object);
+}
+
+GP11Object*
+gp11_session_create_object (GP11Session *session, GError **err, ...)
+{
+	GP11Attributes *attrs;
+	GP11Object *object;
+	va_list va;
+	
+	va_start (va, err);
+	attrs = gp11_attributes_new_valist (va);
+	va_end (va);
+	
+	object = gp11_session_create_object_full (session, attrs, NULL, err);
+	gp11_attributes_unref (attrs);
+	return object;
+}
+
+GP11Object*
+gp11_session_create_object_full (GP11Session *session, GP11Attributes *attrs,
+                                 GCancellable *cancellable, GError **err)
+{
+	CreateObject args = { GP11_ARGUMENTS_INIT, attrs, 0 };
+	if (!_gp11_call_sync (session, perform_create_object, &args, cancellable, err))
+		return NULL;
+	return gp11_object_from_handle (session, args.object);
+}
+
+void
+gp11_session_create_object_async (GP11Session *session, GP11Attributes *attrs,
+                                  GCancellable *cancellable, GAsyncReadyCallback callback, 
+                                  gpointer user_data)
+{
+	CreateObject *args = _gp11_call_async_prep (session, perform_create_object, 
+	                                            sizeof (*args), free_create_object);
+	args->attrs = attrs;
+	gp11_attributes_ref (attrs);
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GP11Object*
+gp11_session_create_object_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+	CreateObject *args;
+	
+	if (!_gp11_call_basic_finish (session, result, err))
+		return NULL;
+	args = _gp11_call_arguments (result, CreateObject);
+	return gp11_object_from_handle (session, args->object);
+}
+
+
+
+/* FIND OBJECTS */
+
+typedef struct _FindObjects {
+	GP11Arguments base;
+	GP11Attributes *attrs;
+	CK_OBJECT_HANDLE_PTR objects;
+	CK_ULONG n_objects;
+} FindObjects;
+
+static void
+free_find_objects (FindObjects *args)
+{
+	gp11_attributes_unref (args->attrs);
+	g_free (args->objects);
+}
+
+static CK_RV
+perform_find_objects (FindObjects *args)
+{
+	CK_OBJECT_HANDLE_PTR batch;
+	CK_ULONG n_batch, n_found;
+	GArray *array;
+	CK_RV rv;
+	
+	rv = (args->base.pkcs11->C_FindObjectsInit) (args->base.handle, 
+	                                             _gp11_attributes_raw (args->attrs),
+	                                             gp11_attributes_count (args->attrs));
+	if (rv != CKR_OK)
+		return rv;
+	
+	batch = NULL;
+	n_found = n_batch = 4;
+	array = g_array_new (0, 1, sizeof (CK_OBJECT_HANDLE));
+	
+	do {
+		/* 
+		 * Reallocate and double in size: 
+		 *  - First time.
+		 *  - Each time we found as many as batch
+		 */
+		
+		if (n_found == n_batch) {
+			n_batch *= 2;
+			batch = g_realloc (batch, sizeof (CK_OBJECT_HANDLE) * n_batch);
+		}
+
+		rv = (args->base.pkcs11->C_FindObjects) (args->base.handle,
+		                                         batch, n_batch, &n_found);
+		if (rv != CKR_OK)
+			break;
+		
+		g_array_append_vals (array, batch, n_found);
+		
+	} while (n_found > 0);
+	
+	g_free (batch);
+	
+	if (rv == CKR_OK) {
+		args->n_objects = array->len;
+		args->objects = (CK_OBJECT_HANDLE_PTR)g_array_free (array, FALSE);
+		rv = (args->base.pkcs11->C_FindObjectsFinal) (args->base.handle);
+	} else {
+		args->objects = NULL;
+		args->n_objects = 0;
+		g_array_free (array, TRUE);
+	}
+	
+	return rv;
+}
+
+static GList*
+objlist_from_handles (GP11Session *session, CK_OBJECT_HANDLE_PTR objects, 
+                      CK_ULONG n_objects)
+{
+	GList *results = NULL;
+	
+	while (n_objects > 0) {
+		results = g_list_prepend (results, 
+		                gp11_object_from_handle (session, objects[--n_objects]));
+	}
+	
+	return g_list_reverse (results);
+}
+
+GList*
+gp11_session_find_objects (GP11Session *session, GError **err, ...)
+{
+	GP11Attributes *attrs;
+	GList *results;
+	va_list va;
+	
+	va_start (va, err);
+	attrs = gp11_attributes_new_valist (va);
+	va_end (va);
+
+	results = gp11_session_find_objects_full (session, attrs, NULL, err);
+	gp11_attributes_unref (attrs);
+	return results;
+}
+
+GList*
+gp11_session_find_objects_full (GP11Session *session, GP11Attributes *attrs, 
+                                GCancellable *cancellable, GError **err)
+{
+	FindObjects args = { GP11_ARGUMENTS_INIT, attrs, NULL, 0 };
+	GList *results = NULL;
+	
+	if (_gp11_call_sync (session, perform_find_objects, &args, cancellable, err)) 
+		results = objlist_from_handles (session, args.objects, args.n_objects);
+	g_free (args.objects);
+	return results;
+}
+	
+void
+gp11_session_find_objects_async (GP11Session *session, GP11Attributes *attrs, 
+                                 GCancellable *cancellable, GAsyncReadyCallback callback, 
+                                 gpointer user_data)
+{
+	FindObjects *args = _gp11_call_async_prep (session, perform_find_objects, 
+	                                           sizeof (*args), free_find_objects);
+	args->attrs = attrs;
+	gp11_attributes_ref (attrs);
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GList*
+gp11_session_find_objects_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+	FindObjects *args;
+	
+	if (!_gp11_call_basic_finish (session, result, err))
+		return NULL;
+	args = _gp11_call_arguments (result, FindObjects);
+	return objlist_from_handles (session, args->objects, args->n_objects);
+}
+
+
+#if UNTESTED 
+
+/* ENCRYPT */
+
+
+typedef struct _Crypt {
+	GP11Arguments base;
+	
+	/* Functions to call */
+	CK_C_EncryptInit init_func;
+	CK_C_Encrypt complete_func;
+	
+	/* Input */
+	CK_OBJECT_HANDLE key;
+	CK_MECHANISM mech;
+	guchar *input;
+	CK_ULONG n_input;
+	
+	/* Output */
+	guchar *result;
+	CK_ULONG n_result;
+} Crypt;
+
+static void
+free_crypt (Crypt *args)
+{
+	g_free (args->input);
+	g_free (args->mech.pParameter);
+	g_free (args->result);
+}
+
+static CK_RV
+perform_crypt (Crypt *args)
+{
+	CK_RV rv;
+	
+	g_assert (args);
+	g_assert (args->init_func);
+	g_assert (args->complete_func);
+	g_assert (!args->result);
+	g_assert (!args->n_result);
+	
+	/* Initialize the crypt operation */
+	rv = (args->init_func) (args->base.handle, &args->mech, args->key);
+	if (rv != CKR_OK)
+		return rv;
+	
+	/* Get the length of the result */
+	rv = (args->complete_func) (args->base.handle, args->input, args->n_input, NULL, &args->n_result);
+	if (rv != CKR_OK)
+		return rv;
+	
+	/* And try again with a real buffer */
+	args->result = g_malloc0 (args->n_result);
+	return (args->complete_func) (args->base.handle, args->input, args->n_input, args->result, &args->n_result);
+}
+
+static guchar*
+crypt_sync (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, 
+            gsize n_input, gsize *n_result, GCancellable *cancellable, GError **err,
+            CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
+{
+	Crypt args;
+	
+	g_return_val_if_fail (GP11_IS_OBJECT (key), NULL);
+	g_return_val_if_fail (mech_args, NULL);
+	g_return_val_if_fail (init_func, NULL);
+	g_return_val_if_fail (complete_func, NULL);
+
+	memset (&args, 0, sizeof (args));
+	g_object_get (key, "handle", &args.key, NULL);
+	g_return_val_if_fail (args.key != 0, NULL);
+	
+	args.mech.mechanism = mech_args->type;
+	args.mech.pParameter = mech_args->parameter;
+	args.mech.ulParameterLen = mech_args->n_parameter;
+	
+	/* No need to copy in this case */
+	args.input = (guchar*)input;
+	args.n_input = n_input;
+	
+	args.init_func = init_func;
+	args.complete_func = complete_func;
+	
+	if (!_gp11_call_sync (session, perform_crypt, &args, cancellable, err)) {
+		g_free (args.result);
+		return NULL;
+	}
+	
+	return args.result;
+}
+
+static void
+crypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args, const guchar *input, 
+             gsize n_input, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data,
+             CK_C_EncryptInit init_func, CK_C_Encrypt complete_func)
+{
+	Crypt *args = _gp11_call_async_prep (session, perform_crypt, sizeof (*args), free_crypt);
+
+	g_return_if_fail (GP11_IS_OBJECT (key));
+	g_return_if_fail (mech_args);
+	g_return_if_fail (init_func);
+	g_return_if_fail (complete_func);
+	
+	g_object_get (key, "handle", &args->key, NULL);
+	g_return_if_fail (args->key != 0);
+
+	args->mech.mechanism = mech_args->type;
+	args->mech.pParameter = mech_args->parameter && mech_args->n_parameter ? 
+	                                   g_memdup (mech_args->parameter, mech_args->n_parameter) : NULL;
+	args->mech.ulParameterLen = mech_args->n_parameter;
+	
+	args->input = input && n_input ? g_memdup (input, n_input) : NULL;
+	args->n_input = n_input;
+	
+	args->init_func = init_func;
+	args->complete_func = complete_func;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+static guchar*
+crypt_finish (GP11Session *session, GAsyncResult *result, gsize *n_result, GError **err)
+{
+	Crypt *args;
+	guchar *res;
+	
+	if (!_gp11_call_basic_finish (session, result, err))
+		return NULL;
+	args = _gp11_call_arguments (result, Crypt);
+	
+	/* Steal the values from the results */
+	res = args->result;
+	args->result = NULL;
+	*n_result = args->n_result;
+	args->n_result = 0;
+	
+	return res;
+}
+
+guchar*
+gp11_session_encrypt (GP11Session *session, GP11Object *key, guint mech, const guchar *input, 
+                      gsize n_input, gsize *n_result, GError **err)
+{
+	GP11Mechanism mech_args = { mech, NULL, 0 };
+	return gp11_session_encrypt_full (session, key, &mech_args, input, n_input, n_result, NULL, err);
+}
+
+guchar*
+gp11_session_encrypt_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                           const guchar *input, gsize n_input, gsize *n_result,
+                           GCancellable *cancellable, GError **err)
+{
+	GP11Module *module = NULL;
+	guchar *ret;
+	
+	g_object_get (session, "module", &module, NULL);
+	g_return_val_if_fail (module != NULL, NULL);
+
+	ret = crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err, 
+	                  module->funcs->C_EncryptInit, module->funcs->C_Encrypt);
+	
+	g_object_unref (module);
+	return ret;
+}
+
+void
+gp11_session_encrypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                            const guchar *input, gsize n_input, GCancellable *cancellable,
+                            GAsyncReadyCallback callback, gpointer user_data)
+{
+	GP11Module *module = NULL;
+	g_object_get (session, "module", &module, NULL);
+	g_return_if_fail (module != NULL);
+
+	crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data,
+	             module->funcs->C_EncryptInit, module->funcs->C_Encrypt);
+	
+	g_object_unref (module);
+}
+
+guchar*
+gp11_session_encrypt_finish (GP11Session *session, GAsyncResult *result, gsize *n_result,
+                             GError **err)
+{
+	return crypt_finish (session, result, n_result, err);
+}
+
+guchar*
+gp11_session_decrypt (GP11Session *session, GP11Object *key, guint mech_type, const guchar *input,
+                      gsize n_input, gsize *n_result, GError **err)
+{
+	GP11Mechanism mech_args = { mech_type, NULL, 0 };
+	return gp11_session_decrypt_full (session, key, &mech_args, input, n_input, n_result, NULL, err);
+}
+
+guchar*
+gp11_session_decrypt_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                           const guchar *input, gsize n_input, gsize *n_result,
+                           GCancellable *cancellable, GError **err)
+{
+	GP11Module *module = NULL;
+	guchar *ret;
+	
+	g_object_get (session, "module", &module, NULL);
+	g_return_val_if_fail (module != NULL, NULL);
+
+	ret = crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err,
+	                  module->funcs->C_DecryptInit, module->funcs->C_Decrypt);
+	g_object_unref (module);
+	return ret;
+}
+
+void
+gp11_session_decrypt_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                            const guchar *input, gsize n_input, GCancellable *cancellable,
+                            GAsyncReadyCallback callback, gpointer user_data)
+{
+	GP11Module *module = NULL;
+	g_object_get (session, "module", &module, NULL);
+	g_return_if_fail (module != NULL);
+
+	crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data,
+	             module->funcs->C_DecryptInit, module->funcs->C_Decrypt);
+	g_object_unref (module);
+}
+
+guchar*
+gp11_session_decrypt_finish (GP11Session *session, GAsyncResult *result,
+                             gsize *n_result, GError **err)
+{
+	return crypt_finish (session, result, n_result, err);
+}
+
+guchar*
+gp11_session_sign (GP11Session *session, GP11Object *key, guint mech_type, const guchar *input, 
+                   gsize n_input, gsize *n_result, GError **err)
+{
+	GP11Mechanism mech_args = { mech_type, NULL, 0 };
+	return gp11_session_sign_full (session, key, &mech_args, input, n_input, n_result, NULL, err);
+}
+
+guchar*
+gp11_session_sign_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                        const guchar *input, gsize n_input, gsize *n_result,
+                        GCancellable *cancellable, GError **err)
+{
+	GP11Module *module = NULL;
+	guchar *ret;
+	
+	g_object_get (session, "module", &module, NULL);
+	g_return_val_if_fail (module != NULL, NULL);
+
+	return crypt_sync (session, key, mech_args, input, n_input, n_result, cancellable, err,
+	                   module->funcs->C_SignInit, module->funcs->C_Sign);
+	g_object_unref (module);
+	return ret;
+}
+
+void
+gp11_session_sign_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                         const guchar *input, gsize n_input, GCancellable *cancellable,
+                         GAsyncReadyCallback callback, gpointer user_data)
+{
+	GP11Module *module = NULL;
+	g_object_get (session, "module", &module, NULL);
+	g_return_if_fail (module != NULL);
+
+	crypt_async (session, key, mech_args, input, n_input, cancellable, callback, user_data,
+	             module->funcs->C_SignInit, module->funcs->C_Sign);
+	g_object_unref (module);
+}
+
+guchar*
+gp11_session_sign_finish (GP11Session *session, GAsyncResult *result, 
+                          gsize *n_result, GError **err)
+{
+	return crypt_finish (session, result, n_result, err);	
+}
+
+
+typedef struct _Verify {
+	GP11Arguments base;
+	
+	/* Input */
+	CK_OBJECT_HANDLE key;
+	CK_MECHANISM mech;
+	guchar *input;
+	CK_ULONG n_input;
+	guchar *signature;
+	CK_ULONG n_signature;
+	
+} Verify;
+
+static void
+free_verify (Verify *args)
+{
+	g_free (args->input);
+	g_free (args->signature);
+	g_free (args->mech.pParameter);
+}
+
+static CK_RV
+perform_verify (Verify *args)
+{
+	CK_RV rv;
+	
+	/* Initialize the crypt operation */
+	rv = (args->base.pkcs11->C_VerifyInit) (args->base.handle, &args->mech, args->key);
+	if (rv != CKR_OK)
+		return rv;
+	
+	/* Do the actual verify */
+	return (args->base.pkcs11->C_Verify) (args->base.handle, args->input, args->n_input, 
+	                                      args->signature, args->n_signature);
+}
+
+gboolean
+gp11_session_verify (GP11Session *session, GP11Object *key, guint mech_type, const guchar *input,
+                     gsize n_input, const guchar *signature, gsize n_signature, GError **err)
+{
+	GP11Mechanism mech_args = { mech_type, NULL, 0 };
+	return gp11_session_verify_full (session, key, &mech_args, input, n_input, 
+	                                 signature, n_signature, NULL, err);	
+}
+
+gboolean
+gp11_session_verify_full (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                          const guchar *input, gsize n_input, const guchar *signature,
+                          gsize n_signature, GCancellable *cancellable, GError **err)
+{
+	Verify args;
+	
+	g_return_val_if_fail (GP11_IS_OBJECT (key), FALSE);
+	g_return_val_if_fail (mech_args, FALSE);
+
+	memset (&args, 0, sizeof (args));
+	g_object_get (key, "handle", &args.key, NULL);
+	g_return_val_if_fail (args.key != 0, FALSE);
+	
+	args.mech.mechanism = mech_args->type;
+	args.mech.pParameter = mech_args->parameter;
+	args.mech.ulParameterLen = mech_args->n_parameter;
+	
+	/* No need to copy in this case */
+	args.input = (guchar*)input;
+	args.n_input = n_input;
+	args.signature = (guchar*)signature;
+	args.n_signature = n_signature;
+
+	return _gp11_call_sync (session, perform_verify, &args, cancellable, err);
+}
+
+void
+gp11_session_verify_async (GP11Session *session, GP11Object *key, GP11Mechanism *mech_args,
+                           const guchar *input, gsize n_input, const guchar *signature,
+                           gsize n_signature, GCancellable *cancellable,
+                           GAsyncReadyCallback callback, gpointer user_data)
+{
+	Verify *args = _gp11_call_async_prep (session, perform_verify, sizeof (*args), free_verify);
+
+	g_return_if_fail (GP11_IS_OBJECT (key));
+	g_return_if_fail (mech_args);
+	
+	g_object_get (key, "handle", &args->key, NULL);
+	g_return_if_fail (args->key != 0);
+
+	args->mech.mechanism = mech_args->type;
+	args->mech.pParameter = mech_args->parameter && mech_args->n_parameter ? 
+	                                   g_memdup (mech_args->parameter, mech_args->n_parameter) : NULL;
+	args->mech.ulParameterLen = mech_args->n_parameter;
+	
+	args->input = input && n_input ? g_memdup (input, n_input) : NULL;
+	args->n_input = n_input;
+	args->signature = signature && n_signature ? g_memdup (signature, n_signature) : NULL;
+	args->n_input = n_signature;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+gboolean
+gp11_session_verify_finish (GP11Session *session, GAsyncResult *result, GError **err)
+{
+	return _gp11_call_basic_finish (session, result, err);
+}
+
+#endif /* UNTESTED */

Added: trunk/gp11/gp11-slot.c
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11-slot.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,436 @@
+
+#include "config.h"
+
+#include "gp11.h"
+#include "gp11-private.h"
+
+#include <string.h>
+
+enum {
+	PROP_0,
+	PROP_MODULE,
+	PROP_HANDLE
+};
+
+G_DEFINE_TYPE (GP11Slot, gp11_slot, G_TYPE_OBJECT);
+
+/* ----------------------------------------------------------------------------
+ * OBJECT
+ */
+
+static void
+gp11_slot_init (GP11Slot *slot)
+{
+	
+}
+
+static void
+gp11_slot_get_property (GObject *obj, guint prop_id, GValue *value, 
+                        GParamSpec *pspec)
+{
+	GP11Slot *slot = GP11_SLOT (obj);
+
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_value_set_object (value, slot->module);
+		break;
+	case PROP_HANDLE:
+		g_value_set_uint (value, slot->handle);
+		break;
+	}
+}
+
+static void
+gp11_slot_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                        GParamSpec *pspec)
+{
+	GP11Slot *slot = GP11_SLOT (obj);
+
+	switch (prop_id) {
+	case PROP_MODULE:
+		g_return_if_fail (!slot->module);
+		slot->module = g_value_get_object (value);
+		g_return_if_fail (slot->module);
+		g_object_ref (slot->module);
+		break;
+	case PROP_HANDLE:
+		g_return_if_fail (!slot->handle);
+		slot->handle = g_value_get_uint (value);
+		break;
+	}
+}
+
+static void
+gp11_slot_dispose (GObject *obj)
+{
+	GP11Slot *slot = GP11_SLOT (obj);
+	
+	if (slot->module)
+		g_object_unref (slot->module);
+	slot->module = NULL;
+
+	G_OBJECT_CLASS (gp11_slot_parent_class)->dispose (obj);
+}
+
+static void
+gp11_slot_finalize (GObject *obj)
+{
+	GP11Slot *slot = GP11_SLOT (obj);
+
+	g_assert (slot->module == NULL);
+	slot->handle = 0;
+	
+	G_OBJECT_CLASS (gp11_slot_parent_class)->finalize (obj);
+}
+
+
+static void
+gp11_slot_class_init (GP11SlotClass *klass)
+{
+	GObjectClass *gobject_class = (GObjectClass*)klass;
+	gp11_slot_parent_class = g_type_class_peek_parent (klass);
+	
+	gobject_class->get_property = gp11_slot_get_property;
+	gobject_class->set_property = gp11_slot_set_property;
+	gobject_class->dispose = gp11_slot_dispose;
+	gobject_class->finalize = gp11_slot_finalize;
+	
+	g_object_class_install_property (gobject_class, PROP_MODULE,
+		g_param_spec_object ("module", "Module", "PKCS11 Module",
+		                     GP11_TYPE_MODULE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (gobject_class, PROP_HANDLE,
+		g_param_spec_uint ("handle", "Handle", "PKCS11 Slot ID",
+		                   0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+/* ----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+void
+gp11_slot_info_free (GP11SlotInfo *slot_info)
+{
+	if (!slot_info)
+		return;
+	g_free (slot_info->slot_description);
+	g_free (slot_info->manufacturer_id);
+	g_free (slot_info);
+}
+
+void
+gp11_token_info_free (GP11TokenInfo *token_info)
+{
+	if (!token_info)
+		return;
+	g_free (token_info->label);
+	g_free (token_info->manufacturer_id);
+	g_free (token_info->model);
+	g_free (token_info->serial_number);
+	g_free (token_info);
+}
+
+void
+gp11_mechanism_info_free (GP11MechanismInfo *mech_info)
+{
+	if (!mech_info)
+		return;
+	g_free (mech_info);
+}
+
+GP11SlotInfo*
+gp11_slot_get_info (GP11Slot *slot)
+{
+	GP11SlotInfo *slotinfo;
+	CK_SLOT_INFO info;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+	g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+	g_return_val_if_fail (slot->module->funcs, NULL);
+	
+	memset (&info, 0, sizeof (info));
+	rv = (slot->module->funcs->C_GetSlotInfo) (slot->handle, &info);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv));
+		return NULL;
+	}
+	
+	slotinfo = g_new0 (GP11SlotInfo, 1);
+	slotinfo->slot_description = gp11_string_from_chars (info.slotDescription, 
+	                                                     sizeof (info.slotDescription));
+	slotinfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID, 
+	                                                    sizeof (info.manufacturerID));
+	slotinfo->flags = info.flags;
+	slotinfo->hardware_version_major = info.hardwareVersion.major;
+	slotinfo->hardware_version_minor = info.hardwareVersion.minor;
+	slotinfo->firmware_version_major = info.firmwareVersion.major;
+	slotinfo->firmware_version_minor = info.firmwareVersion.minor;
+
+	return slotinfo;
+}
+
+GP11TokenInfo*
+gp11_slot_get_token_info (GP11Slot *slot)
+{
+	GP11TokenInfo *tokeninfo;
+	CK_TOKEN_INFO info;
+	gchar *string;
+	struct tm tm;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+	g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+	g_return_val_if_fail (slot->module->funcs, NULL);
+	
+	memset (&info, 0, sizeof (info));
+	rv = (slot->module->funcs->C_GetTokenInfo) (slot->handle, &info);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get slot info: %s", gp11_message_from_rv (rv));
+		return NULL;
+	}
+	
+	tokeninfo = g_new0 (GP11TokenInfo, 1);
+	tokeninfo->label = gp11_string_from_chars (info.label, sizeof (info.label));
+	tokeninfo->model = gp11_string_from_chars (info.model, sizeof (info.model));
+	tokeninfo->manufacturer_id = gp11_string_from_chars (info.manufacturerID, 
+	                                                     sizeof (info.manufacturerID));
+	tokeninfo->serial_number = gp11_string_from_chars (info.serialNumber, 
+	                                                   sizeof (info.serialNumber));
+	tokeninfo->flags = info.flags;
+	tokeninfo->max_session_count = info.ulMaxSessionCount;
+	tokeninfo->session_count = info.ulSessionCount;
+	tokeninfo->max_rw_session_count = info.ulMaxRwSessionCount;
+	tokeninfo->rw_session_count = info.ulRwSessionCount;
+	tokeninfo->max_pin_len = info.ulMaxPinLen;
+	tokeninfo->min_pin_len = info.ulMinPinLen;
+	tokeninfo->total_public_memory = info.ulTotalPublicMemory;
+	tokeninfo->total_private_memory = info.ulTotalPrivateMemory;
+	tokeninfo->free_private_memory = info.ulFreePrivateMemory;
+	tokeninfo->free_public_memory = info.ulFreePublicMemory;
+	tokeninfo->hardware_version_major = info.hardwareVersion.major;
+	tokeninfo->hardware_version_minor = info.hardwareVersion.minor;
+	tokeninfo->firmware_version_major = info.firmwareVersion.major;
+	tokeninfo->firmware_version_minor = info.firmwareVersion.minor;
+	
+	/* Parse the time into seconds since epoch */
+	if (info.flags & CKF_CLOCK_ON_TOKEN) {
+		string = g_strndup ((gchar*)info.utcTime, MIN (14, sizeof (info.utcTime)));
+		if (!strptime (string, "%Y%m%d%H%M%S", &tm))
+			tokeninfo->utc_time = -1;
+		else
+			tokeninfo->utc_time = mktime (&tm);
+	} else {
+		tokeninfo->utc_time = -1;
+	}
+	
+	return tokeninfo;
+}
+
+GSList*
+gp11_slot_get_mechanisms (GP11Slot *slot)
+{
+	CK_MECHANISM_TYPE_PTR mech_list;
+	CK_ULONG count, i;
+	GSList *result;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+	g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+	g_return_val_if_fail (slot->module->funcs, NULL);
+
+	rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, NULL, &count);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get mechanism count: %s", gp11_message_from_rv (rv));
+		return NULL;
+	}
+	
+	if (!count)
+		return NULL;
+	
+	mech_list = g_new (CK_MECHANISM_TYPE, count);
+	rv = (slot->module->funcs->C_GetMechanismList) (slot->handle, mech_list, &count);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get mechanism list: %s", gp11_message_from_rv (rv));
+		g_free (mech_list);
+		return NULL;
+	}
+	
+	result = NULL;
+	for (i = 0; i < count; ++i)
+		result = g_slist_prepend (result, GUINT_TO_POINTER (mech_list[i]));
+	
+	g_free (mech_list);
+	return g_slist_reverse (result);
+
+}
+
+GP11MechanismInfo*
+gp11_slot_get_mechanism_info (GP11Slot *slot, guint mech_type)
+{
+	GP11MechanismInfo *mechinfo;
+	CK_MECHANISM_INFO info;
+	struct tm;
+	CK_RV rv;
+	
+	g_return_val_if_fail (GP11_IS_SLOT (slot), NULL);
+	g_return_val_if_fail (GP11_IS_MODULE (slot->module), NULL);
+	g_return_val_if_fail (slot->module->funcs, NULL);
+	
+	memset (&info, 0, sizeof (info));
+	rv = (slot->module->funcs->C_GetMechanismInfo) (slot->handle, mech_type, &info);
+	if (rv != CKR_OK) {
+		g_warning ("couldn't get mechanism info: %s", gp11_message_from_rv (rv));
+		return NULL;
+	}
+	
+	mechinfo = g_new0 (GP11MechanismInfo, 1);
+	mechinfo->flags = info.flags;
+	mechinfo->max_key_size = info.ulMaxKeySize;
+	mechinfo->min_key_size = info.ulMinKeySize;
+	
+	return mechinfo;
+}
+
+#if UNIMPLEMENTED
+
+typedef struct InitToken {
+	GP11Arguments base;
+	const guchar *pin;
+	gsize length;
+	const gchar *label;
+} InitToken;
+
+static CK_RV
+perform_init_token (InitToken *args)
+{
+	return (args->base.pkcs11->C_InitToken) (args->base.handle, 
+	                                         args->pin, args->length, 
+	                                         args->label);
+}
+
+gboolean
+gp11_slot_init_token (GP11Slot *slot, const guchar *pin, gsize length, 
+                      const gchar *label, GCancellable *cancellable,
+                      GError **err)
+{
+	InitToken args = { GP11_ARGUMENTS_INIT, pin, length, label };
+	return _gp11_call_sync (slot, perform_init_token, &args, err);
+}
+
+void
+gp11_slot_init_token_async (GP11Slot *slot, const guchar *pin, gsize length, 
+                            const gchar *label, GCancellable *cancellable,
+                            GAsyncReadyCallback callback, gpointer user_data)
+{
+	InitToken* args = _gp11_call_async_prep (slot, perform_init_token, 
+	                                         sizeof (*args));
+	
+	args->pin = pin;
+	args->length = length;
+	args->label = label;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+	
+gboolean
+gp11_slot_init_token_finish (GP11Slot *slot, GAsyncResult *result, GError **err)
+{
+	return _gp11_call_basic_finish (slot, result, err);
+}
+
+#endif /* UNIMPLEMENTED */
+
+typedef struct OpenSession {
+	GP11Arguments base;
+	guint flags;
+	CK_SESSION_HANDLE session;
+} OpenSession;
+
+static CK_RV
+perform_open_session (OpenSession *args)
+{
+	return (args->base.pkcs11->C_OpenSession) (args->base.handle, 
+	                                           args->flags | CKF_SERIAL_SESSION, 
+	                                           NULL, NULL, &args->session);
+}
+
+GP11Session*
+gp11_slot_open_session (GP11Slot *slot, guint flags, GError **err)
+{
+	return gp11_slot_open_session_full (slot, flags, NULL, err);
+}
+
+GP11Session*
+gp11_slot_open_session_full (GP11Slot *slot, guint flags, GCancellable *cancellable, GError **err)
+{
+	OpenSession args = { GP11_ARGUMENTS_INIT, flags, 0 };
+	
+	if (!_gp11_call_sync (slot, perform_open_session, &args, cancellable, err))
+		return FALSE;
+	
+	return gp11_session_from_handle (slot, args.session);
+}
+
+void
+gp11_slot_open_session_async (GP11Slot *slot, guint flags, GCancellable *cancellable, 
+                              GAsyncReadyCallback callback, gpointer user_data)
+{
+	OpenSession *args = _gp11_call_async_prep (slot, perform_open_session,
+	                                           sizeof (*args), NULL);
+	
+	args->flags = flags;
+	args->session = 0;
+	
+	_gp11_call_async_go (args, cancellable, callback, user_data);
+}
+
+GP11Session*
+gp11_slot_open_session_finish (GP11Slot *slot, GAsyncResult *result, GError **err)
+{
+	OpenSession *args;
+	
+	if (!_gp11_call_basic_finish (slot, result, err))
+		return NULL;
+	
+	args = _gp11_call_arguments (result, OpenSession);
+	return gp11_session_from_handle (slot, args->session);
+}
+
+#if UNIMPLEMENTED
+
+static CK_RV
+perform_close_all_sessions (GP11Arguments *args)
+{
+	return (args->pkcs11->C_CloseAllSessions) (args->handle);
+}
+
+gboolean
+gp11_slot_close_all_sessions (GP11Slot *slot, GError **err)
+{
+	return gp11_slot_close_all_sessions_full (slot, NULL, err);
+}
+
+gboolean
+gp11_slot_close_all_sessions_full (GP11Slot *slot, GCancellable *cancellable, GError **err)
+{
+	GP11Arguments args = GP11_ARGUMENTS_INIT;
+	return _gp11_call_sync (slot, perform_close_all_sessions, &args, cancellable, err);
+}
+
+void
+gp11_slot_close_all_sessions_async (GP11Slot *slot, GCancellable *cancellable, 
+                                    GAsyncReadyCallback callback, gpointer user_data)
+{
+	GP11Arguments *args = _gp11_call_async_prep (slot, perform_close_all_sessions, 0, NULL);
+	_gp11_call_async_go (args, cancellable, callback, user_data);	
+}
+
+gboolean
+gp11_slot_close_all_sessions_finish (GP11Slot *slot, GAsyncResult *result,
+                                     GError **err)
+{
+	return _gp11_call_basic_finish (slot, result, err);
+}
+
+#endif

Added: trunk/gp11/gp11.h
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11.h	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,1294 @@
+#ifndef GP11_H_
+#define GP11_H_
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "pkcs11.h"
+
+G_BEGIN_DECLS
+
+#define             GP11_VENDOR_CODE                        0x47503131 /* GP11 */
+
+/* An error code which results from a failure to load the PKCS11 module */
+#define             CKR_GP11_MODULE_PROBLEM                 (CKR_VENDOR_DEFINED | (GP11_VENDOR_CODE + 1)) 
+
+#define             GP11_ERROR                              (gp11_get_error_quark ())
+
+GQuark              gp11_get_error_quark                    (void);
+
+void                gp11_list_unref_free                    (GList *reflist);
+
+const gchar*        gp11_message_from_rv                    (CK_RV rv);
+
+gchar*              gp11_string_from_chars                  (const guchar *data, gsize max);
+
+typedef struct GP11Mechanism {
+	guint type;
+	gpointer parameter;
+	gulong n_parameter;
+} GP11Mechanism;
+
+typedef struct GP11Attribute {
+	gulong type;
+	gpointer value;
+	gulong length;
+} GP11Attribute;
+
+/* 
+ * Used with var args in place of a length to denote that this type
+ * of value follows.
+ */
+enum {
+	GP11_BOOLEAN = -1,
+	GP11_ULONG = -2,
+	GP11_STRING = -3,
+	GP11_DATE = -4
+};
+
+void                gp11_attribute_init                     (GP11Attribute *attr,
+                                                             guint attr_type,
+                                                             gconstpointer value,
+                                                             gsize length);
+
+void                gp11_attribute_init_boolean             (GP11Attribute *attr,
+                                                             guint attr_type,
+                                                             gboolean value);
+
+void                gp11_attribute_init_date                (GP11Attribute *attr,
+                                                             guint attr_type, 
+                                                             const GDate *value);
+
+void                gp11_attribute_init_ulong               (GP11Attribute *attr,
+                                                             guint attr_type, 
+                                                             gulong value);
+
+void                gp11_attribute_init_string              (GP11Attribute *attr,
+                                                             guint attr_type, 
+                                                             const gchar *value);
+
+void                gp11_attribute_init_copy                (GP11Attribute *dest, 
+                                                             GP11Attribute *src);
+
+GP11Attribute*      gp11_attribute_new                      (guint attr_type,
+                                                             gpointer value,
+                                                             gsize length);
+
+GP11Attribute*      gp11_attribute_new_boolean              (guint attr_type,
+                                                             gboolean value);
+
+GP11Attribute*      gp11_attribute_new_date                 (guint attr_type,
+                                                             const GDate *value);
+
+GP11Attribute*      gp11_attribute_new_ulong                (guint attr_type,
+                                                             gulong value);
+
+GP11Attribute*      gp11_attribute_new_string               (guint attr_type,
+                                                             const gchar *value);
+
+gboolean            gp11_attribute_get_boolean              (GP11Attribute *attr);
+
+gulong              gp11_attribute_get_ulong                (GP11Attribute *attr);
+
+gchar*              gp11_attribute_get_string               (GP11Attribute *attr);
+
+GDate*              gp11_attribute_get_date                 (GP11Attribute *attr);
+
+GP11Attribute*      gp11_attribute_dup                      (GP11Attribute *attr);
+
+void                gp11_attribute_clear                    (GP11Attribute *attr);
+
+void                gp11_attribute_free                     (GP11Attribute *attr);
+
+typedef struct _GP11Attributes GP11Attributes;
+ 
+GP11Attributes*     gp11_attributes_new                     (void);
+
+GP11Attributes*     gp11_attributes_newv                    (guint attr_type, ...);
+
+GP11Attributes*     gp11_attributes_new_valist              (va_list va);
+
+void                gp11_attributes_set_immutable           (GP11Attributes *attrs);
+
+gboolean            gp11_attributes_is_immutable            (GP11Attributes *attrs);
+
+GP11Attribute*      gp11_attributes_at                      (GP11Attributes *attrs,
+                                                             guint index);
+
+void                gp11_attributes_add                     (GP11Attributes *attrs,
+                                                             GP11Attribute *attr);
+
+void                gp11_attributes_add_data                (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             gconstpointer value,
+                                                             gsize length);
+
+void                gp11_attributes_add_boolean             (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             gboolean value);
+
+void                gp11_attributes_add_string              (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             const gchar *string);
+
+void                gp11_attributes_add_date                (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             const GDate *date);
+
+void                gp11_attributes_add_ulong               (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             gulong value);
+
+GP11Attribute*      gp11_attributes_find                    (GP11Attributes *attrs,
+                                                             guint attr_type);
+
+gboolean            gp11_attributes_find_boolean            (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             gboolean *value);            
+
+gboolean            gp11_attributes_find_ulong              (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             gulong *value);            
+
+gboolean            gp11_attributes_find_string             (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             gchar **value);            
+
+gboolean            gp11_attributes_find_date               (GP11Attributes *attrs,
+                                                             guint attr_type,
+                                                             GDate **value);            
+
+gulong              gp11_attributes_count                   (GP11Attributes *attrs);
+
+void                gp11_attributes_ref                     (GP11Attributes *attrs);
+
+void                gp11_attributes_unref                   (GP11Attributes *attrs);
+
+/* -------------------------------------------------------------------------
+ * FORWARDS
+ */
+
+typedef struct _GP11Slot GP11Slot;
+typedef struct _GP11Module GP11Module;
+typedef struct _GP11Session GP11Session;
+typedef struct _GP11Object GP11Object;
+
+/* -------------------------------------------------------------------------
+ * MODULE
+ */
+
+typedef struct _GP11ModuleInfo {
+	guint pkcs11_version_major;
+	guint pkcs11_version_minor;
+	
+	gchar *manufacturer_id;
+	guint32 flags;
+	
+	gchar *library_description;
+	guint library_version_major;
+	guint library_version_minor;
+} GP11ModuleInfo;
+
+void                gp11_module_info_free                   (GP11ModuleInfo *module_info);
+
+#define GP11_TYPE_MODULE             (gp11_module_get_type())
+#define GP11_MODULE(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_MODULE, GP11Module))
+#define GP11_MODULE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_MODULE, GP11Module))
+#define GP11_IS_MODULE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_MODULE))
+#define GP11_IS_MODULE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_MODULE))
+#define GP11_MODULE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_MODULE, GP11ModuleClass))
+
+typedef struct _GP11ModuleClass GP11ModuleClass;
+
+struct _GP11Module {
+	GObject parent;
+	
+	gchar *path;
+	CK_FUNCTION_LIST_PTR funcs;
+};
+
+struct _GP11ModuleClass {
+	GObjectClass parent;
+};
+
+GType               gp11_module_get_type                    (void) G_GNUC_CONST;
+
+GP11Module*         gp11_module_initialize                  (const gchar *path, 
+                                                             GError **err);
+
+GP11ModuleInfo*     gp11_module_get_info                    (GP11Module *module);
+
+GList*              gp11_module_get_slots                   (GP11Module *module,
+                                                             gboolean token_present);
+
+enum {
+	GP11_IS_STRING = -1,
+	GP11_IS_BOOLEAN = -2,
+	GP11_IS_DATE = -3,
+	GP11_IS_ULONG = -4
+};
+
+/* ------------------------------------------------------------------------
+ * SLOT
+ */
+
+typedef struct _GP11SlotInfo {
+	gchar *slot_description;
+	gchar *manufacturer_id;
+	guint32 flags;
+	guint hardware_version_major;
+	guint hardware_version_minor;
+	guint firmware_version_major;
+	guint firmware_version_minor;
+} GP11SlotInfo;
+
+void                gp11_slot_info_free                      (GP11SlotInfo *slot_info);
+
+typedef struct _GP11TokenInfo {
+	gchar *label;
+	gchar *manufacturer_id;
+	gchar *model;
+	gchar *serial_number;
+	guint32 flags;
+	glong max_session_count;
+	glong session_count;
+	glong max_rw_session_count;
+	glong rw_session_count;
+	glong max_pin_len;
+	glong min_pin_len;
+	glong total_public_memory;
+	glong free_public_memory;
+	glong total_private_memory;
+	glong free_private_memory;
+	guint hardware_version_major;
+	guint hardware_version_minor;
+	guint firmware_version_major;
+	guint firmware_version_minor;
+	gint64 utc_time;
+} GP11TokenInfo;
+
+void                gp11_token_info_free                    (GP11TokenInfo *token_info);
+
+typedef struct _GP11MechanismInfo {
+	gulong min_key_size;
+	gulong max_key_size;
+	guint32 flags;
+} GP11MechanismInfo;
+
+void                gp11_mechanism_info_free                (GP11MechanismInfo *mech_info);
+
+#define GP11_TYPE_SLOT             (gp11_slot_get_type())
+#define GP11_SLOT(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_SLOT, GP11Slot))
+#define GP11_SLOT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_SLOT, GP11Slot))
+#define GP11_IS_SLOT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_SLOT))
+#define GP11_IS_SLOT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_SLOT))
+#define GP11_SLOT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_SLOT, GP11SlotClass))
+
+typedef struct _GP11SlotClass GP11SlotClass;
+
+struct _GP11Slot {
+	GObject parent;
+	
+	GP11Module *module;
+	CK_SLOT_ID handle;
+};
+
+struct _GP11SlotClass {
+	GObjectClass parent;
+	
+	void (*slot_event) (GP11Slot *slot);
+};
+
+GType               gp11_slot_get_type                      (void) G_GNUC_CONST;
+
+GP11SlotInfo*       gp11_slot_get_info                      (GP11Slot *slot);
+
+GP11TokenInfo*      gp11_slot_get_token_info                (GP11Slot *slot);
+
+GSList*             gp11_slot_get_mechanisms                (GP11Slot *slot);
+
+GP11MechanismInfo*  gp11_slot_get_mechanism_info            (GP11Slot *slot,
+                                                             guint32 mech_type);
+
+#if UNIMPLEMENTED
+
+gboolean            gp11_slot_init_token                    (GP11Slot *slot, 
+                                                             const guchar *pin,
+                                                             gsize length, 
+                                                             const gchar *label,
+                                                             GError **err);
+
+
+void                gp11_slot_init_token_async              (GP11Slot *slot, 
+                                                             const guchar *pin,
+                                                             gsize length, 
+                                                             const gchar *label,
+                                                             GAsyncReadyCallback callback, 
+                                                             gpointer user_data);
+
+gboolean            gp11_slot_init_token_finish             (GP11Slot *slot, 
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+GP11Session*        gp11_slot_open_session                  (GP11Slot *slot,
+                                                             guint flags,
+                                                             GError **err);
+
+GP11Session*        gp11_slot_open_session_full             (GP11Slot *slot,
+                                                             guint flags,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_slot_open_session_async            (GP11Slot *slot,
+                                                             guint flags,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+GP11Session*        gp11_slot_open_session_finish           (GP11Slot *slot,
+                                                    	     GAsyncResult *result,
+                                                    	     GError **err);
+
+/* ------------------------------------------------------------------------
+ * SESSION
+ */
+
+typedef struct _GP11SessionInfo {
+	guint32 slot_id;
+	guint32 state;
+	guint32 flags;
+	gulong device_error;
+} GP11SessionInfo;
+
+void                gp11_session_info_free                  (GP11SessionInfo *session_info);
+
+#define GP11_TYPE_SESSION             (gp11_session_get_type())
+#define GP11_SESSION(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_SESSION, GP11Session))
+#define GP11_SESSION_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_SESSION, GP11Session))
+#define GP11_IS_SESSION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_SESSION))
+#define GP11_IS_SESSION_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_SESSION))
+#define GP11_SESSION_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_SESSION, GP11SessionClass))
+
+typedef struct _GP11SessionClass GP11SessionClass;
+
+struct _GP11Session {
+	GObject parent;
+	
+	GP11Module *module;
+	CK_SLOT_ID handle;	
+};
+
+struct _GP11SessionClass {
+	GObjectClass parent;
+};
+
+GType               gp11_session_get_type                   (void) G_GNUC_CONST;
+
+GP11Session*        gp11_session_from_handle                (GP11Slot *slot, CK_SESSION_HANDLE handle); 
+
+GP11SessionInfo*    gp11_session_get_info                   (GP11Session *session);
+
+#if UNIMPLEMENTED
+
+gboolean            gp11_session_init_pin                   (GP11Session *session, 
+                                                             const guchar *pin,
+                                                             gsize n_pin,
+                                                             GError **err);
+
+void                gp11_session_init_pin_async             (GP11Session *session, 
+                                                             const guchar *pin,
+                                                             gsize n_pin,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_session_init_pin_finish            (GP11Session *session, 
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+gboolean            gp11_session_set_pin                    (GP11Session *session,
+                                                             const guchar *old_pin,
+                                                             gsize n_old_pin,
+                                                             const guchar *new_pin,
+                                                             gsize n_new_pin,
+                                                             GError **err);
+
+void                gp11_session_set_pin_async              (GP11Session *session,
+                                                             const guchar *old_pin,
+                                                             gsize n_old_pin,
+                                                             const guchar *new_pin,
+                                                             gsize n_new_pin,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_session_set_pin_finish             (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+guchar*             gp11_session_get_operation_state        (GP11Session *session,
+                                                             gsize *n_result,
+                                                             GError **err);
+
+void                gp11_session_get_operation_state_async  (GP11Session *session,
+                                                             gsize *n_result,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+guchar*             gp11_session_get_operation_state_finish (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             gsize *n_result,
+                                                             GError **err);
+
+gboolean            gp11_session_set_operation_state        (GP11Session *session, 
+                                                             const guchar *state,
+                                                             gsize n_state,
+                                                             GError **err);
+
+void                gp11_session_set_operation_state_async  (GP11Session *session, 
+                                                             const guchar *state,
+                                                             gsize n_state,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_session_set_operation_state_finish (GP11Session *session, 
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+gboolean            gp11_session_login                      (GP11Session *session, 
+                                                             guint32 user_type,
+                                                             const guchar *pin,
+                                                             gsize n_pin,
+                                                             GError **err);
+
+gboolean            gp11_session_login_full                 (GP11Session *session, 
+                                                             guint32 user_type,
+                                                             const guchar *pin,
+                                                             gsize n_pin,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_session_login_async                (GP11Session *session, 
+                                                             guint32 user_type,
+                                                             const guchar *pin,
+                                                             gsize n_pin,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_session_login_finish               (GP11Session *session, 
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+gboolean            gp11_session_logout                     (GP11Session *session,
+                                                             GError **err);
+
+gboolean            gp11_session_logout_full                (GP11Session *session,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_session_logout_async               (GP11Session *session,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_session_logout_finish              (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+GP11Object*         gp11_session_create_object              (GP11Session *session, 
+                                                             GError **err, 
+                                                             ...); 
+
+GP11Object*         gp11_session_create_object_full         (GP11Session *session,
+                                                             GP11Attributes *attrs,
+                                                             GCancellable *cancellable,
+                                                             GError **err); 
+
+void                gp11_session_create_object_async        (GP11Session *session,
+                                                             GP11Attributes *attrs,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+GP11Object*         gp11_session_create_object_finish       (GP11Session *session, 
+                                                             GAsyncResult *result,
+                                                             GError **err); 
+
+GList*              gp11_session_find_objects               (GP11Session *session,
+                                                             GError **err,
+                                                             ...); 
+
+GList*              gp11_session_find_objects_full          (GP11Session *session,
+                                                             GP11Attributes *attrs,
+                                                             GCancellable *cancellable,
+                                                             GError **err); 
+
+void                gp11_session_find_objects_async         (GP11Session *session,
+                                                             GP11Attributes *attrs,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data); 
+
+GList*              gp11_session_find_objects_finish        (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             GError **err); 
+
+#if UNIMPLEMENTED
+
+GP11Object*         gp11_session_generate_key               (GP11Session *session,
+                                                             GP11Mechanism *mechanism,
+                                                             GError **err,
+                                                             ...);
+
+void                gp11_session_generate_key_async         (GP11Session *session,
+                                                             GP11Mechanism *mechanism,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data,
+                                                             ...);
+
+GP11Object*         gp11_session_generate_key_finish        (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             GError **err,
+                                                             ...);
+
+gboolean            gp11_session_generate_key_pair          (GP11Session *session,
+                                                             GP11Mechanism *mechanism,
+                                                             GP11Object **public_key,
+                                                             GP11Object **private_key,
+                                                             GError **err,
+                                                             ...);
+
+void                gp11_session_generate_key_pair_async    (GP11Session *session,
+                                                             GP11Mechanism *mechanism,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data,
+                                                             ...);
+
+gboolean            gp11_session_generate_key_pair_finish   (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             GP11Object **public_key,
+                                                             GP11Object **private_key,
+                                                             GError **err,
+                                                             ...);
+
+gboolean            gp11_session_seed_random                (GP11Session *session,
+                                                             const guchar *seed,
+                                                             gsize n_seed,
+                                                             GError **err);
+
+void                gp11_session_seed_random_async          (GP11Session *session,
+                                                             const guchar *seed,
+                                                             gsize n_seed,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_session_seed_random_finish         (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+guchar*             gp11_session_generate_random            (GP11Session *session,
+                                                             gsize n_random,
+                                                             GError **err);
+
+void                gp11_session_generate_random_async      (GP11Session *session,
+                                                             gsize n_random,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+guchar*             gp11_session_generate_random_finish     (GP11Session *session,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED 
+
+guchar*             gp11_session_encrypt                     (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_encrypt_full                (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_encrypt_async               (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+guchar*             gp11_session_encrypt_finish              (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GP11Processor*      gp11_session_batch_encrypt               (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_encrypt_async         (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_encrypt_finish        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED
+guchar*             gp11_session_decrypt                     (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_decrypt_full                (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_decrypt_async               (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+guchar*             gp11_session_decrypt_finish              (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GP11Processor*      gp11_session_batch_decrypt               (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_decrypt_async         (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_decrypt_finish        (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+guchar*             gp11_session_digest                      (GP11Session *session,
+                                                              guint mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_digest_full                 (GP11Session *session,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_digest_async                (GP11Session *session,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+guchar*             gp11_session_digest_finish               (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+GP11Processor*      gp11_session_batch_digest	             (GP11Session *session,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_digest_async          (GP11Session *session,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_digest_finish         (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+GP11Processor*      gp11_session_batch_digest_encrypt        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *digest_mech,
+                                                              GP11Mechanism *encrypt_mech,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_digest_encrypt_async  (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *digest_mech,
+                                                              GP11Mechanism *encrypt_mech,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_digest_encrypt_finish (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+GP11Processor*      gp11_session_batch_digest_decrypt        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *digest_mech,
+                                                              GP11Mechanism *decrypt_mech,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_digest_decrypt_async  (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *digest_mech,
+                                                              GP11Mechanism *decrypt_mech,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_digest_decrypt_finish (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+GP11Processor*      gp11_session_batch_decrypt_verify        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *decrypt_mech,
+                                                              GP11Mechanism *verify_mech,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_decrypt_verify_async  (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *decrypt_mech,
+                                                              GP11Mechanism *verify_mech,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_decrypt_verify_finish (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED 
+
+guchar*             gp11_session_sign                        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_sign_full                   (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_sign_async                  (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+guchar*             gp11_session_sign_finish                 (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GP11Processor*      gp11_session_batch_sign                  (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_sign_async            (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_sign_finish           (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+GP11Processor*      gp11_session_batch_sign_encrypt          (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *sign_mech,
+                                                              GP11Mechanism *encrypt_mech,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_sign_encrypt_async    (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *sign_mechanism,
+                                                              GP11Mechanism *encrypt_mech,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GP11Processor*      gp11_session_batch_sign_encrypt_finish   (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+guchar*             gp11_session_sign_recover                (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_sign_recover_full           (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_sign_recover_async          (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+guchar*             gp11_session_sign_recover_finish         (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+#if UNTESTED 
+
+gboolean            gp11_session_verify                      (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              const guchar *signature,
+                                                              gsize n_signature,
+                                                              GError **err);
+
+gboolean            gp11_session_verify_full                 (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              const guchar *signature,
+                                                              gsize n_signature,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_verify_async                (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mechanism,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              const guchar *signature,
+                                                              gsize n_signature,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+gboolean            gp11_session_verify_finish               (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+#endif /* UNTESTED */
+
+#if UNIMPLEMENTED
+
+GkrProcessor*       gp11_session_batch_verify                (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_batch_verify_async          (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+GkrProcessor*       gp11_session_batch_verify_finish         (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+guchar*             gp11_session_verify_recover              (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_verify_recover_full         (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_verify_recover_async        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+guchar*             gp11_session_verify_recover_finish       (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_wrap                        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              GP11Object *wrapped_key,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+guchar*             gp11_session_wrap                        (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GP11Object *wrapped_key,
+                                                              gsize *n_result,
+                                                              GCancellable *cancellable,
+                                                              GError **err);
+
+void                gp11_session_wrap_async                  (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GP11Object *wrapped_key,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+
+guchar*             gp11_session_wrap_finish                 (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              gsize *n_result,
+                                                              GError **err);
+
+GP11Object*         gp11_session_unwrap                      (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GError **err,
+                                                              ...);
+
+GP11Object*         gp11_session_unwrap                      (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GError **err,
+                                                              ...);
+
+void                gp11_session_unwrap_async                (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              const guchar *input,
+                                                              gsize n_input,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+                                                              ...);
+
+GP11Object*         gp11_session_unwrap_finish               (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+GP11Object*         gp11_session_derive                      (GP11Session *session,
+                                                              GP11Object *key,
+                                                              guint mech_type,
+                                                              GError **err,
+                                                              ...);
+
+GP11Object*         gp11_session_derive_full                 (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GError **err,
+                                                              ...);
+
+void                gp11_session_derive_async                (GP11Session *session,
+                                                              GP11Object *key,
+                                                              GP11Mechanism *mech_args,
+                                                              GCancellable *cancellable,
+                                                              GAsyncReadyCallback callback,
+                                                              gpointer user_data);
+                                                              ...);
+
+GP11Object*         gp11_session_derive_finish               (GP11Session *session,
+                                                              GAsyncResult *result,
+                                                              GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+
+/* ------------------------------------------------------------------------
+ * OBJECT
+ */
+
+#define GP11_TYPE_OBJECT             (gp11_object_get_type())
+#define GP11_OBJECT(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GP11_TYPE_OBJECT, GP11Object))
+#define GP11_OBJECT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GP11_TYPE_OBJECT, GP11Object))
+#define GP11_IS_OBJECT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GP11_TYPE_OBJECT))
+#define GP11_IS_OBJECT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GP11_TYPE_OBJECT))
+#define GP11_OBJECT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), GP11_TYPE_OBJECT, GP11ObjectClass))
+
+typedef struct _GP11ObjectClass GP11ObjectClass;
+
+struct _GP11Object {
+	GObject parent;
+	
+	GP11Module *module;
+	GP11Session *session;
+	CK_OBJECT_HANDLE handle;
+};
+
+struct _GP11ObjectClass {
+	GObjectClass parent;
+};
+
+GType               gp11_object_get_type                    (void) G_GNUC_CONST;
+
+GP11Object*         gp11_object_from_handle                 (GP11Session *session, 
+                                                             CK_OBJECT_HANDLE handle);
+
+#ifdef UNIMPLEMENTED
+
+GP11Object*         gp11_object_copy                        (GP11Object *object,
+                                                             GError **err);
+
+GP11Object*         gp11_object_copy_full                   (GP11Object *object,
+                                                             GP11Attributes *additional,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_object_copy_async                  (GP11Object *object,
+                                                             GP11Attributes *additional,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+GP11Object*         gp11_object_copy_finish                 (GP11Object *object,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+gboolean            gp11_object_destroy                     (GP11Object *object,
+                                                             GError **err);
+
+gboolean            gp11_object_destroy_full                (GP11Object *object,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_object_destroy_async               (GP11Object *object,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_object_destroy_finish              (GP11Object *object,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+#if UNIMPLEMENTED
+
+gssize              gp11_object_get_size                    (GP11Object *object,
+                                                             GError **err);
+
+gssize              gp11_object_get_size_full               (GP11Object *object,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_object_get_size_async              (GP11Object *object,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gssize              gp11_object_get_size_finish             (GP11Object *object,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+gboolean            gp11_object_set                         (GP11Object *object,
+                                                             GError **err,
+                                                             ...);
+
+gboolean            gp11_object_set_full                    (GP11Object *object,
+                                                             GP11Attributes *attrs,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_object_set_async                   (GP11Object *object,
+                                                             GP11Attributes *attrs,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean            gp11_object_set_finish                  (GP11Object *object,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+GP11Attributes*     gp11_object_get                         (GP11Object *object,
+                                                             GError **err,
+                                                             ...);
+
+GP11Attributes*     gp11_object_get_full                    (GP11Object *object,
+                                                             guint *attr_types,
+                                                             gsize n_attr_types,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_object_get_async                   (GP11Object *object,
+                                                             guint *attr_types,
+                                                             gsize n_attr_types,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+GP11Attributes*     gp11_object_get_finish                  (GP11Object *object,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+GP11Attribute*      gp11_object_get_one                     (GP11Object *object,
+                                                             guint attr_type,
+                                                             GError **err);
+
+GP11Attribute*      gp11_object_get_one_full                (GP11Object *object,
+                                                             guint attr_type,
+                                                             GCancellable *cancellable,
+                                                             GError **err);
+
+void                gp11_object_get_one_async               (GP11Object *object,
+                                                             guint attr_type,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+GP11Attribute*      gp11_object_get_one_finish              (GP11Object *object,
+                                                             GAsyncResult *result,
+                                                             GError **err);
+
+
+/* ----------------------------------------------------------------------
+ * PROCESSOR
+ */
+
+#if UNIMPLEMENTED
+
+guchar*             gp11_processor_step                    (GP11Processor *processor,
+                                                            const guchar *input,
+                                                            gsize n_input,
+                                                            gsize *n_result,
+                                                            GError **err);
+
+void                gp11_processor_step_async              (GP11Processor *processor,
+                                                            const guchar *input,
+                                                            gsize n_input,
+                                                            GAsyncReadyCallback callback,
+                                                            gpointer user_data);
+
+guchar*             gp11_processor_step_finish             (GP11Processor *processor,
+                                                            GAsyncResult *result,
+                                                            gsize *n_result,
+                                                            GError **err);
+
+guchar*             gp11_processor_close                   (GP11Processor *processor,
+                                                            gsize *n_result,
+                                                            GError **err);
+
+guchar*             gp11_processor_close_async             (GP11Processor *processor,
+                                                            GAsyncReadyCallback callback,
+                                                            gpointer user_data);
+
+guchar*             gp11_processor_close_finish            (GP11Processor *processor,
+                                                            GAsyncResult *result,
+                                                            gsize *n_result,
+                                                            GError **err);
+
+#endif /* UNIMPLEMENTED */
+
+G_END_DECLS
+
+#endif /*GP11_H_*/

Added: trunk/gp11/gp11.pc.in
==============================================================================
--- (empty file)
+++ trunk/gp11/gp11.pc.in	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,14 @@
+prefix= prefix@
+exec_prefix= exec_prefix@
+libdir= libdir@
+includedir= includedir@
+datarootdir= datarootdir@
+datadir= datadir@
+sysconfdir= sysconfdir@
+
+Name: gp11
+Description: GObject bindings for PKCS#11
+Version: @GP11_MAJOR@
+Requires: gconf-2.0
+Libs: -L${libdir} -lgp11
+Cflags: -I${includedir}/gp11

Added: trunk/gp11/pkcs11.h
==============================================================================
--- (empty file)
+++ trunk/gp11/pkcs11.h	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,1357 @@
+/* pkcs11.h
+   Copyright 2006, 2007 g10 Code GmbH
+   Copyright 2006 Andreas Jellinghaus
+
+   This file is free software; as a special exception the author gives
+   unlimited permission to copy and/or distribute it, with or without
+   modifications, as long as this notice is preserved.
+
+   This file 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.  */
+
+/* Please submit changes back to the Scute project at
+   http://www.scute.org/ (or send them to marcus g10code com), so that
+   they can be picked up by other projects from there as well.  */
+
+/* This file is a modified implementation of the PKCS #11 standard by
+   RSA Security Inc.  It is mostly a drop-in replacement, with the
+   following change:
+
+   This header file does not require any macro definitions by the user
+   (like CK_DEFINE_FUNCTION etc).  In fact, it defines those macros
+   for you (if useful, some are missing, let me know if you need
+   more).
+
+   There is an additional API available that does comply better to the
+   GNU coding standard.  It can be switched on by defining
+   CRYPTOKI_GNU before including this header file.  For this, the
+   following changes are made to the specification:
+
+   All structure types are changed to a "struct ck_foo" where CK_FOO
+   is the type name in PKCS #11.
+
+   All non-structure types are changed to ck_foo_t where CK_FOO is the
+   lowercase version of the type name in PKCS #11.  The basic types
+   (CK_ULONG et al.) are removed without substitute.
+
+   All members of structures are modified in the following way: Type
+   indication prefixes are removed, and underscore characters are
+   inserted before words.  Then the result is lowercased.
+
+   Note that function names are still in the original case, as they
+   need for ABI compatibility.
+
+   CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute.  Use
+   <stdbool.h>.
+
+   If CRYPTOKI_COMPAT is defined before including this header file,
+   then none of the API changes above take place, and the API is the
+   one defined by the PKCS #11 standard.  */
+
+#ifndef PKCS11_H
+#define PKCS11_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The version of cryptoki we implement.  The revision is changed with
+   each modification of this file.  If you do not use the "official"
+   version of this file, please consider deleting the revision macro
+   (you may use a macro with a different name to keep track of your
+   versions).  */
+#define CRYPTOKI_VERSION_MAJOR		2
+#define CRYPTOKI_VERSION_MINOR		20
+#define CRYPTOKI_VERSION_REVISION	6
+
+
+/* Compatibility interface is default, unless CRYPTOKI_GNU is
+   given.  */
+#ifndef CRYPTOKI_GNU
+#ifndef CRYPTOKI_COMPAT
+#define CRYPTOKI_COMPAT 1
+#endif
+#endif
+
+/* System dependencies.  */
+
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+
+/* There is a matching pop below.  */
+#pragma pack(push, cryptoki, 1)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_SPEC __declspec(dllexport)
+#else
+#define CK_SPEC __declspec(dllimport)
+#endif
+
+#else
+
+#define CK_SPEC
+
+#endif
+
+
+#ifdef CRYPTOKI_COMPAT
+  /* If we are in compatibility mode, switch all exposed names to the
+     PKCS #11 variant.  There are corresponding #undefs below.  */
+
+#define ck_flags_t CK_FLAGS
+#define ck_version _CK_VERSION
+
+#define ck_info _CK_INFO
+#define cryptoki_version cryptokiVersion
+#define manufacturer_id manufacturerID
+#define library_description libraryDescription
+#define library_version libraryVersion
+
+#define ck_notification_t CK_NOTIFICATION
+#define ck_slot_id_t CK_SLOT_ID
+
+#define ck_slot_info _CK_SLOT_INFO
+#define slot_description slotDescription
+#define hardware_version hardwareVersion
+#define firmware_version firmwareVersion
+
+#define ck_token_info _CK_TOKEN_INFO
+#define serial_number serialNumber
+#define max_session_count ulMaxSessionCount
+#define session_count ulSessionCount
+#define max_rw_session_count ulMaxRwSessionCount
+#define rw_session_count ulRwSessionCount
+#define max_pin_len ulMaxPinLen
+#define min_pin_len ulMinPinLen
+#define total_public_memory ulTotalPublicMemory
+#define free_public_memory ulFreePublicMemory
+#define total_private_memory ulTotalPrivateMemory
+#define free_private_memory ulFreePrivateMemory
+#define utc_time utcTime
+
+#define ck_session_handle_t CK_SESSION_HANDLE
+#define ck_user_type_t CK_USER_TYPE
+#define ck_state_t CK_STATE
+
+#define ck_session_info _CK_SESSION_INFO
+#define slot_id slotID
+#define device_error ulDeviceError
+
+#define ck_object_handle_t CK_OBJECT_HANDLE
+#define ck_object_class_t CK_OBJECT_CLASS
+#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE
+#define ck_key_type_t CK_KEY_TYPE
+#define ck_certificate_type_t CK_CERTIFICATE_TYPE
+#define ck_attribute_type_t CK_ATTRIBUTE_TYPE
+
+#define ck_attribute _CK_ATTRIBUTE
+#define value pValue
+#define value_len ulValueLen
+
+#define ck_date _CK_DATE
+
+#define ck_mechanism_type_t CK_MECHANISM_TYPE
+
+#define ck_mechanism _CK_MECHANISM
+#define parameter pParameter
+#define parameter_len ulParameterLen
+
+#define ck_mechanism_info _CK_MECHANISM_INFO
+#define min_key_size ulMinKeySize
+#define max_key_size ulMaxKeySize
+
+#define ck_rv_t CK_RV
+#define ck_notify_t CK_NOTIFY
+
+#define ck_function_list _CK_FUNCTION_LIST
+
+#define ck_createmutex_t CK_CREATEMUTEX
+#define ck_destroymutex_t CK_DESTROYMUTEX
+#define ck_lockmutex_t CK_LOCKMUTEX
+#define ck_unlockmutex_t CK_UNLOCKMUTEX
+
+#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS
+#define create_mutex CreateMutex
+#define destroy_mutex DestroyMutex
+#define lock_mutex LockMutex
+#define unlock_mutex UnlockMutex
+#define reserved pReserved
+
+#endif	/* CRYPTOKI_COMPAT */
+
+
+
+typedef unsigned long ck_flags_t;
+
+struct ck_version
+{
+  unsigned char major;
+  unsigned char minor;
+};
+
+
+struct ck_info
+{
+  struct ck_version cryptoki_version;
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  unsigned char library_description[32];
+  struct ck_version library_version;
+};
+
+
+typedef unsigned long ck_notification_t;
+
+#define CKN_SURRENDER	(0)
+
+
+typedef unsigned long ck_slot_id_t;
+
+
+struct ck_slot_info
+{
+  unsigned char slot_description[64];
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+};
+
+
+#define CKF_TOKEN_PRESENT	(1 << 0)
+#define CKF_REMOVABLE_DEVICE	(1 << 1)
+#define CKF_HW_SLOT		(1 << 2)
+#define CKF_ARRAY_ATTRIBUTE	(1 << 30)
+
+
+struct ck_token_info
+{
+  unsigned char label[32];
+  unsigned char manufacturer_id[32];
+  unsigned char model[16];
+  unsigned char serial_number[16];
+  ck_flags_t flags;
+  unsigned long max_session_count;
+  unsigned long session_count;
+  unsigned long max_rw_session_count;
+  unsigned long rw_session_count;
+  unsigned long max_pin_len;
+  unsigned long min_pin_len;
+  unsigned long total_public_memory;
+  unsigned long free_public_memory;
+  unsigned long total_private_memory;
+  unsigned long free_private_memory;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+  unsigned char utc_time[16];
+};
+
+
+#define CKF_RNG					(1 << 0)
+#define CKF_WRITE_PROTECTED			(1 << 1)
+#define CKF_LOGIN_REQUIRED			(1 << 2)
+#define CKF_USER_PIN_INITIALIZED		(1 << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED		(1 << 5)
+#define CKF_CLOCK_ON_TOKEN			(1 << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH	(1 << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS		(1 << 9)
+#define CKF_TOKEN_INITIALIZED			(1 << 10)
+#define CKF_SECONDARY_AUTHENTICATION		(1 << 11)
+#define CKF_USER_PIN_COUNT_LOW			(1 << 16)
+#define CKF_USER_PIN_FINAL_TRY			(1 << 17)
+#define CKF_USER_PIN_LOCKED			(1 << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED		(1 << 19)
+#define CKF_SO_PIN_COUNT_LOW			(1 << 20)
+#define CKF_SO_PIN_FINAL_TRY			(1 << 21)
+#define CKF_SO_PIN_LOCKED			(1 << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED		(1 << 23)
+
+#define CK_UNAVAILABLE_INFORMATION	((unsigned long) -1)
+#define CK_EFFECTIVELY_INFINITE		(0)
+
+
+typedef unsigned long ck_session_handle_t;
+
+#define CK_INVALID_HANDLE	(0)
+
+
+typedef unsigned long ck_user_type_t;
+
+#define CKU_SO			(0)
+#define CKU_USER		(1)
+#define CKU_CONTEXT_SPECIFIC	(2)
+
+
+typedef unsigned long ck_state_t;
+
+#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)
+
+
+struct ck_session_info
+{
+  ck_slot_id_t slot_id;
+  ck_state_t state;
+  ck_flags_t flags;
+  unsigned long device_error;
+};
+
+#define CKF_RW_SESSION		(1 << 1)
+#define CKF_SERIAL_SESSION	(1 << 2)
+
+
+typedef unsigned long ck_object_handle_t;
+
+
+typedef unsigned long ck_object_class_t;
+
+#define CKO_DATA		(0)
+#define CKO_CERTIFICATE		(1)
+#define CKO_PUBLIC_KEY		(2)
+#define CKO_PRIVATE_KEY		(3)
+#define CKO_SECRET_KEY		(4)
+#define CKO_HW_FEATURE		(5)
+#define CKO_DOMAIN_PARAMETERS	(6)
+#define CKO_MECHANISM		(7)
+#define CKO_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_hw_feature_type_t;
+
+#define CKH_MONOTONIC_COUNTER	(1)
+#define CKH_CLOCK		(2)
+#define CKH_USER_INTERFACE	(3)
+#define CKH_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_key_type_t;
+
+#define CKK_RSA			(0)
+#define CKK_DSA			(1)
+#define CKK_DH			(2)
+#define CKK_ECDSA		(3)
+#define CKK_EC			(3)
+#define CKK_X9_42_DH		(4)
+#define CKK_KEA			(5)
+#define CKK_GENERIC_SECRET	(0x10)
+#define CKK_RC2			(0x11)
+#define CKK_RC4			(0x12)
+#define CKK_DES			(0x13)
+#define CKK_DES2		(0x14)
+#define CKK_DES3		(0x15)
+#define CKK_CAST		(0x16)
+#define CKK_CAST3		(0x17)
+#define CKK_CAST128		(0x18)
+#define CKK_RC5			(0x19)
+#define CKK_IDEA		(0x1a)
+#define CKK_SKIPJACK		(0x1b)
+#define CKK_BATON		(0x1c)
+#define CKK_JUNIPER		(0x1d)
+#define CKK_CDMF		(0x1e)
+#define CKK_AES			(0x1f)
+#define CKK_BLOWFISH		(0x20)
+#define CKK_TWOFISH		(0x21)
+#define CKK_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_certificate_type_t;
+
+#define CKC_X_509		(0)
+#define CKC_X_509_ATTR_CERT	(1)
+#define CKC_WTLS		(2)
+#define CKC_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_attribute_type_t;
+
+#define CKA_CLASS			(0)
+#define CKA_TOKEN			(1)
+#define CKA_PRIVATE			(2)
+#define CKA_LABEL			(3)
+#define CKA_APPLICATION			(0x10)
+#define CKA_VALUE			(0x11)
+#define CKA_OBJECT_ID			(0x12)
+#define CKA_CERTIFICATE_TYPE		(0x80)
+#define CKA_ISSUER			(0x81)
+#define CKA_SERIAL_NUMBER		(0x82)
+#define CKA_AC_ISSUER			(0x83)
+#define CKA_OWNER			(0x84)
+#define CKA_ATTR_TYPES			(0x85)
+#define CKA_TRUSTED			(0x86)
+#define CKA_CERTIFICATE_CATEGORY	(0x87)
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN	(0x88)
+#define CKA_URL				(0x89)
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY	(0x8a)
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY	(0x8b)
+#define CKA_CHECK_VALUE			(0x90)
+#define CKA_KEY_TYPE			(0x100)
+#define CKA_SUBJECT			(0x101)
+#define CKA_ID				(0x102)
+#define CKA_SENSITIVE			(0x103)
+#define CKA_ENCRYPT			(0x104)
+#define CKA_DECRYPT			(0x105)
+#define CKA_WRAP			(0x106)
+#define CKA_UNWRAP			(0x107)
+#define CKA_SIGN			(0x108)
+#define CKA_SIGN_RECOVER		(0x109)
+#define CKA_VERIFY			(0x10a)
+#define CKA_VERIFY_RECOVER		(0x10b)
+#define CKA_DERIVE			(0x10c)
+#define CKA_START_DATE			(0x110)
+#define CKA_END_DATE			(0x111)
+#define CKA_MODULUS			(0x120)
+#define CKA_MODULUS_BITS		(0x121)
+#define CKA_PUBLIC_EXPONENT		(0x122)
+#define CKA_PRIVATE_EXPONENT		(0x123)
+#define CKA_PRIME_1			(0x124)
+#define CKA_PRIME_2			(0x125)
+#define CKA_EXPONENT_1			(0x126)
+#define CKA_EXPONENT_2			(0x127)
+#define CKA_COEFFICIENT			(0x128)
+#define CKA_PRIME			(0x130)
+#define CKA_SUBPRIME			(0x131)
+#define CKA_BASE			(0x132)
+#define CKA_PRIME_BITS			(0x133)
+#define CKA_SUB_PRIME_BITS		(0x134)
+#define CKA_VALUE_BITS			(0x160)
+#define CKA_VALUE_LEN			(0x161)
+#define CKA_EXTRACTABLE			(0x162)
+#define CKA_LOCAL			(0x163)
+#define CKA_NEVER_EXTRACTABLE		(0x164)
+#define CKA_ALWAYS_SENSITIVE		(0x165)
+#define CKA_KEY_GEN_MECHANISM		(0x166)
+#define CKA_MODIFIABLE			(0x170)
+#define CKA_ECDSA_PARAMS		(0x180)
+#define CKA_EC_PARAMS			(0x180)
+#define CKA_EC_POINT			(0x181)
+#define CKA_SECONDARY_AUTH		(0x200)
+#define CKA_AUTH_PIN_FLAGS		(0x201)
+#define CKA_ALWAYS_AUTHENTICATE		(0x202)
+#define CKA_WRAP_WITH_TRUSTED		(0x210)
+#define CKA_HW_FEATURE_TYPE		(0x300)
+#define CKA_RESET_ON_INIT		(0x301)
+#define CKA_HAS_RESET			(0x302)
+#define CKA_PIXEL_X			(0x400)
+#define CKA_PIXEL_Y			(0x401)
+#define CKA_RESOLUTION			(0x402)
+#define CKA_CHAR_ROWS			(0x403)
+#define CKA_CHAR_COLUMNS		(0x404)
+#define CKA_COLOR			(0x405)
+#define CKA_BITS_PER_PIXEL		(0x406)
+#define CKA_CHAR_SETS			(0x480)
+#define CKA_ENCODING_METHODS		(0x481)
+#define CKA_MIME_TYPES			(0x482)
+#define CKA_MECHANISM_TYPE		(0x500)
+#define CKA_REQUIRED_CMS_ATTRIBUTES	(0x501)
+#define CKA_DEFAULT_CMS_ATTRIBUTES	(0x502)
+#define CKA_SUPPORTED_CMS_ATTRIBUTES	(0x503)
+#define CKA_WRAP_TEMPLATE		(CKF_ARRAY_ATTRIBUTE | 0x211)
+#define CKA_UNWRAP_TEMPLATE		(CKF_ARRAY_ATTRIBUTE | 0x212)
+#define CKA_ALLOWED_MECHANISMS		(CKF_ARRAY_ATTRIBUTE | 0x600)
+#define CKA_VENDOR_DEFINED		((unsigned long) (1 << 31))
+
+
+struct ck_attribute
+{
+  ck_attribute_type_t type;
+  void *value;
+  unsigned long value_len;
+};
+
+
+struct ck_date
+{
+  unsigned char year[4];
+  unsigned char month[2];
+  unsigned char day[2];
+};
+
+
+typedef unsigned long ck_mechanism_type_t;
+
+#define CKM_RSA_PKCS_KEY_PAIR_GEN	(0)
+#define CKM_RSA_PKCS			(1)
+#define CKM_RSA_9796			(2)
+#define CKM_RSA_X_509			(3)
+#define CKM_MD2_RSA_PKCS		(4)
+#define CKM_MD5_RSA_PKCS		(5)
+#define CKM_SHA1_RSA_PKCS		(6)
+#define CKM_RIPEMD128_RSA_PKCS		(7)
+#define CKM_RIPEMD160_RSA_PKCS		(8)
+#define CKM_RSA_PKCS_OAEP		(9)
+#define CKM_RSA_X9_31_KEY_PAIR_GEN	(0xa)
+#define CKM_RSA_X9_31			(0xb)
+#define CKM_SHA1_RSA_X9_31		(0xc)
+#define CKM_RSA_PKCS_PSS		(0xd)
+#define CKM_SHA1_RSA_PKCS_PSS		(0xe)
+#define CKM_DSA_KEY_PAIR_GEN		(0x10)
+#define	CKM_DSA				(0x11)
+#define CKM_DSA_SHA1			(0x12)
+#define CKM_DH_PKCS_KEY_PAIR_GEN	(0x20)
+#define CKM_DH_PKCS_DERIVE		(0x21)
+#define	CKM_X9_42_DH_KEY_PAIR_GEN	(0x30)
+#define CKM_X9_42_DH_DERIVE		(0x31)
+#define CKM_X9_42_DH_HYBRID_DERIVE	(0x32)
+#define CKM_X9_42_MQV_DERIVE		(0x33)
+#define CKM_SHA256_RSA_PKCS		(0x40)
+#define CKM_SHA384_RSA_PKCS		(0x41)
+#define CKM_SHA512_RSA_PKCS		(0x42)
+#define CKM_SHA256_RSA_PKCS_PSS		(0x43)
+#define CKM_SHA384_RSA_PKCS_PSS		(0x44)
+#define CKM_SHA512_RSA_PKCS_PSS		(0x45)
+#define CKM_RC2_KEY_GEN			(0x100)
+#define CKM_RC2_ECB			(0x101)
+#define	CKM_RC2_CBC			(0x102)
+#define	CKM_RC2_MAC			(0x103)
+#define CKM_RC2_MAC_GENERAL		(0x104)
+#define CKM_RC2_CBC_PAD			(0x105)
+#define CKM_RC4_KEY_GEN			(0x110)
+#define CKM_RC4				(0x111)
+#define CKM_DES_KEY_GEN			(0x120)
+#define CKM_DES_ECB			(0x121)
+#define CKM_DES_CBC			(0x122)
+#define CKM_DES_MAC			(0x123)
+#define CKM_DES_MAC_GENERAL		(0x124)
+#define CKM_DES_CBC_PAD			(0x125)
+#define CKM_DES2_KEY_GEN		(0x130)
+#define CKM_DES3_KEY_GEN		(0x131)
+#define CKM_DES3_ECB			(0x132)
+#define CKM_DES3_CBC			(0x133)
+#define CKM_DES3_MAC			(0x134)
+#define CKM_DES3_MAC_GENERAL		(0x135)
+#define CKM_DES3_CBC_PAD		(0x136)
+#define CKM_CDMF_KEY_GEN		(0x140)
+#define CKM_CDMF_ECB			(0x141)
+#define CKM_CDMF_CBC			(0x142)
+#define CKM_CDMF_MAC			(0x143)
+#define CKM_CDMF_MAC_GENERAL		(0x144)
+#define CKM_CDMF_CBC_PAD		(0x145)
+#define CKM_MD2				(0x200)
+#define CKM_MD2_HMAC			(0x201)
+#define CKM_MD2_HMAC_GENERAL		(0x202)
+#define CKM_MD5				(0x210)
+#define CKM_MD5_HMAC			(0x211)
+#define CKM_MD5_HMAC_GENERAL		(0x212)
+#define CKM_SHA_1			(0x220)
+#define CKM_SHA_1_HMAC			(0x221)
+#define CKM_SHA_1_HMAC_GENERAL		(0x222)
+#define CKM_RIPEMD128			(0x230)
+#define CKM_RIPEMD128_HMAC		(0x231)
+#define CKM_RIPEMD128_HMAC_GENERAL	(0x232)
+#define CKM_RIPEMD160			(0x240)
+#define CKM_RIPEMD160_HMAC		(0x241)
+#define CKM_RIPEMD160_HMAC_GENERAL	(0x242)
+#define CKM_SHA256			(0x250)
+#define CKM_SHA256_HMAC			(0x251)
+#define CKM_SHA256_HMAC_GENERAL		(0x252)
+#define CKM_SHA384			(0x260)
+#define CKM_SHA384_HMAC			(0x261)
+#define CKM_SHA384_HMAC_GENERAL		(0x262)
+#define CKM_SHA512			(0x270)
+#define CKM_SHA512_HMAC			(0x271)
+#define CKM_SHA512_HMAC_GENERAL		(0x272)
+#define CKM_CAST_KEY_GEN		(0x300)
+#define CKM_CAST_ECB			(0x301)
+#define CKM_CAST_CBC			(0x302)
+#define CKM_CAST_MAC			(0x303)
+#define CKM_CAST_MAC_GENERAL		(0x304)
+#define CKM_CAST_CBC_PAD		(0x305)
+#define CKM_CAST3_KEY_GEN		(0x310)
+#define CKM_CAST3_ECB			(0x311)
+#define CKM_CAST3_CBC			(0x312)
+#define CKM_CAST3_MAC			(0x313)
+#define CKM_CAST3_MAC_GENERAL		(0x314)
+#define CKM_CAST3_CBC_PAD		(0x315)
+#define CKM_CAST5_KEY_GEN		(0x320)
+#define CKM_CAST128_KEY_GEN		(0x320)
+#define CKM_CAST5_ECB			(0x321)
+#define CKM_CAST128_ECB			(0x321)
+#define CKM_CAST5_CBC			(0x322)
+#define CKM_CAST128_CBC			(0x322)
+#define CKM_CAST5_MAC			(0x323)
+#define	CKM_CAST128_MAC			(0x323)
+#define CKM_CAST5_MAC_GENERAL		(0x324)
+#define CKM_CAST128_MAC_GENERAL		(0x324)
+#define CKM_CAST5_CBC_PAD		(0x325)
+#define CKM_CAST128_CBC_PAD		(0x325)
+#define CKM_RC5_KEY_GEN			(0x330)
+#define CKM_RC5_ECB			(0x331)
+#define CKM_RC5_CBC			(0x332)
+#define CKM_RC5_MAC			(0x333)
+#define CKM_RC5_MAC_GENERAL		(0x334)
+#define CKM_RC5_CBC_PAD			(0x335)
+#define CKM_IDEA_KEY_GEN		(0x340)
+#define CKM_IDEA_ECB			(0x341)
+#define	CKM_IDEA_CBC			(0x342)
+#define CKM_IDEA_MAC			(0x343)
+#define CKM_IDEA_MAC_GENERAL		(0x344)
+#define CKM_IDEA_CBC_PAD		(0x345)
+#define CKM_GENERIC_SECRET_KEY_GEN	(0x350)
+#define CKM_CONCATENATE_BASE_AND_KEY	(0x360)
+#define CKM_CONCATENATE_BASE_AND_DATA	(0x362)
+#define CKM_CONCATENATE_DATA_AND_BASE	(0x363)
+#define CKM_XOR_BASE_AND_DATA		(0x364)
+#define CKM_EXTRACT_KEY_FROM_KEY	(0x365)
+#define CKM_SSL3_PRE_MASTER_KEY_GEN	(0x370)
+#define CKM_SSL3_MASTER_KEY_DERIVE	(0x371)
+#define CKM_SSL3_KEY_AND_MAC_DERIVE	(0x372)
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH	(0x373)
+#define CKM_TLS_PRE_MASTER_KEY_GEN	(0x374)
+#define CKM_TLS_MASTER_KEY_DERIVE	(0x375)
+#define CKM_TLS_KEY_AND_MAC_DERIVE	(0x376)
+#define CKM_TLS_MASTER_KEY_DERIVE_DH	(0x377)
+#define CKM_SSL3_MD5_MAC		(0x380)
+#define CKM_SSL3_SHA1_MAC		(0x381)
+#define CKM_MD5_KEY_DERIVATION		(0x390)
+#define CKM_MD2_KEY_DERIVATION		(0x391)
+#define CKM_SHA1_KEY_DERIVATION		(0x392)
+#define CKM_PBE_MD2_DES_CBC		(0x3a0)
+#define CKM_PBE_MD5_DES_CBC		(0x3a1)
+#define CKM_PBE_MD5_CAST_CBC		(0x3a2)
+#define CKM_PBE_MD5_CAST3_CBC		(0x3a3)
+#define CKM_PBE_MD5_CAST5_CBC		(0x3a4)
+#define CKM_PBE_MD5_CAST128_CBC		(0x3a4)
+#define CKM_PBE_SHA1_CAST5_CBC		(0x3a5)
+#define CKM_PBE_SHA1_CAST128_CBC	(0x3a5)
+#define CKM_PBE_SHA1_RC4_128		(0x3a6)
+#define CKM_PBE_SHA1_RC4_40		(0x3a7)
+#define CKM_PBE_SHA1_DES3_EDE_CBC	(0x3a8)
+#define CKM_PBE_SHA1_DES2_EDE_CBC	(0x3a9)
+#define CKM_PBE_SHA1_RC2_128_CBC	(0x3aa)
+#define CKM_PBE_SHA1_RC2_40_CBC		(0x3ab)
+#define CKM_PKCS5_PBKD2			(0x3b0)
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC	(0x3c0)
+#define CKM_KEY_WRAP_LYNKS		(0x400)
+#define CKM_KEY_WRAP_SET_OAEP		(0x401)
+#define CKM_SKIPJACK_KEY_GEN		(0x1000)
+#define CKM_SKIPJACK_ECB64		(0x1001)
+#define CKM_SKIPJACK_CBC64		(0x1002)
+#define CKM_SKIPJACK_OFB64		(0x1003)
+#define CKM_SKIPJACK_CFB64		(0x1004)
+#define CKM_SKIPJACK_CFB32		(0x1005)
+#define CKM_SKIPJACK_CFB16		(0x1006)
+#define CKM_SKIPJACK_CFB8		(0x1007)
+#define CKM_SKIPJACK_WRAP		(0x1008)
+#define CKM_SKIPJACK_PRIVATE_WRAP	(0x1009)
+#define CKM_SKIPJACK_RELAYX		(0x100a)
+#define CKM_KEA_KEY_PAIR_GEN		(0x1010)
+#define CKM_KEA_KEY_DERIVE		(0x1011)
+#define CKM_FORTEZZA_TIMESTAMP		(0x1020)
+#define CKM_BATON_KEY_GEN		(0x1030)
+#define CKM_BATON_ECB128		(0x1031)
+#define CKM_BATON_ECB96			(0x1032)
+#define CKM_BATON_CBC128		(0x1033)
+#define CKM_BATON_COUNTER		(0x1034)
+#define CKM_BATON_SHUFFLE		(0x1035)
+#define CKM_BATON_WRAP			(0x1036)
+#define CKM_ECDSA_KEY_PAIR_GEN		(0x1040)
+#define CKM_EC_KEY_PAIR_GEN		(0x1040)
+#define CKM_ECDSA			(0x1041)
+#define CKM_ECDSA_SHA1			(0x1042)
+#define CKM_ECDH1_DERIVE		(0x1050)
+#define CKM_ECDH1_COFACTOR_DERIVE	(0x1051)
+#define CKM_ECMQV_DERIVE		(0x1052)
+#define CKM_JUNIPER_KEY_GEN		(0x1060)
+#define CKM_JUNIPER_ECB128		(0x1061)
+#define CKM_JUNIPER_CBC128		(0x1062)
+#define CKM_JUNIPER_COUNTER		(0x1063)
+#define CKM_JUNIPER_SHUFFLE		(0x1064)
+#define CKM_JUNIPER_WRAP		(0x1065)
+#define CKM_FASTHASH			(0x1070)
+#define CKM_AES_KEY_GEN			(0x1080)
+#define CKM_AES_ECB			(0x1081)
+#define CKM_AES_CBC			(0x1082)
+#define CKM_AES_MAC			(0x1083)
+#define CKM_AES_MAC_GENERAL		(0x1084)
+#define CKM_AES_CBC_PAD			(0x1085)
+#define CKM_DSA_PARAMETER_GEN		(0x2000)
+#define CKM_DH_PKCS_PARAMETER_GEN	(0x2001)
+#define CKM_X9_42_DH_PARAMETER_GEN	(0x2002)
+#define CKM_VENDOR_DEFINED		((unsigned long) (1 << 31))
+
+
+struct ck_mechanism
+{
+  ck_mechanism_type_t mechanism;
+  void *parameter;
+  unsigned long parameter_len;
+};
+
+
+struct ck_mechanism_info
+{
+  unsigned long min_key_size;
+  unsigned long max_key_size;
+  ck_flags_t flags;
+};
+
+#define CKF_HW			(1 << 0)
+#define CKF_ENCRYPT		(1 << 8)
+#define CKF_DECRYPT		(1 << 9)
+#define CKF_DIGEST		(1 << 10)
+#define CKF_SIGN		(1 << 11)
+#define CKF_SIGN_RECOVER	(1 << 12)
+#define CKF_VERIFY		(1 << 13)
+#define CKF_VERIFY_RECOVER	(1 << 14)
+#define CKF_GENERATE		(1 << 15)
+#define CKF_GENERATE_KEY_PAIR	(1 << 16)
+#define CKF_WRAP		(1 << 17)
+#define CKF_UNWRAP		(1 << 18)
+#define CKF_DERIVE		(1 << 19)
+#define CKF_EXTENSION		((unsigned long) (1 << 31))
+
+
+/* Flags for C_WaitForSlotEvent.  */
+#define CKF_DONT_BLOCK				(1)
+
+
+typedef unsigned long ck_rv_t;
+
+
+typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session,
+				ck_notification_t event, void *application);
+
+/* Forward reference.  */
+struct ck_function_list;
+
+#define _CK_DECLARE_FUNCTION(name, args)	\
+typedef ck_rv_t (*CK_ ## name) args;		\
+ck_rv_t CK_SPEC name args
+
+_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args));
+_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved));
+_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info));
+_CK_DECLARE_FUNCTION (C_GetFunctionList,
+		      (struct ck_function_list **function_list));
+
+_CK_DECLARE_FUNCTION (C_GetSlotList,
+		      (unsigned char token_present, ck_slot_id_t *slot_list,
+		       unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetSlotInfo,
+		      (ck_slot_id_t slot_id, struct ck_slot_info *info));
+_CK_DECLARE_FUNCTION (C_GetTokenInfo,
+		      (ck_slot_id_t slot_id, struct ck_token_info *info));
+_CK_DECLARE_FUNCTION (C_WaitForSlotEvent,
+		      (ck_flags_t flags, ck_slot_id_t *slot, void *reserved));
+_CK_DECLARE_FUNCTION (C_GetMechanismList,
+		      (ck_slot_id_t slot_id,
+		       ck_mechanism_type_t *mechanism_list,
+		       unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetMechanismInfo,
+		      (ck_slot_id_t slot_id, ck_mechanism_type_t type,
+		       struct ck_mechanism_info *info));
+_CK_DECLARE_FUNCTION (C_InitToken,
+		      (ck_slot_id_t slot_id, unsigned char *pin,
+		       unsigned long pin_len, unsigned char *label));
+_CK_DECLARE_FUNCTION (C_InitPIN,
+		      (ck_session_handle_t session, unsigned char *pin,
+		       unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_SetPIN,
+		      (ck_session_handle_t session, unsigned char *old_pin,
+		       unsigned long old_len, unsigned char *new_pin,
+		       unsigned long new_len));
+
+_CK_DECLARE_FUNCTION (C_OpenSession,
+		      (ck_slot_id_t slot_id, ck_flags_t flags,
+		       void *application, ck_notify_t notify,
+		       ck_session_handle_t *session));
+_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id));
+_CK_DECLARE_FUNCTION (C_GetSessionInfo,
+		      (ck_session_handle_t session,
+		       struct ck_session_info *info));
+_CK_DECLARE_FUNCTION (C_GetOperationState,
+		      (ck_session_handle_t session,
+		       unsigned char *operation_state,
+		       unsigned long *operation_state_len));
+_CK_DECLARE_FUNCTION (C_SetOperationState,
+		      (ck_session_handle_t session,
+		       unsigned char *operation_state,
+		       unsigned long operation_state_len,
+		       ck_object_handle_t encryption_key,
+		       ck_object_handle_t authentiation_key));
+_CK_DECLARE_FUNCTION (C_Login,
+		      (ck_session_handle_t session, ck_user_type_t user_type,
+		       unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_CreateObject,
+		      (ck_session_handle_t session,
+		       struct ck_attribute *templ,
+		       unsigned long count, ck_object_handle_t *object));
+_CK_DECLARE_FUNCTION (C_CopyObject,
+		      (ck_session_handle_t session, ck_object_handle_t object,
+		       struct ck_attribute *templ, unsigned long count,
+		       ck_object_handle_t *new_object));
+_CK_DECLARE_FUNCTION (C_DestroyObject,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object));
+_CK_DECLARE_FUNCTION (C_GetObjectSize,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       unsigned long *size));
+_CK_DECLARE_FUNCTION (C_GetAttributeValue,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_SetAttributeValue,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjectsInit,
+		      (ck_session_handle_t session,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjects,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t *object,
+		       unsigned long max_object_count,
+		       unsigned long *object_count));
+_CK_DECLARE_FUNCTION (C_FindObjectsFinal,
+		      (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_EncryptInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Encrypt,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *encrypted_data,
+		       unsigned long *encrypted_data_len));
+_CK_DECLARE_FUNCTION (C_EncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_EncryptFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *last_encrypted_part,
+		       unsigned long *last_encrypted_part_len));
+
+_CK_DECLARE_FUNCTION (C_DecryptInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Decrypt,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_data,
+		       unsigned long encrypted_data_len,
+		       unsigned char *data, unsigned long *data_len));
+_CK_DECLARE_FUNCTION (C_DecryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part, unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_DecryptFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *last_part,
+		       unsigned long *last_part_len));
+
+_CK_DECLARE_FUNCTION (C_DigestInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism));
+_CK_DECLARE_FUNCTION (C_Digest,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *digest,
+		       unsigned long *digest_len));
+_CK_DECLARE_FUNCTION (C_DigestUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_DigestKey,
+		      (ck_session_handle_t session, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_DigestFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *digest,
+		       unsigned long *digest_len));
+
+_CK_DECLARE_FUNCTION (C_SignInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Sign,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_SignFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignRecoverInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_SignRecover,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+
+_CK_DECLARE_FUNCTION (C_VerifyInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Verify,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_VerifyFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyRecoverInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_VerifyRecover,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long signature_len,
+		       unsigned char *data,
+		       unsigned long *data_len));
+
+_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part,
+		       unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_SignEncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part,
+		       unsigned long *part_len));
+
+_CK_DECLARE_FUNCTION (C_GenerateKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       struct ck_attribute *templ,
+		       unsigned long count,
+		       ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_GenerateKeyPair,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       struct ck_attribute *public_key_template,
+		       unsigned long public_key_attribute_count,
+		       struct ck_attribute *private_key_template,
+		       unsigned long private_key_attribute_count,
+		       ck_object_handle_t *public_key,
+		       ck_object_handle_t *private_key));
+_CK_DECLARE_FUNCTION (C_WrapKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t wrapping_key,
+		       ck_object_handle_t key,
+		       unsigned char *wrapped_key,
+		       unsigned long *wrapped_key_len));
+_CK_DECLARE_FUNCTION (C_UnwrapKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t unwrapping_key,
+		       unsigned char *wrapped_key,
+		       unsigned long wrapped_key_len,
+		       struct ck_attribute *templ,
+		       unsigned long attribute_count,
+		       ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_DeriveKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t base_key,
+		       struct ck_attribute *templ,
+		       unsigned long attribute_count,
+		       ck_object_handle_t *key));
+
+_CK_DECLARE_FUNCTION (C_SeedRandom,
+		      (ck_session_handle_t session, unsigned char *seed,
+		       unsigned long seed_len));
+_CK_DECLARE_FUNCTION (C_GenerateRandom,
+		      (ck_session_handle_t session,
+		       unsigned char *random_data,
+		       unsigned long random_len));
+
+_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session));
+
+
+struct ck_function_list
+{
+  struct ck_version version;
+  CK_C_Initialize C_Initialize;
+  CK_C_Finalize C_Finalize;
+  CK_C_GetInfo C_GetInfo;
+  CK_C_GetFunctionList C_GetFunctionList;
+  CK_C_GetSlotList C_GetSlotList;
+  CK_C_GetSlotInfo C_GetSlotInfo;
+  CK_C_GetTokenInfo C_GetTokenInfo;
+  CK_C_GetMechanismList C_GetMechanismList;
+  CK_C_GetMechanismInfo C_GetMechanismInfo;
+  CK_C_InitToken C_InitToken;
+  CK_C_InitPIN C_InitPIN;
+  CK_C_SetPIN C_SetPIN;
+  CK_C_OpenSession C_OpenSession;
+  CK_C_CloseSession C_CloseSession;
+  CK_C_CloseAllSessions C_CloseAllSessions;
+  CK_C_GetSessionInfo C_GetSessionInfo;
+  CK_C_GetOperationState C_GetOperationState;
+  CK_C_SetOperationState C_SetOperationState;
+  CK_C_Login C_Login;
+  CK_C_Logout C_Logout;
+  CK_C_CreateObject C_CreateObject;
+  CK_C_CopyObject C_CopyObject;
+  CK_C_DestroyObject C_DestroyObject;
+  CK_C_GetObjectSize C_GetObjectSize;
+  CK_C_GetAttributeValue C_GetAttributeValue;
+  CK_C_SetAttributeValue C_SetAttributeValue;
+  CK_C_FindObjectsInit C_FindObjectsInit;
+  CK_C_FindObjects C_FindObjects;
+  CK_C_FindObjectsFinal C_FindObjectsFinal;
+  CK_C_EncryptInit C_EncryptInit;
+  CK_C_Encrypt C_Encrypt;
+  CK_C_EncryptUpdate C_EncryptUpdate;
+  CK_C_EncryptFinal C_EncryptFinal;
+  CK_C_DecryptInit C_DecryptInit;
+  CK_C_Decrypt C_Decrypt;
+  CK_C_DecryptUpdate C_DecryptUpdate;
+  CK_C_DecryptFinal C_DecryptFinal;
+  CK_C_DigestInit C_DigestInit;
+  CK_C_Digest C_Digest;
+  CK_C_DigestUpdate C_DigestUpdate;
+  CK_C_DigestKey C_DigestKey;
+  CK_C_DigestFinal C_DigestFinal;
+  CK_C_SignInit C_SignInit;
+  CK_C_Sign C_Sign;
+  CK_C_SignUpdate C_SignUpdate;
+  CK_C_SignFinal C_SignFinal;
+  CK_C_SignRecoverInit C_SignRecoverInit;
+  CK_C_SignRecover C_SignRecover;
+  CK_C_VerifyInit C_VerifyInit;
+  CK_C_Verify C_Verify;
+  CK_C_VerifyUpdate C_VerifyUpdate;
+  CK_C_VerifyFinal C_VerifyFinal;
+  CK_C_VerifyRecoverInit C_VerifyRecoverInit;
+  CK_C_VerifyRecover C_VerifyRecover;
+  CK_C_DigestEncryptUpdate C_DigestEncryptUpdate;
+  CK_C_DecryptDigestUpdate C_DecryptDigestUpdate;
+  CK_C_SignEncryptUpdate C_SignEncryptUpdate;
+  CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate;
+  CK_C_GenerateKey C_GenerateKey;
+  CK_C_GenerateKeyPair C_GenerateKeyPair;
+  CK_C_WrapKey C_WrapKey;
+  CK_C_UnwrapKey C_UnwrapKey;
+  CK_C_DeriveKey C_DeriveKey;
+  CK_C_SeedRandom C_SeedRandom;
+  CK_C_GenerateRandom C_GenerateRandom;
+  CK_C_GetFunctionStatus C_GetFunctionStatus;
+  CK_C_CancelFunction C_CancelFunction;
+  CK_C_WaitForSlotEvent C_WaitForSlotEvent;
+};
+
+
+typedef ck_rv_t (*ck_createmutex_t) (void **mutex);
+typedef ck_rv_t (*ck_destroymutex_t) (void *mutex);
+typedef ck_rv_t (*ck_lockmutex_t) (void *mutex);
+typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex);
+
+
+struct ck_c_initialize_args
+{
+  ck_createmutex_t create_mutex;
+  ck_destroymutex_t destroy_mutex;
+  ck_lockmutex_t lock_mutex;
+  ck_unlockmutex_t unlock_mutex;
+  ck_flags_t flags;
+  void *reserved;
+};
+
+
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS	(1 << 0)
+#define CKF_OS_LOCKING_OK			(1 << 1)
+
+#define CKR_OK					(0)
+#define CKR_CANCEL				(1)
+#define CKR_HOST_MEMORY				(2)
+#define CKR_SLOT_ID_INVALID			(3)
+#define CKR_GENERAL_ERROR			(5)
+#define CKR_FUNCTION_FAILED			(6)
+#define CKR_ARGUMENTS_BAD			(7)
+#define CKR_NO_EVENT				(8)
+#define CKR_NEED_TO_CREATE_THREADS		(9)
+#define CKR_CANT_LOCK				(0xa)
+#define CKR_ATTRIBUTE_READ_ONLY			(0x10)
+#define CKR_ATTRIBUTE_SENSITIVE			(0x11)
+#define CKR_ATTRIBUTE_TYPE_INVALID		(0x12)
+#define CKR_ATTRIBUTE_VALUE_INVALID		(0x13)
+#define CKR_DATA_INVALID			(0x20)
+#define CKR_DATA_LEN_RANGE			(0x21)
+#define CKR_DEVICE_ERROR			(0x30)
+#define CKR_DEVICE_MEMORY			(0x31)
+#define CKR_DEVICE_REMOVED			(0x32)
+#define CKR_ENCRYPTED_DATA_INVALID		(0x40)
+#define CKR_ENCRYPTED_DATA_LEN_RANGE		(0x41)
+#define CKR_FUNCTION_CANCELED			(0x50)
+#define CKR_FUNCTION_NOT_PARALLEL		(0x51)
+#define CKR_FUNCTION_NOT_SUPPORTED		(0x54)
+#define CKR_KEY_HANDLE_INVALID			(0x60)
+#define CKR_KEY_SIZE_RANGE			(0x62)
+#define CKR_KEY_TYPE_INCONSISTENT		(0x63)
+#define CKR_KEY_NOT_NEEDED			(0x64)
+#define CKR_KEY_CHANGED				(0x65)
+#define CKR_KEY_NEEDED				(0x66)
+#define CKR_KEY_INDIGESTIBLE			(0x67)
+#define CKR_KEY_FUNCTION_NOT_PERMITTED		(0x68)
+#define CKR_KEY_NOT_WRAPPABLE			(0x69)
+#define CKR_KEY_UNEXTRACTABLE			(0x6a)
+#define CKR_MECHANISM_INVALID			(0x70)
+#define CKR_MECHANISM_PARAM_INVALID		(0x71)
+#define CKR_OBJECT_HANDLE_INVALID		(0x82)
+#define CKR_OPERATION_ACTIVE			(0x90)
+#define CKR_OPERATION_NOT_INITIALIZED		(0x91)
+#define CKR_PIN_INCORRECT			(0xa0)
+#define CKR_PIN_INVALID				(0xa1)
+#define CKR_PIN_LEN_RANGE			(0xa2)
+#define CKR_PIN_EXPIRED				(0xa3)
+#define CKR_PIN_LOCKED				(0xa4)
+#define CKR_SESSION_CLOSED			(0xb0)
+#define CKR_SESSION_COUNT			(0xb1)
+#define CKR_SESSION_HANDLE_INVALID		(0xb3)
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED	(0xb4)
+#define CKR_SESSION_READ_ONLY			(0xb5)
+#define CKR_SESSION_EXISTS			(0xb6)
+#define CKR_SESSION_READ_ONLY_EXISTS		(0xb7)
+#define CKR_SESSION_READ_WRITE_SO_EXISTS	(0xb8)
+#define CKR_SIGNATURE_INVALID			(0xc0)
+#define CKR_SIGNATURE_LEN_RANGE			(0xc1)
+#define CKR_TEMPLATE_INCOMPLETE			(0xd0)
+#define CKR_TEMPLATE_INCONSISTENT		(0xd1)
+#define CKR_TOKEN_NOT_PRESENT			(0xe0)
+#define CKR_TOKEN_NOT_RECOGNIZED		(0xe1)
+#define CKR_TOKEN_WRITE_PROTECTED		(0xe2)
+#define	CKR_UNWRAPPING_KEY_HANDLE_INVALID	(0xf0)
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE		(0xf1)
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT	(0xf2)
+#define CKR_USER_ALREADY_LOGGED_IN		(0x100)
+#define CKR_USER_NOT_LOGGED_IN			(0x101)
+#define CKR_USER_PIN_NOT_INITIALIZED		(0x102)
+#define CKR_USER_TYPE_INVALID			(0x103)
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN	(0x104)
+#define CKR_USER_TOO_MANY_TYPES			(0x105)
+#define CKR_WRAPPED_KEY_INVALID			(0x110)
+#define CKR_WRAPPED_KEY_LEN_RANGE		(0x112)
+#define CKR_WRAPPING_KEY_HANDLE_INVALID		(0x113)
+#define CKR_WRAPPING_KEY_SIZE_RANGE		(0x114)
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT	(0x115)
+#define CKR_RANDOM_SEED_NOT_SUPPORTED		(0x120)
+#define CKR_RANDOM_NO_RNG			(0x121)
+#define CKR_DOMAIN_PARAMS_INVALID		(0x130)
+#define CKR_BUFFER_TOO_SMALL			(0x150)
+#define CKR_SAVED_STATE_INVALID			(0x160)
+#define CKR_INFORMATION_SENSITIVE		(0x170)
+#define CKR_STATE_UNSAVEABLE			(0x180)
+#define CKR_CRYPTOKI_NOT_INITIALIZED		(0x190)
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED	(0x191)
+#define CKR_MUTEX_BAD				(0x1a0)
+#define CKR_MUTEX_NOT_LOCKED			(0x1a1)
+#define CKR_FUNCTION_REJECTED			(0x200)
+#define CKR_VENDOR_DEFINED			((unsigned long) (1 << 31))
+
+
+
+/* Compatibility layer.  */
+
+#ifdef CRYPTOKI_COMPAT
+
+#undef CK_DEFINE_FUNCTION
+#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name
+
+/* For NULL.  */
+#include <stddef.h>
+
+typedef unsigned char CK_BYTE;
+typedef unsigned char CK_CHAR;
+typedef unsigned char CK_UTF8CHAR;
+typedef unsigned char CK_BBOOL;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+typedef CK_BYTE *CK_BYTE_PTR;
+typedef CK_CHAR *CK_CHAR_PTR;
+typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR;
+typedef CK_ULONG *CK_ULONG_PTR;
+typedef void *CK_VOID_PTR;
+typedef void **CK_VOID_PTR_PTR;
+#define CK_FALSE 0
+#define CK_TRUE 1
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#endif
+
+typedef struct ck_version CK_VERSION;
+typedef struct ck_version *CK_VERSION_PTR;
+
+typedef struct ck_info CK_INFO;
+typedef struct ck_info *CK_INFO_PTR;
+
+typedef ck_slot_id_t *CK_SLOT_ID_PTR;
+
+typedef struct ck_slot_info CK_SLOT_INFO;
+typedef struct ck_slot_info *CK_SLOT_INFO_PTR;
+
+typedef struct ck_token_info CK_TOKEN_INFO;
+typedef struct ck_token_info *CK_TOKEN_INFO_PTR;
+
+typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR;
+
+typedef struct ck_session_info CK_SESSION_INFO;
+typedef struct ck_session_info *CK_SESSION_INFO_PTR;
+
+typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR;
+
+typedef ck_object_class_t *CK_OBJECT_CLASS_PTR;
+
+typedef struct ck_attribute CK_ATTRIBUTE;
+typedef struct ck_attribute *CK_ATTRIBUTE_PTR;
+
+typedef struct ck_date CK_DATE;
+typedef struct ck_date *CK_DATE_PTR;
+
+typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR;
+
+typedef struct ck_mechanism CK_MECHANISM;
+typedef struct ck_mechanism *CK_MECHANISM_PTR;
+
+typedef struct ck_mechanism_info CK_MECHANISM_INFO;
+typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR;
+
+typedef struct ck_function_list CK_FUNCTION_LIST;
+typedef struct ck_function_list *CK_FUNCTION_LIST_PTR;
+typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR;
+
+typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS;
+typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
+
+#define NULL_PTR NULL
+
+/* Delete the helper macros defined at the top of the file.  */
+#undef ck_flags_t
+#undef ck_version
+
+#undef ck_info
+#undef cryptoki_version
+#undef manufacturer_id
+#undef library_description
+#undef library_version
+
+#undef ck_notification_t
+#undef ck_slot_id_t
+
+#undef ck_slot_info
+#undef slot_description
+#undef hardware_version
+#undef firmware_version
+
+#undef ck_token_info
+#undef serial_number
+#undef max_session_count
+#undef session_count
+#undef max_rw_session_count
+#undef rw_session_count
+#undef max_pin_len
+#undef min_pin_len
+#undef total_public_memory
+#undef free_public_memory
+#undef total_private_memory
+#undef free_private_memory
+#undef utc_time
+
+#undef ck_session_handle_t
+#undef ck_user_type_t
+#undef ck_state_t
+
+#undef ck_session_info
+#undef slot_id
+#undef device_error
+
+#undef ck_object_handle_t
+#undef ck_object_class_t
+#undef ck_hw_feature_type_t
+#undef ck_key_type_t
+#undef ck_certificate_type_t
+#undef ck_attribute_type_t
+
+#undef ck_attribute
+#undef value
+#undef value_len
+
+#undef ck_date
+
+#undef ck_mechanism_type_t
+
+#undef ck_mechanism
+#undef parameter
+#undef parameter_len
+
+#undef ck_mechanism_info
+#undef min_key_size
+#undef max_key_size
+
+#undef ck_rv_t
+#undef ck_notify_t
+
+#undef ck_function_list
+
+#undef ck_createmutex_t
+#undef ck_destroymutex_t
+#undef ck_lockmutex_t
+#undef ck_unlockmutex_t
+
+#undef ck_c_initialize_args
+#undef create_mutex
+#undef destroy_mutex
+#undef lock_mutex
+#undef unlock_mutex
+#undef reserved
+
+#endif	/* CRYPTOKI_COMPAT */
+
+
+/* System dependencies.  */
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+#pragma pack(pop, cryptoki)
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif	/* PKCS11_H */

Added: trunk/gp11/tests/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/Makefile.am	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,39 @@
+UNIT_AUTO = \
+	unit-test-gp11-attributes.c \
+	unit-test-gp11-module.c \
+	unit-test-gp11-object.c \
+	unit-test-gp11-session.c \
+	unit-test-gp11-slot.c 
+
+
+UNIT_FLAGS = \
+	-I.. \
+	-DEXTERNAL_TEST
+	
+UNIT_PROMPT = 
+
+UNIT_LIBS = \
+	$(GIO_LIBS) \
+	$(top_builddir)/gp11/libgp11.la \
+	libgp11-test-module.la 
+	
+include $(top_srcdir)/tests/check.make
+
+# ------------------------------------------------------------------------
+
+lib_LTLIBRARIES = libgp11-test-module.la
+
+libgp11_test_module_la_LDFLAGS = \
+	-avoid-version
+
+libgp11_test_module_la_CFLAGS = \
+	-I. -I../ \
+	-I$(top_srcdir) \
+	$(GLIB_CFLAGS)
+
+libgp11_test_module_la_SOURCES = \
+	gp11-test-module.c
+
+libgp11_test_module_la_LIBADD = \
+	$(top_builddir)/gp11/libgp11.la
+	

Added: trunk/gp11/tests/gp11-test-module.c
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/gp11-test-module.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,1297 @@
+#include "config.h"
+
+#include "gp11.h"
+#include "pkcs11.h"
+
+#include <glib.h>
+
+#include <check.h>
+#include <string.h>
+
+static gboolean initialized = FALSE;
+static gchar *the_pin = NULL;
+
+typedef enum _Operation {
+	OP_FIND = 1,
+} Operation;
+
+typedef struct _Session {
+	CK_SESSION_HANDLE handle;
+	CK_SESSION_INFO info;
+	gboolean logged_in;
+	CK_USER_TYPE user_type;
+	GHashTable *objects;
+
+	Operation operation;
+	GList *matches;
+	
+} Session;
+
+static guint unique_identifier = 100;
+static GHashTable *the_sessions = NULL;
+static GHashTable *the_objects = NULL;
+
+/* 
+ * This is not a generic test module, it works in concert with the 
+ * unit-test-gp11-module.c
+ */ 
+
+static void
+free_session (gpointer data)
+{
+	Session *sess = (Session*)data;
+	if (sess)
+		g_hash_table_destroy (sess->objects);
+	g_free (sess);
+}
+
+static CK_RV
+test_C_Initialize (CK_VOID_PTR pInitArgs)
+{
+	GP11Attributes *attrs;
+	CK_C_INITIALIZE_ARGS_PTR args;
+	void *mutex;
+	CK_RV rv;
+	
+	fail_unless (initialized == FALSE, "Initialized same module twice, maybe module was not finalized, outstanding refs?");
+	fail_unless (pInitArgs != NULL, "Missing arguments");
+	
+	args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
+	fail_unless (args->CreateMutex != NULL, "Missing CreateMutex");
+	fail_unless (args->DestroyMutex != NULL, "Missing DestroyMutex");
+	fail_unless (args->LockMutex != NULL, "Missing LockMutex");
+	fail_unless (args->UnlockMutex != NULL, "Missing UnlockMutex");
+
+	fail_unless ((args->CreateMutex) (NULL) == CKR_ARGUMENTS_BAD, "CreateMutex succeeded wrong");
+	fail_unless ((args->DestroyMutex) (NULL) == CKR_MUTEX_BAD, "DestroyMutex succeeded wrong");
+	fail_unless ((args->LockMutex) (NULL) == CKR_MUTEX_BAD, "LockMutex succeeded wrong");
+	fail_unless ((args->UnlockMutex) (NULL) == CKR_MUTEX_BAD, "UnlockMutex succeeded wrong");
+
+	/* Try to create an actual mutex */
+	rv = (args->CreateMutex) (&mutex);
+	fail_unless (rv == CKR_OK, "CreateMutex failed");
+	fail_unless (mutex != NULL, "CreateMutex created null mutex");
+	
+	/* Try and lock the mutex */
+	rv = (args->LockMutex) (mutex);
+	fail_unless (rv == CKR_OK, "LockMutex failed");
+
+	/* Try and unlock the mutex */
+	rv = (args->UnlockMutex) (mutex);
+	fail_unless (rv == CKR_OK, "UnlockMutex failed");
+
+	/* Try and destroy the mutex */
+	rv = (args->DestroyMutex) (mutex);
+	fail_unless (rv == CKR_OK, "DestroyMutex failed");
+	
+	/* Flags should allow OS locking and os threads */
+	fail_unless ((args->flags & CKF_OS_LOCKING_OK) == CKF_OS_LOCKING_OK, "Invalid CKF_OS_LOCKING_OK flag");
+	fail_unless ((args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) == 0, "Invalid CKF_LIBRARY_CANT_CREATE_OS_THREADS flag");
+	
+	the_pin = g_strdup ("booo");
+	the_sessions = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_session);
+	the_objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)gp11_attributes_unref);
+	
+	/* Our token object */
+	attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                              CKA_LABEL, GP11_STRING, "TEST LABEL",
+	                              -1);
+	g_hash_table_insert (the_objects, GUINT_TO_POINTER (2), attrs);
+	
+	initialized = TRUE;
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_Finalize (CK_VOID_PTR pReserved)
+{
+	
+	
+	fail_unless (pReserved == NULL, "Invalid reserved pointer");
+	fail_unless (initialized == TRUE, "Finalize without being initialized");
+	
+	initialized = FALSE;
+	g_hash_table_destroy (the_objects);
+	the_objects = NULL;
+	
+	g_hash_table_destroy (the_sessions);
+	the_sessions = NULL;
+	
+	g_free (the_pin);
+	return CKR_OK;
+}
+
+const static CK_INFO TEST_INFO = {
+	{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+	"TEST MANUFACTURER              ",
+	0, 
+	"TEST LIBRARY                   ",
+	{ 45, 145 }
+};
+	
+static CK_RV
+test_C_GetInfo (CK_INFO_PTR pInfo)
+{
+	
+
+	fail_unless (pInfo != NULL, "Invalid pointer to GetInfo");
+	memcpy (pInfo, &TEST_INFO, sizeof (*pInfo));
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+	
+	
+	fail_unless (list != NULL, "Invalid pointer passed to GetFunctionList");
+	return C_GetFunctionList (list);
+}
+
+#define TEST_SLOT_ONE  52
+#define TEST_SLOT_TWO  134
+
+/* 
+ * Two slots 
+ *  ONE: token present
+ *  TWO: token not present
+ */
+
+static CK_RV
+test_C_GetSlotList (CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+	CK_ULONG count;
+	
+	
+	
+	fail_unless (pulCount != NULL, "Invalid pulCount");
+
+	count = tokenPresent ? 1 : 2;
+
+	/* Application only wants to know the number of slots. */
+	if (pSlotList == NULL) {
+		*pulCount = count; 
+		return CKR_OK;
+	}
+
+	if (*pulCount < count) {
+		fail_unless (*pulCount, "Passed in a bad count");
+		return CKR_BUFFER_TOO_SMALL;
+	}
+
+	*pulCount = count;
+	pSlotList[0] = TEST_SLOT_ONE;
+	if (!tokenPresent)
+		pSlotList[1] = TEST_SLOT_TWO;
+
+	return CKR_OK;
+}
+
+const static CK_SLOT_INFO TEST_INFO_ONE = {
+	"TEST SLOT                                                       ",
+	"TEST MANUFACTURER              ",
+	CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE,
+	{ 55, 155 },
+	{ 65, 165 },
+};
+
+const static CK_SLOT_INFO TEST_INFO_TWO = {
+	"TEST SLOT                                                       ",
+	"TEST MANUFACTURER              ",
+	CKF_REMOVABLE_DEVICE,
+	{ 55, 155 },
+	{ 65, 165 },
+};
+
+static CK_RV
+test_C_GetSlotInfo (CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
+{
+	
+	
+	fail_unless (pInfo != NULL, "Invalid pInfo");
+	
+	if (slotID == TEST_SLOT_ONE) {
+		memcpy (pInfo, &TEST_INFO_ONE, sizeof (*pInfo));
+		return CKR_OK;
+	} else if (slotID == TEST_SLOT_TWO) {
+		memcpy (pInfo, &TEST_INFO_TWO, sizeof (*pInfo));
+		return CKR_OK;
+	} else {
+		fail ("Invalid slot id");
+		return CKR_SLOT_ID_INVALID;
+	}
+}
+
+const static CK_TOKEN_INFO TEST_TOKEN_ONE = {
+	"TEST LABEL                      ",
+	"TEST MANUFACTURER               ",
+	"TEST MODEL      ",
+	"TEST SERIAL     ",
+	CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_CLOCK_ON_TOKEN | CKF_PROTECTED_AUTHENTICATION_PATH | CKF_TOKEN_INITIALIZED,
+	1,
+	2,
+	3,
+	4,
+	5,
+	6,
+	7,
+	8,
+	9,
+	10,
+	{ 75, 175 },
+	{ 85, 185 },
+	{ '1', '9', '9', '9', '0', '5', '2', '5', '0', '9', '1', '9', '5', '9', '0', '0' } 
+};
+
+static CK_RV
+test_C_GetTokenInfo (CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
+{
+	
+	
+	fail_unless (pInfo != NULL, "Invalid pInfo");
+	
+	if (slotID == TEST_SLOT_ONE) {
+		memcpy (pInfo, &TEST_TOKEN_ONE, sizeof (*pInfo));
+		return CKR_OK;
+	} else if (slotID == TEST_SLOT_TWO) {
+		return CKR_TOKEN_NOT_PRESENT;
+	} else {
+		fail ("Invalid slot id");
+		return CKR_SLOT_ID_INVALID;
+	}
+}
+
+/* 
+ * TWO mechanisms: 
+ *  RSA 
+ *  DSA
+ */
+
+static CK_RV
+test_C_GetMechanismList (CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
+                         CK_ULONG_PTR pulCount)
+{
+	
+	
+	fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+	fail_unless (pulCount != NULL, "Invalid pulCount");
+	
+	/* Application only wants to know the number of slots. */
+	if (pMechanismList == NULL) {
+		*pulCount = 2; 
+		return CKR_OK;
+	}
+
+	if (*pulCount != 2) {
+		fail_unless (*pulCount, "Passed in a bad count");
+		return CKR_BUFFER_TOO_SMALL;
+	}
+
+	pMechanismList[0] = CKM_RSA_PKCS;
+	pMechanismList[1] = CKM_DSA;
+	return CKR_OK;
+}
+
+static const CK_MECHANISM_INFO TEST_MECH_RSA = {
+	512, 4096, 0
+};
+
+static const CK_MECHANISM_INFO TEST_MECH_DSA = {
+	2048, 2048, 0
+};
+
+static CK_RV
+test_C_GetMechanismInfo (CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 
+                       CK_MECHANISM_INFO_PTR pInfo)
+{
+	
+
+	fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+	fail_unless (pInfo != NULL, "Invalid pInfo");
+
+	if (type == CKM_RSA_PKCS) {
+		memcpy (pInfo, &TEST_MECH_RSA, sizeof (*pInfo));
+		return CKR_OK;
+	} else if (type == CKM_DSA) {
+		memcpy (pInfo, &TEST_MECH_DSA, sizeof (*pInfo));
+		return CKR_OK;
+	} else {
+		fail ("Invalid type");
+		return CKR_MECHANISM_INVALID;
+	}
+}
+
+static CK_RV
+test_C_InitToken (CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, 
+                  CK_UTF8CHAR_PTR pLabel)
+{
+	fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+	fail_unless (pPin != NULL, "Invalid pPin");
+	fail_unless (strlen ("TEST PIN"), "Invalid ulPinLen");
+	fail_unless (strncmp ((gchar*)pPin, "TEST PIN", ulPinLen) == 0, "Invalid pPin string");
+	fail_unless (pLabel != NULL, "Invalid pLabel");
+	fail_unless (strcmp ((gchar*)pPin, "TEST LABEL") == 0, "Invalid pLabel string");
+
+	g_free (the_pin);
+	the_pin = g_strndup ((gchar*)pPin, ulPinLen);
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_WaitForSlotEvent (CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+#define TEST_RSA_KEY   257
+#define TEST_DSA_KEY   357
+
+#ifdef INCOMPLETE
+
+#define TEST_KEY \
+"(private-key (rsa " \
+"(n  #00B78758D55EBFFAB61D07D0DC49B5309A6F1DA2AE51C275DFC2370959BB81AC0C39093B1C618E396161A0DECEB8768D0FFB14F197B96C3DA14190EE0F20D51315#)" \
+"(e #010001#)" \
+"(d #108BCAC5FDD35812981E6EC5957D98E2AB76E4064C47B861D27C2CC322C50792313C852B4164A035B42D261F1A09F9FFE8F477F9F78FF2EABBDA6BA875C671D7#)" \
+"(p #00C357F11B19A18C66573D25D1E466D9AB8BCDDCDFE0B2E80BD46712C4BEC18EB7#)" \
+"(q #00F0843B90A60EF7034CA4BE80414ED9497CABCC685143B388013FF989CBB0E093#)" \
+"(u #12F2555F52EB56329A991CF0404B51C68AC921AD370A797860F550415FF987BD#)" \
+"))"
+#endif
+
+static CK_RV
+test_C_OpenSession (CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
+                    CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
+{
+	Session *sess;
+	
+	fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");
+	fail_unless (pApplication == NULL, "pApplication should be null");
+	fail_unless (Notify == NULL, "Notify should be null");
+	fail_unless (phSession != NULL, "Invalid phSession");
+	fail_unless ((flags & CKF_SERIAL_SESSION) == CKF_SERIAL_SESSION);
+
+	sess = g_new0 (Session, 1);
+	sess->handle = ++unique_identifier;
+	sess->info.flags = flags;
+	sess->info.slotID = slotID;
+	sess->info.state = 0;
+	sess->info.ulDeviceError = 1414;
+	sess->objects = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)gp11_attributes_unref);
+	*phSession = sess->handle;
+
+	g_hash_table_replace (the_sessions, GUINT_TO_POINTER (sess->handle), sess);
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_CloseSession (CK_SESSION_HANDLE hSession)
+{
+	Session *session;
+	
+	
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_unless (session != NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+	
+	g_hash_table_remove (the_sessions, GUINT_TO_POINTER (hSession));
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_CloseAllSessions (CK_SLOT_ID slotID)
+{
+	fail_unless (slotID == TEST_SLOT_ONE, "Invalid slotID");	
+
+	
+
+	g_hash_table_remove_all (the_sessions);
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_GetFunctionStatus (CK_SESSION_HANDLE hSession)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+static CK_RV
+test_C_CancelFunction (CK_SESSION_HANDLE hSession)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+static CK_RV
+test_C_GetSessionInfo (CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+	Session *session;
+
+	fail_unless (pInfo != NULL, "Invalid pInfo");
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_unless (session != NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	memcpy (pInfo, &session->info, sizeof (*pInfo));
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_InitPIN (CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, 
+                CK_ULONG ulPinLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SetPIN (CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
+             CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GetOperationState (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
+                        CK_ULONG_PTR pulOperationStateLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SetOperationState (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
+                        CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey,
+                        CK_OBJECT_HANDLE hAuthenticationKey)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_Login (CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+              CK_UTF8CHAR_PTR pPin, CK_ULONG pPinLen)
+{
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+	
+	fail_unless (pPinLen == strlen (the_pin), "Wrong PIN length");
+	fail_unless (strncmp ((gchar*)pPin, the_pin, pPinLen) == 0, "Wrong PIN");
+	fail_unless (userType == CKU_SO || userType == CKU_USER || userType == CKU_CONTEXT_SPECIFIC, "Bad user type");
+	fail_unless (session->logged_in == FALSE, "Already logged in");
+	
+	session->logged_in = TRUE;
+	session->user_type = userType;
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_Logout (CK_SESSION_HANDLE hSession)
+{
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_unless (session != NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	fail_unless (session->logged_in, "Not logged in");
+	session->logged_in = FALSE;
+	session->user_type = 0;
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_CreateObject (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+                     CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
+{
+	GP11Attributes *attrs;
+	Session *session;
+	gboolean token;
+	CK_ULONG i;
+
+	fail_if (phObject == NULL);
+	
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	attrs = gp11_attributes_new ();
+	for (i = 0; i < ulCount; ++i) 
+		gp11_attributes_add_data (attrs, pTemplate[i].type, pTemplate[i].pValue, pTemplate[i].ulValueLen);
+	
+	*phObject = ++unique_identifier;
+	if (gp11_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
+		g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phObject), attrs);
+	else
+		g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phObject), attrs);
+	
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_CopyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+                 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+                 CK_OBJECT_HANDLE_PTR phNewObject)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+
+static CK_RV
+test_C_DestroyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+	
+	if (!g_hash_table_remove (the_objects, GUINT_TO_POINTER (hObject)) && 
+	    !g_hash_table_remove (session->objects, GUINT_TO_POINTER (hObject))) {
+		fail ("no such object found");
+		return CKR_OBJECT_HANDLE_INVALID;
+	}
+		
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_GetObjectSize (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+                    CK_ULONG_PTR pulSize)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+                        CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+	CK_ATTRIBUTE_PTR result;
+	CK_RV ret = CKR_OK;
+	GP11Attributes *attrs;
+	GP11Attribute *attr;
+	Session *session;
+	CK_ULONG i;
+	
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+	
+	attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject));
+	if (!attrs)
+		attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject));
+	if (!attrs) {
+		fail ("invalid object handle passed");
+		return CKR_OBJECT_HANDLE_INVALID;
+	}
+
+	for (i = 0; i < ulCount; ++i) {
+		result = pTemplate + i;
+		attr = gp11_attributes_find (attrs, result->type);
+		if (!attr) {
+			result->ulValueLen = (CK_ULONG)-1;
+			ret = CKR_ATTRIBUTE_TYPE_INVALID;
+			continue;
+		}
+		
+		if (!result->pValue) {
+			result->ulValueLen = attr->length;
+			continue;
+		}
+		
+		if (result->ulValueLen >= attr->length) {
+			memcpy (result->pValue, attr->value, attr->length);
+			continue;
+		}
+		
+		result->ulValueLen = (CK_ULONG)-1;
+		ret = CKR_BUFFER_TOO_SMALL;
+	}
+	
+	return ret;
+}
+
+static CK_RV
+test_C_SetAttributeValue (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+                        CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+	Session *session;
+	CK_ATTRIBUTE_PTR set;
+	GP11Attributes *attrs;
+	GP11Attribute *attr;
+	CK_ULONG i;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	attrs = g_hash_table_lookup (the_objects, GUINT_TO_POINTER (hObject));
+	if (!attrs)
+		attrs = g_hash_table_lookup (session->objects, GUINT_TO_POINTER (hObject));
+	if (!attrs) {
+		fail ("invalid object handle passed");
+		return CKR_OBJECT_HANDLE_INVALID;
+	}
+
+	for (i = 0; i < ulCount; ++i) {
+		set = pTemplate + i;
+		attr = gp11_attributes_find (attrs, set->type);
+		if (!attr) {
+			gp11_attributes_add_data (attrs, set->type, set->pValue, set->ulValueLen);
+		} else {
+			gp11_attribute_clear (attr);
+			gp11_attribute_init (attr, set->type, set->pValue, set->ulValueLen);
+		}
+	}
+	
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_FindObjectsInit (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+                        CK_ULONG ulCount)
+{
+	GHashTableIter iter;
+	GP11Attributes *attrs;
+	GP11Attribute *attr;
+	CK_ATTRIBUTE_PTR match;
+	Session *session;
+	gpointer key, value;
+	gboolean matched = TRUE;
+	CK_ULONG i;
+	
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	if (session->operation != 0) {
+		fail ("invalid call to FindObjectsInit");
+		return CKR_OPERATION_ACTIVE;
+	}
+	
+	session->operation = OP_FIND;
+	
+	/* Token objects */
+	g_hash_table_iter_init (&iter, the_objects);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		attrs = (GP11Attributes*)value;
+		matched = TRUE;
+		for (i = 0; i < ulCount; ++i) {
+			match = pTemplate + i;
+			attr = gp11_attributes_find (attrs, match->type);
+			if (!attr) {
+				matched = FALSE;
+				break;
+			}
+			
+			if (attr->length != match->ulValueLen || 
+			    memcmp (attr->value, match->pValue, attr->length) != 0) {
+				matched = FALSE;
+				break;
+			}
+		}
+		
+		if (matched)
+			session->matches = g_list_prepend (session->matches, key);
+	}
+
+	/* session objects */
+	g_hash_table_iter_init (&iter, session->objects);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		attrs = (GP11Attributes*)value;
+		matched = TRUE;
+		for (i = 0; i < ulCount; ++i) {
+			match = pTemplate + i;
+			attr = gp11_attributes_find (attrs, match->type);
+			if (!attr) {
+				matched = FALSE;
+				break;
+			}
+			
+			if (attr->length != match->ulValueLen || 
+			    memcmp (attr->value, match->pValue, attr->length) != 0) {
+				matched = FALSE;
+				break;
+			}
+		}
+		
+		if (matched)
+			session->matches = g_list_prepend (session->matches, key);
+	}
+
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_FindObjects (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+                  CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+	Session *session;
+
+	fail_if (phObject == NULL);
+	fail_if (pulObjectCount == NULL);
+	fail_if (ulMaxObjectCount == 0);
+	
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+	
+	if (session->operation != OP_FIND) {
+		fail ("invalid call to FindObjects");
+		return CKR_OPERATION_NOT_INITIALIZED;
+	}
+	
+	*pulObjectCount = 0;
+	while (ulMaxObjectCount > 0 && session->matches) {
+		*phObject = GPOINTER_TO_UINT (session->matches->data);
+		++phObject;
+		--ulMaxObjectCount;
+		++(*pulObjectCount);
+		session->matches = g_list_remove (session->matches, session->matches->data);
+	}
+	
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_FindObjectsFinal (CK_SESSION_HANDLE hSession)
+{
+	
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+	
+	if (session->operation != OP_FIND) {
+		fail ("invalid call to FindObjectsFinal");
+		return CKR_OPERATION_NOT_INITIALIZED;
+	}
+	
+	session->operation = 0;
+	g_list_free (session->matches);
+	session->matches = NULL;
+	
+	return CKR_OK;
+}
+
+static CK_RV
+test_C_EncryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                    CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+	BEGIN_CALL (C_EncryptInit)
+		IN_SESSION (hSession)
+		IN_MECHANISM (pMechanism)
+		IN_HANDLE (hKey)
+	PROCESS_CALL ((hSession, pMechanism, hKey))
+	DONE_CALL
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+              CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+	BEGIN_CALL (C_Encrypt)
+		IN_SESSION (hSession)
+		IN_BYTE_ARRAY (pData, ulDataLen)
+	PROCESS_CALL ((hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen))
+		OUT_BYTE_ARRAY (pEncryptedData, pulEncryptedDataLen)
+	DONE_CALL
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_EncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+                    CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+                    CK_ULONG_PTR pulEncryptedPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_EncryptFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart,
+                   CK_ULONG_PTR pulLastEncryptedPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                  CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+	BEGIN_CALL (C_DecryptInit)
+		IN_SESSION (hSession)
+		IN_MECHANISM (pMechanism)
+		IN_HANDLE (hKey)
+	PROCESS_CALL ((hSession, pMechanism, hKey))
+	DONE_CALL
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Decrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
+              CK_ULONG pulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+	BEGIN_CALL (C_Decrypt)
+		IN_SESSION (hSession)
+		IN_BYTE_ARRAY (pEncryptedData, pulEncryptedDataLen)
+	PROCESS_CALL ((hSession, pEncryptedData, pulEncryptedDataLen, pData, pulDataLen))
+		OUT_BYTE_ARRAY (pData, pulDataLen)
+	DONE_CALL
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_DecryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
+                    CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
+                   CK_ULONG_PTR pulLastPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_Digest (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+             CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestKey (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
+                  CK_ULONG_PTR pulDigestLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+               CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Sign (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+            CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_SignUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+                CK_ULONG_PTR pulSignatureLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignRecoverInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                      CK_OBJECT_HANDLE hKey)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignRecover (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 
+                  CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                 CK_OBJECT_HANDLE hKey)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+	BEGIN_CALL (C_VerifyInit);
+		IN_SESSION (hSession)
+		IN_MECHANISM (pMechanism)
+		IN_HANDLE (hKey)
+	PROCESS_CALL ((hSession, pMechanism, hKey))
+	DONE_CALL
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_Verify (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+             CK_BYTE_PTR pSignature, CK_ULONG pulSignatureLen)
+{
+#ifdef INCOMPLETE
+	Session *session;
+
+	session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
+	fail_if (session == NULL, "No such session found");
+	if (!session)
+		return CKR_SESSION_HANDLE_INVALID;
+
+	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+	BEGIN_CALL (C_Verify)
+		IN_SESSION (hSession)
+		IN_BYTE_ARRAY (pData, ulDataLen)
+		IN_BYTE_ARRAY (pSignature, pulSignatureLen)
+	PROCESS_CALL ((hSession, pData, ulDataLen, pSignature, pulSignatureLen))
+	DONE_CALL
+#else 
+	fail ("Not yet implemented");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+}
+
+static CK_RV
+test_C_VerifyUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyFinal (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+                  CK_ULONG pulSignatureLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyRecoverInit (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                        CK_OBJECT_HANDLE hKey)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_VerifyRecover (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+                    CK_ULONG pulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DigestEncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+                          CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+                          CK_ULONG_PTR ulEncryptedPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptDigestUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
+                          CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, 
+                          CK_ULONG_PTR pulPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SignEncryptUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+                        CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
+                        CK_ULONG_PTR ulEncryptedPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DecryptVerifyUpdate (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
+                          CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, 
+                          CK_ULONG_PTR pulPartLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GenerateKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                  CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 
+                  CK_OBJECT_HANDLE_PTR phKey)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_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)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_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)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_UnwrapKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                CK_OBJECT_HANDLE pUnwrappingKey, CK_BYTE_PTR pWrappedKey,
+                CK_ULONG pulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
+                CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_DeriveKey (CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+                CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
+                CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_SeedRandom (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV
+test_C_GenerateRandom (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData,
+                      CK_ULONG ulRandomLen)
+{
+	fail ("Not yet used by library");
+	return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_FUNCTION_LIST functionList = {
+	{ 2, 11 },	/* version */
+	test_C_Initialize,
+	test_C_Finalize,
+	test_C_GetInfo,
+	test_C_GetFunctionList,
+	test_C_GetSlotList,
+	test_C_GetSlotInfo,
+	test_C_GetTokenInfo,
+	test_C_GetMechanismList,
+	test_C_GetMechanismInfo,
+	test_C_InitToken,
+	test_C_InitPIN,
+	test_C_SetPIN,
+	test_C_OpenSession,
+	test_C_CloseSession,
+	test_C_CloseAllSessions,
+	test_C_GetSessionInfo,
+	test_C_GetOperationState,
+	test_C_SetOperationState,
+	test_C_Login,
+	test_C_Logout,
+	test_C_CreateObject,
+	test_C_CopyObject,
+	test_C_DestroyObject,
+	test_C_GetObjectSize,
+	test_C_GetAttributeValue,
+	test_C_SetAttributeValue,
+	test_C_FindObjectsInit,
+	test_C_FindObjects,
+	test_C_FindObjectsFinal,
+	test_C_EncryptInit,
+	test_C_Encrypt,
+	test_C_EncryptUpdate,
+	test_C_EncryptFinal,
+	test_C_DecryptInit,
+	test_C_Decrypt,
+	test_C_DecryptUpdate,
+	test_C_DecryptFinal,
+	test_C_DigestInit,
+	test_C_Digest,
+	test_C_DigestUpdate,
+	test_C_DigestKey,
+	test_C_DigestFinal,
+	test_C_SignInit,
+	test_C_Sign,
+	test_C_SignUpdate,
+	test_C_SignFinal,
+	test_C_SignRecoverInit,
+	test_C_SignRecover,
+	test_C_VerifyInit,
+	test_C_Verify,
+	test_C_VerifyUpdate,
+	test_C_VerifyFinal,
+	test_C_VerifyRecoverInit,
+	test_C_VerifyRecover,
+	test_C_DigestEncryptUpdate,
+	test_C_DecryptDigestUpdate,
+	test_C_SignEncryptUpdate,
+	test_C_DecryptVerifyUpdate,
+	test_C_GenerateKey,
+	test_C_GenerateKeyPair,
+	test_C_WrapKey,
+	test_C_UnwrapKey,
+	test_C_DeriveKey,
+	test_C_SeedRandom,
+	test_C_GenerateRandom,
+	test_C_GetFunctionStatus,
+	test_C_CancelFunction,
+	test_C_WaitForSlotEvent
+};
+
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+	if (!list)
+		return CKR_ARGUMENTS_BAD;
+
+	*list = &functionList;
+	return CKR_OK;
+}

Added: trunk/gp11/tests/gp11-test.h
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/gp11-test.h	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,22 @@
+#ifndef TESTGP11HELPERS_H_
+#define TESTGP11HELPERS_H_
+
+#include "gp11.h"
+
+#define FAIL_RES(res, e) do { \
+	fail_if (res ? TRUE : FALSE, "should have failed"); \
+	fail_unless ((e) && (e)->message, "error should be set"); \
+	g_clear_error (&e); \
+	} while (0)
+
+#define SUCCESS_RES(res, err) do { \
+	if (!res) g_printerr ("error: %s\n", err && err->message ? err->message : ""); \
+	fail_unless (res ? TRUE : FALSE, "should have succeeded"); \
+	g_clear_error (&err); \
+	} while(0)
+
+
+#define WAIT_UNTIL(cond) \
+	while(!cond) g_main_iteration (TRUE);
+
+#endif /*TESTGP11HELPERS_H_*/

Added: trunk/gp11/tests/unit-test-gp11-attributes.c
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/unit-test-gp11-attributes.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,440 @@
+
+#include <check.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+#include "gp11-test.h"
+
+#define ATTR_TYPE 55
+#define ATTR_DATA "TEST DATA"
+#define N_ATTR_DATA 9
+
+DEFINE_TEST(init_memory)
+{
+	GP11Attribute attr;
+	
+	fail_if (sizeof (attr) != sizeof (CK_ATTRIBUTE));
+	
+	gp11_attribute_init (&attr, ATTR_TYPE, ATTR_DATA, N_ATTR_DATA);
+	fail_unless (attr.type == ATTR_TYPE);
+	fail_unless (attr.length == N_ATTR_DATA);
+	fail_unless (memcmp (attr.value, ATTR_DATA, attr.length) == 0);
+	
+	gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_boolean)
+{
+	GP11Attribute attr;
+
+	gp11_attribute_init_boolean (&attr, ATTR_TYPE, TRUE);
+	fail_unless (attr.type == ATTR_TYPE);
+	fail_unless (attr.length == sizeof (CK_BBOOL));
+	fail_unless (*((CK_BBOOL*)attr.value) == CK_TRUE);
+
+	gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_date)
+{
+	GP11Attribute attr;
+	CK_DATE ck_date;
+	GDate *date;
+
+	date = g_date_new_dmy(05, 06, 1960);
+	memcpy (ck_date.year, "1960", 4);
+	memcpy (ck_date.month, "06", 2);
+	memcpy (ck_date.day, "05", 2);
+	gp11_attribute_init_date (&attr, ATTR_TYPE, date);
+	g_date_free (date);
+	fail_unless (attr.type == ATTR_TYPE);
+	fail_unless (attr.length == sizeof (CK_DATE));
+	fail_unless (memcmp (attr.value, &ck_date, attr.length) == 0);
+	
+	gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_ulong)
+{
+	GP11Attribute attr;
+	
+	gp11_attribute_init_ulong (&attr, ATTR_TYPE, 88);
+	fail_unless (attr.type == ATTR_TYPE);
+	fail_unless (attr.length == sizeof (CK_ULONG));
+	fail_unless (*((CK_ULONG*)attr.value) == 88);
+
+	gp11_attribute_clear (&attr);
+}
+
+DEFINE_TEST(init_string)
+{
+	GP11Attribute attr;
+	
+	gp11_attribute_init_string (&attr, ATTR_TYPE, "a test string");
+	fail_unless (attr.type == ATTR_TYPE);
+	fail_unless (attr.length == strlen ("a test string"));
+	fail_unless (memcmp (attr.value, "a test string", attr.length) == 0);
+
+	gp11_attribute_clear (&attr);
+}
+	
+DEFINE_TEST(new_memory)
+{
+	GP11Attribute *attr;
+	
+	attr = gp11_attribute_new (ATTR_TYPE, ATTR_DATA, N_ATTR_DATA);
+	fail_unless (attr->type == ATTR_TYPE);
+	fail_unless (attr->length == N_ATTR_DATA);
+	fail_unless (memcmp (attr->value, ATTR_DATA, attr->length) == 0);
+	
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_boolean)
+{
+	GP11Attribute *attr;
+
+	attr = gp11_attribute_new_boolean (ATTR_TYPE, TRUE);
+	fail_unless (attr->type == ATTR_TYPE);
+	fail_unless (attr->length == sizeof (CK_BBOOL));
+	fail_unless (*((CK_BBOOL*)attr->value) == CK_TRUE);
+
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_date)
+{
+	GP11Attribute *attr;
+	CK_DATE ck_date;
+	GDate *date;
+
+	date = g_date_new_dmy(05, 06, 1800);
+	memcpy (ck_date.year, "1800", 4);
+	memcpy (ck_date.month, "06", 2);
+	memcpy (ck_date.day, "05", 2);
+	attr = gp11_attribute_new_date (ATTR_TYPE, date);
+	g_date_free (date);
+	fail_unless (attr->type == ATTR_TYPE);
+	fail_unless (attr->length == sizeof (CK_DATE));
+	fail_unless (memcmp (attr->value, &ck_date, attr->length) == 0);
+	
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_ulong)
+{
+	GP11Attribute *attr;
+	
+	attr = gp11_attribute_new_ulong (ATTR_TYPE, 88);
+	fail_unless (attr->type == ATTR_TYPE);
+	fail_unless (attr->length == sizeof (CK_ULONG));
+	fail_unless (*((CK_ULONG*)attr->value) == 88);
+
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(new_string)
+{
+	GP11Attribute *attr;
+	
+	attr = gp11_attribute_new_string (ATTR_TYPE, "a test string");
+	fail_unless (attr->type == ATTR_TYPE);
+	fail_unless (attr->length == strlen ("a test string"));
+	fail_unless (memcmp (attr->value, "a test string", attr->length) == 0);
+
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_boolean)
+{
+	GP11Attribute *attr;
+
+	attr = gp11_attribute_new_boolean (ATTR_TYPE, TRUE);
+	fail_unless (gp11_attribute_get_boolean (attr) == TRUE);
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_date)
+{
+	GP11Attribute *attr;
+	CK_DATE ck_date;
+	GDate *date, *date2;
+
+	date = g_date_new_dmy(05, 06, 1800);
+	memcpy (ck_date.year, "1800", 4);
+	memcpy (ck_date.month, "06", 2);
+	memcpy (ck_date.day, "05", 2);
+	attr = gp11_attribute_new_date (ATTR_TYPE, date);
+	date2 = gp11_attribute_get_date (attr);
+	fail_unless (g_date_compare (date, date2) == 0);
+	g_date_free (date);
+	g_date_free (date2);
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_ulong)
+{
+	GP11Attribute *attr;
+	
+	attr = gp11_attribute_new_ulong (ATTR_TYPE, 88);
+	fail_unless (gp11_attribute_get_ulong (attr) == 88);
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(get_string)
+{
+	GP11Attribute *attr;
+	gchar *value;
+	
+	attr = gp11_attribute_new_string (ATTR_TYPE, "a test string");
+	value = gp11_attribute_get_string (attr);
+	fail_unless (strcmp ("a test string", value) == 0);
+	g_free (value);
+	gp11_attribute_free (attr);
+
+	/* Should be able to store null strings */
+	attr = gp11_attribute_new_string (ATTR_TYPE, NULL);
+	value = gp11_attribute_get_string (attr);
+	fail_unless (value == NULL);
+	gp11_attribute_free (attr);
+}
+
+DEFINE_TEST(dup_attribute)
+{
+	GP11Attribute attr, *dup;
+
+	gp11_attribute_init_ulong (&attr, ATTR_TYPE, 88);
+	dup = gp11_attribute_dup (&attr);
+	gp11_attribute_clear (&attr);
+	fail_unless (gp11_attribute_get_ulong (dup) == 88);
+	fail_unless (dup->type == ATTR_TYPE);
+	gp11_attribute_free (dup);
+	
+	/* Should be able to dup null */
+	dup = gp11_attribute_dup (NULL);
+	fail_if (dup != NULL);
+}
+
+DEFINE_TEST(copy_attribute)
+{
+	GP11Attribute attr, copy;
+
+	gp11_attribute_init_ulong (&attr, ATTR_TYPE, 88);
+	gp11_attribute_init_copy (&copy, &attr);
+	gp11_attribute_clear (&attr);
+	fail_unless (gp11_attribute_get_ulong (&copy) == 88);
+	fail_unless (copy.type == ATTR_TYPE);
+	gp11_attribute_clear (&copy);
+}
+
+DEFINE_TEST(new_attributes)
+{
+	GP11Attributes *attrs;
+	
+	attrs = gp11_attributes_new ();
+	fail_if (attrs == NULL);
+	fail_unless (gp11_attributes_count (attrs) == 0);
+	
+	gp11_attributes_ref (attrs);
+	gp11_attributes_unref (attrs);
+	
+	gp11_attributes_unref (attrs);
+	
+	/* Can unref NULL */
+	gp11_attributes_unref (NULL);
+}
+
+static void
+test_attributes_contents (GP11Attributes *attrs)
+{
+	GP11Attribute *attr;
+	gchar *value;
+	GDate *date, *check;
+	
+	fail_if (attrs == NULL);
+	fail_unless (gp11_attributes_count (attrs) == 5);
+	
+	attr = gp11_attributes_at (attrs, 0);
+	fail_unless (attr->type == 0);
+	fail_unless (gp11_attribute_get_boolean (attr) == TRUE);
+	
+	attr = gp11_attributes_at (attrs, 1);
+	fail_unless (attr->type == 101);
+	fail_unless (gp11_attribute_get_ulong (attr) == 888);
+
+	attr = gp11_attributes_at (attrs, 2);
+	fail_unless (attr->type == 202);
+	value = gp11_attribute_get_string (attr);
+	fail_unless (strcmp (value, "string") == 0);
+	g_free (value);
+
+	attr = gp11_attributes_at (attrs, 3);
+	fail_unless (attr->type == 303);
+	check = g_date_new_dmy (11, 12, 2008);
+	date = gp11_attribute_get_date (attr);
+	fail_unless (g_date_compare (date, check) == 0);
+	g_date_free (date);
+	g_date_free (check);
+	
+	attr = gp11_attributes_at (attrs, 4);
+	fail_unless (attr->type == 404);
+	fail_unless (attr->length == N_ATTR_DATA);
+	fail_unless (memcmp (attr->value, ATTR_DATA, N_ATTR_DATA) == 0);
+}
+
+DEFINE_TEST(newv_attributes)
+{
+	GDate *date = g_date_new_dmy (11, 12, 2008);
+	GP11Attributes *attrs;
+	attrs = gp11_attributes_newv (0, GP11_BOOLEAN, TRUE, 
+	                              101, GP11_ULONG, 888,
+	                              202, GP11_STRING, "string",
+	                              303, GP11_DATE, date,
+	                              404, N_ATTR_DATA, ATTR_DATA,
+	                              -1);
+	g_date_free (date);
+
+	test_attributes_contents (attrs);
+	gp11_attributes_unref (attrs);
+	
+	/* An empty one */
+	attrs = gp11_attributes_newv (-1);
+	gp11_attributes_unref (attrs);
+}
+
+static GP11Attributes*
+help_attributes_valist (int dummy, ...)
+{
+	GP11Attributes *attrs;
+	va_list va;
+	
+	va_start (va, dummy);
+	attrs = gp11_attributes_new_valist (va);
+	va_end (va);
+	
+	return attrs;
+}
+
+DEFINE_TEST(new_valist_attributes)
+{
+	GP11Attributes *attrs;
+	GDate *date = g_date_new_dmy (11, 12, 2008);
+	
+	attrs = help_attributes_valist (232434243, /* Not used */
+	                                0, GP11_BOOLEAN, TRUE, 
+	                                101, GP11_ULONG, 888,
+	                                202, GP11_STRING, "string",
+	                                303, GP11_DATE, date,
+	                                404, N_ATTR_DATA, ATTR_DATA,
+	                                -1);
+	
+	g_date_free (date);
+	test_attributes_contents (attrs);
+	gp11_attributes_unref (attrs);	
+}
+
+DEFINE_ABORT(bad_length)
+{
+	GP11Attributes *attrs;
+	
+	/* We should catch this with a warning */
+	attrs = gp11_attributes_newv (1, G_MAXSSIZE + 500U, GP11_ULONG, "invalid data",
+	                              -1);
+	
+	gp11_attributes_unref (attrs);
+}
+
+DEFINE_TEST(add_data_attributes)
+{
+	GP11Attributes *attrs;
+	GDate *date = g_date_new_dmy (11, 12, 2008);
+	attrs = gp11_attributes_new ();
+	gp11_attributes_add_boolean (attrs, 0, TRUE);
+	gp11_attributes_add_ulong (attrs, 101, 888);
+	gp11_attributes_add_string (attrs, 202, "string");
+	gp11_attributes_add_date (attrs, 303, date);
+	g_date_free (date);
+	gp11_attributes_add_data (attrs, 404, ATTR_DATA, N_ATTR_DATA);
+	test_attributes_contents (attrs);
+	gp11_attributes_unref (attrs);
+}
+
+DEFINE_TEST(add_attributes)
+{
+	GP11Attributes *attrs;
+	GP11Attribute attr;
+	
+	GDate *date = g_date_new_dmy (11, 12, 2008);
+	attrs = gp11_attributes_new ();
+	
+	gp11_attribute_init_boolean (&attr, 0, TRUE);
+	gp11_attributes_add (attrs, &attr);
+	gp11_attribute_clear (&attr);
+	
+	gp11_attribute_init_ulong (&attr, 101, 888);
+	gp11_attributes_add (attrs, &attr);
+	gp11_attribute_clear (&attr);
+	
+	gp11_attribute_init_string (&attr, 202, "string");
+	gp11_attributes_add (attrs, &attr);
+	gp11_attribute_clear (&attr);
+
+	gp11_attribute_init_date (&attr, 303, date);
+	gp11_attributes_add (attrs, &attr);
+	gp11_attribute_clear (&attr);
+	g_date_free (date);
+	
+	gp11_attribute_init (&attr, 404, ATTR_DATA, N_ATTR_DATA);
+	gp11_attributes_add (attrs, &attr);
+	gp11_attribute_clear (&attr);
+	
+	test_attributes_contents (attrs);
+	gp11_attributes_unref (attrs);
+}
+
+
+DEFINE_TEST(find_attributes)
+{
+	GP11Attribute *attr;
+	GDate *check, *date = g_date_new_dmy (13, 12, 2008);
+	gboolean bvalue, ret;
+	gulong uvalue;
+	gchar *svalue;
+	
+	GP11Attributes *attrs;
+	attrs = gp11_attributes_newv (0, GP11_BOOLEAN, TRUE, 
+	                              101, GP11_ULONG, 888,
+	                              202, GP11_STRING, "string",
+	                              303, GP11_DATE, date,
+	                              404, N_ATTR_DATA, ATTR_DATA,
+	                              -1);
+
+	attr = gp11_attributes_find (attrs, 404);
+	fail_if (attr == NULL);
+	fail_unless (attr->length == N_ATTR_DATA);
+	fail_unless (memcmp (attr->value, ATTR_DATA, N_ATTR_DATA) == 0);
+	
+	ret = gp11_attributes_find_boolean (attrs, 0, &bvalue);
+	fail_unless (ret == TRUE);
+	fail_unless (bvalue == TRUE);
+	
+	ret = gp11_attributes_find_ulong (attrs, 101, &uvalue);
+	fail_unless (ret == TRUE);
+	fail_unless (uvalue == 888);
+
+	ret = gp11_attributes_find_string (attrs, 202, &svalue);
+	fail_unless (ret == TRUE);
+	fail_if (svalue == NULL);
+	fail_unless (strcmp (svalue, "string") == 0);
+	g_free (svalue);
+	
+	ret = gp11_attributes_find_date (attrs, 303, &check);
+	fail_unless (ret == TRUE);
+	fail_if (check == NULL);
+	fail_unless (g_date_compare (date, check) == 0);
+	g_date_free (check);
+	
+	gp11_attributes_unref (attrs);
+}

Added: trunk/gp11/tests/unit-test-gp11-module.c
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/unit-test-gp11-module.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,67 @@
+
+#include <check.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+
+DEFINE_SETUP(load_module)
+{
+	GError *err = NULL;
+
+	/* Successful load */
+	module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+	SUCCESS_RES (module, err);
+}
+
+DEFINE_TEARDOWN(load_module)
+{
+	g_object_unref (module);
+}
+
+DEFINE_TEST(invalid_modules)
+{
+	GP11Module *invalid;
+	GError *err = NULL;
+	
+	/* Shouldn't be able to load modules */
+	invalid = gp11_module_initialize ("blah-blah-non-existant", &err);
+	FAIL_RES (invalid, err);
+
+	/* Shouldn't be able to load any file successfully */ 
+	invalid = gp11_module_initialize ("/usr/lib/libm.so", &err);
+	FAIL_RES (invalid, err);
+
+}
+
+DEFINE_TEST(module_props)
+{
+	gchar *path;
+
+	g_object_get (module, "module-path", &path, NULL);
+	fail_unless (path != NULL, "no module-path");
+	fail_unless (strcmp (".libs/libgp11-test-module.so", path) == 0, "module path wrong");
+	g_free (path);
+}
+
+DEFINE_TEST(module_info)
+{
+	GP11ModuleInfo *info;
+	
+	info = gp11_module_get_info (module);
+	fail_unless (info != NULL, "no module info");
+	
+	fail_unless (info->pkcs11_version_major == CRYPTOKI_VERSION_MAJOR, "wrong major version"); 
+	fail_unless (info->pkcs11_version_minor == CRYPTOKI_VERSION_MINOR, "wrong minor version"); 
+	fail_unless (strcmp ("TEST MANUFACTURER", info->manufacturer_id) == 0);
+	fail_unless (strcmp ("TEST LIBRARY", info->library_description) == 0);
+	fail_unless (0 == info->flags);
+	fail_unless (45 == info->library_version_major);
+	fail_unless (145 == info->library_version_minor);
+	
+	gp11_module_info_free (info);
+}

Added: trunk/gp11/tests/unit-test-gp11-object.c
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/unit-test-gp11-object.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,369 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include <glib.h>
+
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+static GP11Slot *slot = NULL;
+static GP11Session *session = NULL;
+static GP11Object *object = NULL;
+
+DEFINE_SETUP(prep_object)
+{
+	GError *err = NULL;
+	GList *slots;
+	
+	/* Successful load */
+	module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+	SUCCESS_RES (module, err);
+	
+	slots = gp11_module_get_slots (module, TRUE);
+	fail_if (slots == NULL);
+	
+	slot = GP11_SLOT (slots->data);
+	g_object_ref (slot);
+	gp11_list_unref_free (slots);
+
+	session = gp11_slot_open_session (slot, 0, &err);
+	SUCCESS_RES(session, err);
+	
+	/* Our module always exports a token object with this */
+	object = gp11_object_from_handle (session, 2);
+	fail_if (object == NULL);
+}
+
+DEFINE_TEARDOWN(prep_object)
+{
+	g_object_unref (object);
+	g_object_unref (session); 
+	g_object_unref (slot);
+	g_object_unref (module);
+}
+
+DEFINE_TEST(object_props)
+{
+	GP11Session *sess;
+	GP11Module *mod;
+	CK_OBJECT_HANDLE handle;
+	g_object_get (object, "session", &sess, "module", &mod, "handle", &handle, NULL);
+	fail_unless (sess == session);
+	g_object_unref (session);
+	fail_unless (module == mod);
+	g_object_unref (mod);
+	fail_unless (handle == 2);
+}
+
+static void 
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	*((GAsyncResult**)user_data) = result;
+	g_object_ref (result);
+}
+
+DEFINE_TEST(create_object)
+{
+	GAsyncResult *result = NULL;
+	GP11Attributes *attrs;
+	GP11Object *object;
+	CK_OBJECT_HANDLE last_handle;
+	GError *err = NULL;
+	
+	/* Using simple */
+	object = gp11_session_create_object (session, &err, 
+	                                     CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                                     CKA_LABEL, GP11_STRING, "TEST LABEL",
+	                                     CKA_TOKEN, GP11_BOOLEAN, CK_FALSE,
+	                                     CKA_VALUE, 4, "BLAH",
+	                                     -1);
+	SUCCESS_RES (object, err);
+	fail_unless (GP11_IS_OBJECT (object));
+	
+	if (object) {
+		last_handle = object->handle;
+		g_object_unref (object);
+	}
+	
+	/* Using full */
+	attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                              CKA_LABEL, GP11_STRING, "TEST LABEL",
+	                              CKA_TOKEN, GP11_BOOLEAN, CK_FALSE,
+	                              CKA_VALUE, 4, "BLAH",
+	                              -1);
+	
+	object = gp11_session_create_object_full (session, attrs, NULL, &err);
+	fail_unless (GP11_IS_OBJECT (object));
+	SUCCESS_RES (object, err);
+	
+	if (object) {
+		fail_if (last_handle == object->handle);
+		last_handle = object->handle;
+		g_object_unref (object);
+	}
+
+	/* Using async */
+	gp11_session_create_object_async (session, attrs, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+	
+	object = gp11_session_create_object_finish (session, result, &err);
+	g_object_unref (result);
+	SUCCESS_RES (object, err);
+	fail_unless (GP11_IS_OBJECT (object));
+	
+	if (object)
+		g_object_unref (object);
+	gp11_attributes_unref (attrs);
+}
+
+DEFINE_TEST(destroy_object)
+{
+	GAsyncResult *result = NULL;
+	GP11Object *object;
+	GError *err = NULL;
+	gboolean ret;
+	
+	/* Using simple */
+	object = gp11_session_create_object (session, &err, 
+	                                     CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                                     CKA_LABEL, GP11_STRING, "TEST OBJECT",
+	                                     CKA_TOKEN, GP11_BOOLEAN, CK_TRUE,
+	                                     -1);
+	SUCCESS_RES (object, err);
+	fail_unless (GP11_IS_OBJECT (object));
+	
+	if (!object)
+		return;
+	
+	ret = gp11_object_destroy (object, &err);
+	SUCCESS_RES (ret, err);
+	g_object_unref (object);
+
+	/* Using full */
+	object = gp11_session_create_object (session, &err, 
+	                                     CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                                     CKA_LABEL, GP11_STRING, "TEST OBJECT",
+	                                     CKA_TOKEN, GP11_BOOLEAN, CK_TRUE,
+	                                     -1);
+	SUCCESS_RES (object, err);
+	fail_unless (GP11_IS_OBJECT (object));
+	
+	if (!object)
+		return;
+	
+	ret = gp11_object_destroy_full (object, NULL, &err);
+	SUCCESS_RES (ret, err);
+	g_object_unref (object);
+	
+	/* Using async */
+	object = gp11_session_create_object (session, &err, 
+	                                     CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                                     CKA_LABEL, GP11_STRING, "TEST OBJECT",
+	                                     CKA_TOKEN, GP11_BOOLEAN, CK_TRUE,
+	                                     -1);
+	SUCCESS_RES (object, err);
+	fail_unless (GP11_IS_OBJECT (object));
+	
+	if (!object)
+		return;
+	
+	/* Using async */
+	gp11_object_destroy_async (object, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+
+	ret = gp11_object_destroy_finish (object, result, &err);
+	g_object_unref (result);
+	SUCCESS_RES (object, err);
+	g_object_unref (object);
+}
+
+DEFINE_TEST(get_attributes)
+{
+	GAsyncResult *result = NULL;
+	GP11Attributes *attrs;
+	GError *err = NULL;
+	gulong klass;
+	gchar *value = NULL;
+	guint types[2] = { CKA_CLASS, CKA_LABEL };
+	
+	/* Simple */
+	attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+	SUCCESS_RES (attrs, err);
+	if (attrs != NULL) {
+		fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == CKO_DATA);
+		fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "TEST LABEL") == 0);
+		g_free (value); value = NULL;
+		gp11_attributes_unref (attrs);
+	}
+
+	/* Full */
+	attrs = gp11_object_get_full (object, types, 2, NULL, &err);
+	SUCCESS_RES (attrs, err);
+	if (attrs != NULL) {
+		fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == CKO_DATA);
+		fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "TEST LABEL") == 0);
+		g_free (value); value = NULL;
+		gp11_attributes_unref (attrs);
+	}
+
+	/* Async */
+	gp11_object_get_async (object, types, 2, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+
+	attrs = gp11_object_get_finish (object, result, &err);
+	g_object_unref (result);
+	SUCCESS_RES (attrs, err);
+	if (attrs != NULL) {
+		fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == CKO_DATA);
+		fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "TEST LABEL") == 0);
+		g_free (value); value = NULL;
+		gp11_attributes_unref (attrs);
+	}
+}
+
+DEFINE_TEST(get_one_attribute)
+{
+	GAsyncResult *result = NULL;
+	GP11Attribute *attr;
+	GError *err = NULL;
+	
+	/* Simple */
+	attr = gp11_object_get_one (object, CKA_CLASS, &err);
+	SUCCESS_RES (attr, err);
+	if (attr != NULL) {
+		fail_unless (attr->type == CKA_CLASS && gp11_attribute_get_ulong (attr) == CKO_DATA);
+		gp11_attribute_free (attr);
+	}
+
+	/* Full */
+	attr = gp11_object_get_one_full (object, CKA_CLASS, NULL, &err);
+	SUCCESS_RES (attr, err);
+	if (attr != NULL) {
+		fail_unless (attr->type == CKA_CLASS && gp11_attribute_get_ulong (attr) == CKO_DATA);
+		gp11_attribute_free (attr);
+	}
+
+	/* Async */
+	gp11_object_get_one_async (object, CKA_CLASS, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+
+	attr = gp11_object_get_one_finish (object, result, &err);
+	g_object_unref (result);
+	SUCCESS_RES (attr, err);
+	if (attr != NULL) {
+		fail_unless (attr->type == CKA_CLASS && gp11_attribute_get_ulong (attr) == CKO_DATA);
+		gp11_attribute_free (attr);
+	}
+}
+
+DEFINE_TEST(set_attributes)
+{
+	GAsyncResult *result = NULL;
+	GP11Attributes *attrs, *templ;
+	GError *err = NULL;
+	gulong klass;
+	gchar *value = NULL;
+	gboolean ret;
+	
+	/* Simple */
+	ret = gp11_object_set (object, &err, 
+	                       CKA_CLASS, GP11_ULONG, 5, 
+	                       CKA_LABEL, GP11_STRING, "CHANGE ONE", 
+	                       -1);
+	SUCCESS_RES (ret, err);
+	if (ret) {
+		attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+		fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == 5);
+		fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "CHANGE ONE") == 0);
+		g_free (value); value = NULL;
+		gp11_attributes_unref (attrs);
+	}
+
+	templ = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, 6,
+	                              CKA_LABEL, GP11_STRING, "CHANGE TWO",
+	                              -1);
+	
+	/* Full */
+	ret = gp11_object_set_full (object, templ, NULL, &err);
+	gp11_attributes_unref (templ);
+	SUCCESS_RES (ret, err);
+	if (ret) {
+		attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+		fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == 6);
+		fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "CHANGE TWO") == 0);
+		g_free (value); value = NULL;
+		gp11_attributes_unref (attrs);
+	}
+
+	templ = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, 7,
+	                              CKA_LABEL, GP11_STRING, "CHANGE THREE",
+	                              -1);
+
+	/* Async */
+	gp11_object_set_async (object, templ, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+
+	ret = gp11_object_set_finish (object, result, &err);
+	g_object_unref (result);
+	SUCCESS_RES (ret, err);
+	if (ret) {
+		attrs = gp11_object_get (object, &err, CKA_CLASS, CKA_LABEL, -1);
+		fail_unless (gp11_attributes_find_ulong (attrs, CKA_CLASS, &klass) && klass == 7);
+		fail_unless (gp11_attributes_find_string (attrs, CKA_LABEL, &value) && strcmp (value, "CHANGE THREE") == 0);
+		g_free (value); value = NULL;
+		gp11_attributes_unref (attrs);
+	}
+}
+
+DEFINE_TEST(find_objects)
+{
+	GAsyncResult *result = NULL;
+	GP11Attributes *templ;
+	GList *objects;
+	GP11Object *testobj;
+	GError *err = NULL;
+	
+	testobj = gp11_session_create_object (session, &err, 
+	                                      CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                                      CKA_LABEL, GP11_STRING, "UNIQUE LABEL",
+	                                      -1);
+	g_object_unref (testobj);
+
+	testobj = gp11_session_create_object (session, &err, 
+	                                      CKA_CLASS, GP11_ULONG, CKO_DATA,
+	                                      CKA_LABEL, GP11_STRING, "OTHER LABEL",
+	                                      -1);
+	g_object_unref (testobj);
+
+	/* Simple, "TEST LABEL" */
+	objects = gp11_session_find_objects (session, &err, CKA_LABEL, GP11_STRING, "UNIQUE LABEL", -1);
+	SUCCESS_RES (objects, err);
+	fail_unless (g_list_length (objects) == 1);
+	gp11_list_unref_free (objects);
+
+	/* Full, All */
+	templ = gp11_attributes_new ();
+	objects = gp11_session_find_objects_full (session, templ, NULL, &err);
+	SUCCESS_RES (objects, err);
+	fail_unless (g_list_length (objects) > 1);
+	gp11_list_unref_free (objects);
+	
+	/* Async, None */
+	gp11_attributes_add_string (templ, CKA_LABEL, "blah blah");
+	gp11_session_find_objects_async (session, templ, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+
+	objects = gp11_session_find_objects_finish (session, result, &err);
+	g_object_unref (result);
+	fail_unless (objects == NULL);
+	gp11_list_unref_free (objects);
+}

Added: trunk/gp11/tests/unit-test-gp11-session.c
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/unit-test-gp11-session.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,142 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+
+#include <glib.h>
+
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+static GP11Slot *slot = NULL;
+static GP11Session *session = NULL;
+
+DEFINE_SETUP(load_session)
+{
+	GError *err = NULL;
+	GList *slots;
+	
+	/* Successful load */
+	module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+	SUCCESS_RES (module, err);
+	
+	slots = gp11_module_get_slots (module, TRUE);
+	fail_if (slots == NULL);
+	
+	slot = GP11_SLOT (slots->data);
+	g_object_ref (slot);
+	gp11_list_unref_free (slots);
+
+	session = gp11_slot_open_session (slot, 0, &err);
+	SUCCESS_RES(session, err); 
+}
+
+DEFINE_TEARDOWN(load_session)
+{
+	g_object_unref (session); 
+	g_object_unref (slot);
+	g_object_unref (module);
+}
+
+DEFINE_TEST(session_props)
+{
+	GP11Module *mod;
+	guint handle;
+	
+	g_object_get (session, "module", &mod, "handle", &handle, NULL);
+	fail_unless (mod == module);
+	g_object_unref (mod);
+	
+	fail_unless (handle != 0);
+	fail_unless (session->handle == handle);
+}
+
+DEFINE_TEST(session_info)
+{
+	GP11SessionInfo *info;
+	
+	g_printerr ("session_info");
+	info = gp11_session_get_info (session);
+	fail_unless (info != NULL, "no session info");
+	
+	fail_unless (info->slot_id == slot->handle); 
+	fail_unless ((info->flags & CKF_SERIAL_SESSION) == CKF_SERIAL_SESSION); 
+	fail_unless (info->device_error == 1414); 
+	gp11_session_info_free (info);
+}
+
+static void 
+fetch_async_result (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+	*((GAsyncResult**)user_data) = result;
+	g_object_ref (result);
+}
+
+DEFINE_TEST(open_close_session)
+{
+	GP11Session *sess;
+	GAsyncResult *result = NULL;
+	GError *err = NULL;
+	
+	sess = gp11_slot_open_session_full (slot, 0, NULL, &err);
+	SUCCESS_RES (sess, err);
+	
+	g_object_unref (sess);
+	
+	/* Test opening async */
+	gp11_slot_open_session_async (slot, 0, NULL, fetch_async_result, &result);
+	
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+	
+	/* Get the result */
+	sess = gp11_slot_open_session_finish (slot, result, &err);
+	SUCCESS_RES (sess, err);
+	
+	g_object_unref (result);
+	g_object_unref (sess);
+}
+DEFINE_TEST(login_logout)
+{
+	GAsyncResult *result = NULL;
+	GError *err = NULL;
+	gboolean ret;
+
+	/* login/logout */
+	ret = gp11_session_login (session, CKU_USER, (guchar*)"booo", 4, &err);
+	SUCCESS_RES (ret, err);
+	
+	ret = gp11_session_logout (session, &err);
+	SUCCESS_RES (ret, err);
+
+	/* login/logout full */
+	ret = gp11_session_login_full (session, CKU_USER, (guchar*)"booo", 4, NULL, &err);
+	SUCCESS_RES (ret, err);
+	
+	ret = gp11_session_logout_full (session, NULL, &err);
+	SUCCESS_RES (ret, err);
+
+	/* login async */
+	gp11_session_login_async (session, CKU_USER, (guchar*)"booo", 4, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+	
+	ret = gp11_session_login_finish (session, result, &err);
+	SUCCESS_RES (ret, err);
+	
+	g_object_unref (result);
+	result = NULL;
+	
+	/* logout async */
+	gp11_session_logout_async (session, NULL, fetch_async_result, &result);
+	WAIT_UNTIL (result);
+	fail_if (result == NULL);
+	
+	ret = gp11_session_logout_finish (session, result, &err);
+	SUCCESS_RES (ret, err);
+	
+	g_object_unref (result);
+	result = NULL;
+
+}

Added: trunk/gp11/tests/unit-test-gp11-slot.c
==============================================================================
--- (empty file)
+++ trunk/gp11/tests/unit-test-gp11-slot.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,122 @@
+
+#include <check.h>
+
+#include <glib.h>
+#include <string.h>
+
+#include "run-auto-test.h"
+#include "gp11-test.h"
+
+static GP11Module *module = NULL;
+static GP11Slot *slot = NULL;
+
+DEFINE_SETUP(load_slots)
+{
+	GError *err = NULL;
+	GList *slots;
+	
+	/* Successful load */
+	module = gp11_module_initialize (".libs/libgp11-test-module.so", &err);
+	SUCCESS_RES (module, err);
+	
+	slots = gp11_module_get_slots (module, TRUE);
+	fail_if (slots == NULL);
+	
+	slot = GP11_SLOT (slots->data);
+	g_object_ref (slot);
+	gp11_list_unref_free (slots);
+	
+}
+
+DEFINE_TEARDOWN(load_slots)
+{
+	g_object_unref (slot);
+	g_object_unref (module);
+}
+
+DEFINE_TEST(slot_info)
+{
+	GP11SlotInfo *info;
+	GP11TokenInfo *token;
+	GList *slots, *l;
+
+	slots = gp11_module_get_slots (module, FALSE);
+	fail_unless (2 == g_list_length (slots), "wrong number of slots returned");
+	fail_unless (GP11_IS_SLOT (slots->data), "missing slot one");
+	fail_unless (GP11_IS_SLOT (slots->next->data), "missing slot two");
+	
+	for (l = slots; l; l = g_list_next (l)) {
+		info = gp11_slot_get_info (GP11_SLOT (l->data));
+		fail_unless (info != NULL, "no slot info");
+
+		fail_unless (strcmp("TEST MANUFACTURER", info->manufacturer_id) == 0);
+		fail_unless (strcmp("TEST SLOT", info->slot_description) == 0);
+		fail_unless (55 == info->hardware_version_major);
+		fail_unless (155 == info->hardware_version_minor);
+		fail_unless (65 == info->firmware_version_major);
+		fail_unless (165 == info->firmware_version_minor);
+	
+		gp11_slot_info_free (info);
+		
+		if (info->flags & CKF_TOKEN_PRESENT) {		
+			token = gp11_slot_get_token_info (slot);
+			fail_if (token == NULL, "no token info");
+
+			fail_unless (strcmp ("TEST MANUFACTURER", token->manufacturer_id) == 0);
+			fail_unless (strcmp ("TEST LABEL", token->label) == 0);
+			fail_unless (strcmp ("TEST MODEL", token->model) == 0);
+			fail_unless (strcmp ("TEST SERIAL", token->serial_number) == 0);
+			fail_unless (1 == token->max_session_count);
+			fail_unless (2 == token->session_count);
+			fail_unless (3 == token->max_rw_session_count);
+			fail_unless (4 == token->rw_session_count);
+			fail_unless (5 == token->max_pin_len);
+			fail_unless (6 == token->min_pin_len);
+			fail_unless (7 == token->total_public_memory);
+			fail_unless (8 == token->free_public_memory);
+			fail_unless (9 == token->total_private_memory);
+			fail_unless (10 == token->free_private_memory);
+			fail_unless (75 == token->hardware_version_major);
+			fail_unless (175 == token->hardware_version_minor);
+			fail_unless (85 == token->firmware_version_major);
+			fail_unless (185 == token->firmware_version_minor);
+			fail_unless (927645599 == token->utc_time);
+			
+			gp11_token_info_free (token);
+		}
+	}
+	
+	gp11_list_unref_free (slots);
+}
+
+DEFINE_TEST(slot_props)
+{
+	GP11Module *mod;
+	CK_SLOT_ID slot_id;
+	
+	g_object_get (slot, "module", &mod, "handle", &slot_id, NULL);
+	fail_unless (mod == module);
+	fail_unless (slot_id == 52);
+
+	g_object_unref (mod);
+}
+
+DEFINE_TEST(slot_mechanisms)
+{
+	GSList *mechs, *l;
+	GP11MechanismInfo *info;
+	
+	mechs = gp11_slot_get_mechanisms (slot);
+	fail_unless (2 == g_slist_length (mechs), "wrong number of mech types returned");
+
+	for (l = mechs; l; l = g_slist_next (l)) {
+		
+		info = gp11_slot_get_mechanism_info (slot, GPOINTER_TO_UINT (l->data));
+		fail_unless (info != NULL, "no mech info returned");
+		
+		gp11_mechanism_info_free (info);
+	}
+	
+	g_slist_free (mechs);
+}
+

Added: trunk/tests/check-helpers.c
==============================================================================
--- (empty file)
+++ trunk/tests/check-helpers.c	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,161 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-helpers.c: Common functions called from check unit tests
+
+   Copyright (C) 2008 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+/* This file is included into the main .c file for each check unit-test program */
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <check.h>
+
+#include "check-helpers.h"
+
+#include "common/gkr-secure-memory.h"
+
+static GStaticMutex memory_mutex = G_STATIC_MUTEX_INIT;
+
+/* Used from the tests sometimes */
+SRunner *srunner = NULL;
+
+void gkr_memory_lock (void) 
+{ 
+	g_static_mutex_lock (&memory_mutex); 
+}
+
+void gkr_memory_unlock (void) 
+{ 
+	g_static_mutex_unlock (&memory_mutex); 
+}
+
+void* gkr_memory_fallback (void *p, unsigned long sz) 
+{ 
+	return g_realloc (p, sz); 
+}
+
+#ifndef EXTERNAL_TEST
+#include "common/gkr-async.h"
+#endif
+
+static GMainLoop *mainloop = NULL;
+
+static gboolean
+quit_loop (gpointer unused)
+{
+	g_main_loop_quit (mainloop);
+	return TRUE;	
+}
+
+void
+test_mainloop_quit (void)
+{
+	g_main_loop_quit (mainloop);
+}
+
+void
+test_mainloop_run (int timeout)
+{
+	guint id = 0;
+	
+	if (timeout)
+		id = g_timeout_add (timeout, quit_loop, NULL);
+	g_main_loop_run (mainloop);
+	if (timeout)
+		g_source_remove (id); 
+} 
+
+GMainLoop* 
+test_mainloop_get (void)
+{
+	if (!mainloop)
+		mainloop = g_main_loop_new (NULL, FALSE);
+	return mainloop;
+}
+
+void
+test_quiet_abort_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
+                              const gchar *message, gpointer user_data)
+{
+	abort();
+}
+
+static void 
+chdir_base_dir (char* argv0)
+{
+	gchar *dir, *base;
+
+	dir = g_path_get_dirname (argv0);
+	chdir (dir);
+	
+	base = g_path_get_basename (dir);
+	if (strcmp (base, ".libs") == 0)
+		chdir ("..");
+
+	g_free (base);
+	g_free (dir);
+}
+
+int
+main (int argc, char* argv[])
+{
+	GLogLevelFlags fatal_mask;
+	const gchar* envi;
+	int number_failed;
+	Suite *suite;
+
+	g_thread_init (NULL);
+
+	envi = getenv ("GNOME_KEYRING_TEST_PATH");
+	if (envi) {
+		setenv ("GNOME_KEYRING_OUTSIDE_TEST", "TRUE", 1);
+	} else {
+		setenv ("GNOME_KEYRING_TEST_PATH", "/tmp/test-gnome-keyring", 1);
+		g_mkdir_with_parents ("/tmp/test-gnome-keyring", 0777);
+	}
+
+	chdir_base_dir (argv[0]);
+	gtk_init(&argc, &argv);
+	mainloop = g_main_loop_new (NULL, FALSE);
+
+#ifndef EXTERNAL_TEST
+
+	gkr_async_workers_init (mainloop);
+	
+#endif
+
+	fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+	fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
+	g_log_set_always_fatal (fatal_mask);
+
+	suite = test_suite_create ();
+	srunner = srunner_create (suite);
+	srunner_run_all (srunner, CK_NORMAL);
+	number_failed = srunner_ntests_failed (srunner);
+	srunner_free (srunner);
+	srunner = NULL;
+	
+	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+} 

Added: trunk/tests/check-helpers.h
==============================================================================
--- (empty file)
+++ trunk/tests/check-helpers.h	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,36 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* check-helpers.h: Declarations for common functions called from check unit tests
+
+   Copyright (C) 2008 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#ifndef CHECK_HELPERS_H_
+#define CHECK_HELPERS_H_
+
+#include <glib.h>
+
+void test_mainloop_quit (void);
+void test_mainloop_run (int timeout);
+GMainLoop* test_mainloop_get (void);
+
+void test_quiet_abort_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
+                                   const gchar *message, gpointer user_data);
+
+#endif /*CHECK_HELPERS_H_*/

Added: trunk/tests/check.make
==============================================================================
--- (empty file)
+++ trunk/tests/check.make	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,62 @@
+
+# The following need to be declared before this file is included:
+#   UNIT_AUTO     A list of C files with tests
+#   UNIT_PROMPT   A list of C files with prompting tests
+#   UNIT_LIBS     Libraries to link the tests to
+
+# ------------------------------------------------------------------------------
+
+INCLUDES=				\
+	-I$(top_srcdir) 		\
+	-I$(top_srcdir)/daemon 		\
+	-I$(top_builddir) 		\
+	$(GTK_CFLAGS)			\
+	$(GLIB_CFLAGS) \
+	$(CHECK_CFLAGS) 
+	
+LIBS = \
+	$(GTK_LIBS) \
+	$(GLIB_LIBS) \
+	$(GTHREAD_LIBS) \
+	$(CHECK_LIBS)
+	
+noinst_PROGRAMS= \
+	run-auto-test \
+	run-prompt-test
+	
+run-auto-test.c: $(UNIT_AUTO) Makefile.am $(top_srcdir)/tests/prep-check.sh
+	sh $(top_srcdir)/tests/prep-check.sh -b run-auto-test $(UNIT_AUTO)
+
+run_auto_test_SOURCES = \
+	run-auto-test.c run-auto-test.h \
+	$(UNIT_AUTO)
+	
+run_auto_test_LDADD = \
+	$(UNIT_LIBS) \
+	$(DAEMON_LIBS)
+	
+run_auto_test_CFLAGS = \
+	$(UNIT_FLAGS)
+
+run-prompt-test.c: $(UNIT_PROMPT) Makefile.am $(top_srcdir)/tests/prep-check.sh
+	sh $(top_srcdir)/tests/prep-check.sh -b run-prompt-test $(UNIT_PROMPT)
+
+run_prompt_test_SOURCES = \
+	run-prompt-test.c run-prompt-test.h \
+	$(UNIT_PROMPT)
+	
+run_prompt_test_LDADD = \
+	$(UNIT_LIBS) \
+	$(DAEMON_LIBS)
+
+run_prompt_test_CFLAGS = \
+	$(UNIT_FLAGS)
+
+# ------------------------------------------------------------------------------
+# Run the tests
+
+test-auto: $(noinst_PROGRAMS)
+	./run-auto-test
+
+test-prompt: $(noinst_PROGRAMS)
+	./run-prompt-test

Added: trunk/tests/prep-check.sh
==============================================================================
--- (empty file)
+++ trunk/tests/prep-check.sh	Mon Jul 14 19:54:11 2008
@@ -0,0 +1,134 @@
+#!/bin/sh -eu
+
+set -eu
+
+# --------------------------------------------------------------------
+# FUNCTIONS 
+
+usage()
+{
+	echo "usage: prep-check.sh -b base-name files.c ..." >&2
+	exit 2
+}
+
+# --------------------------------------------------------------------
+# SOURCE FILE 
+
+build_header()
+{
+	local _file
+	
+	echo '/* This is auto-generated code. Edit at your own peril. */'
+	# echo "#ifndef _${BASE}_H_"
+	# echo "#define _${BASE}_H_"
+	echo 
+	echo '#include <check.h>'
+	echo
+	echo 'extern SRunner *srunner;'
+	echo
+	echo '#define DEFINE_SETUP(x) void setup_##x(void)'
+	echo '#define DEFINE_TEARDOWN(x) void teardown_##x(void)'
+	echo '#define DEFINE_TEST(x) void x(void)'
+	echo '#define DEFINE_ABORT(x) void x(void)'
+	echo
+	for _file in $@; do
+		sed -ne 's/.*DEFINE_SETUP(\([^)]\+\))/	void setup_\1(void);/p' $_file
+		sed -ne 's/.*DEFINE_TEARDOWN(\([^)]\+\))/	void teardown_\1(void);/p' $_file
+		sed -ne 's/.*DEFINE_TEST(\([^)]\+\))/	void \1(void);/p' $_file
+		sed -ne 's/.*DEFINE_ABORT(\([^)]\+\))/	void \1(void);/p' $_file
+	done
+	echo
+	# echo "#endif"
+}
+
+build_source()
+{
+	local _tcases _file _name
+	
+	echo '/* This is auto-generated code. Edit at your own peril. */'
+	echo '#include <check.h>'
+	echo "#include \"tests/check-helpers.h\""
+	echo "#include \"$BASE.h\""
+	echo
+	
+	# A  test macro
+	echo '#define WRAP_TEST(name) \'
+	echo '	START_TEST(test_##name) { \'
+	echo '		name (); \'
+	echo '	} END_TEST'
+	
+	# Note that we can't run abort tests without CK_FORK
+	echo '#define WRAP_ABORT(name) \'
+	echo '	START_TEST(test_##name) { \'
+	echo '		if (srunner_fork_status (srunner) == CK_NOFORK) return; \'
+	echo '		GLogFunc old = g_log_set_default_handler (test_quiet_abort_log_handler, NULL); \'
+	echo '		name (); \'
+	echo '		g_log_set_default_handler (old, NULL); \'
+	echo '	} END_TEST'
+	
+	# Include each file, and build a test case for it
+	_tcases=""
+	for _file in $@; do
+		_name=`echo $_file | tr -c 'a-zA-Z0-9' '_'`  
+
+		# Include the test file
+		# echo "#include \"$_file\""
+		# echo
+
+		# Wrap each and every test
+		sed -ne 's/.*DEFINE_TEST(\([^)]\+\)).*/WRAP_TEST (\1);/p' $_file
+		sed -ne 's/.*DEFINE_ABORT(\([^)]\+\)).*/WRAP_ABORT (\1);/p' $_file
+		echo
+		
+		# Add all tests to the test case 
+		echo "static TCase* tcase_$_name(void) {"
+		_tcases="$_tcases $_name"
+		echo "	TCase *tc = tcase_create (\"X\");"
+		sed -ne 's/.*DEFINE_SETUP(\([^)]\+\)).*/	tcase_add_checked_fixture (tc, setup_\1, teardown_\1);/p' $_file
+		sed -ne 's/.*DEFINE_TEST(\([^)]\+\)).*/	tcase_add_test (tc, test_\1);/p' $_file
+		sed -ne 's/.*DEFINE_ABORT(\([^)]\+\)).*/	tcase_add_test_raise_signal (tc, test_\1, 6);/p' $_file
+		echo "	return tc;"
+		echo "}"
+		echo
+		
+	done
+	
+	echo "static Suite* test_suite_create (void) {"
+	echo "	Suite *s = suite_create (\"$BASE\");"
+	for _name in $_tcases; do
+		echo "	suite_add_tcase (s, tcase_$_name());"
+	done
+	echo "	return s;"
+	echo "}"
+	echo
+		
+	echo "#include \"tests/check-helpers.c\""
+}
+
+# --------------------------------------------------------------------
+# ARGUMENT PARSING
+
+BASE=unit
+
+while [ $# -gt 0 ]; do
+	case "$1" in
+	-b)
+		BASE="$2"
+		shift
+		;;	
+	--)
+		shift
+		break
+		;;
+	-*)
+		usage
+		;;
+	*)
+		break
+		;;
+	esac
+	shift
+done
+	
+build_header $* > $BASE.h
+build_source $* > $BASE.c



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]