[Openpgpmdrv-commits] r1 - / trunk trunk/OpenPGPminidriver trunk/OpenPGPminidriverTest

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Tue Feb 23 20:19:08 CET 2010


Author: vletoux
Date: 2010-02-23 20:18:59 +0100 (Tue, 23 Feb 2010)
New Revision: 1

Added:
   trunk/
   trunk/OpenPGPminidriver.sln
   trunk/OpenPGPminidriver/
   trunk/OpenPGPminidriver/CardAndContainerProperties.c
   trunk/OpenPGPminidriver/CardCryptographicOperations.c
   trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c
   trunk/OpenPGPminidriver/CardKeyContainer.c
   trunk/OpenPGPminidriver/CardPinOperation.c
   trunk/OpenPGPminidriver/CardPublicDataOperation.c
   trunk/OpenPGPminidriver/CardSecureKeyInjection.c
   trunk/OpenPGPminidriver/Context.h
   trunk/OpenPGPminidriver/ContextManagement.c
   trunk/OpenPGPminidriver/CryptoOperations.c
   trunk/OpenPGPminidriver/CryptoOperations.h
   trunk/OpenPGPminidriver/DllMain.c
   trunk/OpenPGPminidriver/OpenPGPminidriver.def
   trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj
   trunk/OpenPGPminidriver/PinOperations.c
   trunk/OpenPGPminidriver/PinOperations.h
   trunk/OpenPGPminidriver/PublicDataOperations.c
   trunk/OpenPGPminidriver/PublicDataOperations.h
   trunk/OpenPGPminidriver/README.txt
   trunk/OpenPGPminidriver/SmartCard.c
   trunk/OpenPGPminidriver/SmartCard.h
   trunk/OpenPGPminidriver/SmartCardOperations.c
   trunk/OpenPGPminidriver/Tracing.c
   trunk/OpenPGPminidriver/Tracing.h
   trunk/OpenPGPminidriver/driver.inf
   trunk/OpenPGPminidriver/version.rc
   trunk/OpenPGPminidriverTest/
   trunk/OpenPGPminidriverTest/BaseCSP.cpp
   trunk/OpenPGPminidriverTest/CryptoOperations.cpp
   trunk/OpenPGPminidriverTest/Dialog.h
   trunk/OpenPGPminidriverTest/Dialog.rc
   trunk/OpenPGPminidriverTest/InitializationAndDeconstruct.cpp
   trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj
   trunk/OpenPGPminidriverTest/PINOperations.cpp
   trunk/OpenPGPminidriverTest/PublicDataOperations.cpp
   trunk/OpenPGPminidriverTest/RegisterCardForTestIfTheDriverIsNotInstalled.reg
   trunk/OpenPGPminidriverTest/global.h
   trunk/OpenPGPminidriverTest/main.cpp
Log:


Added: trunk/OpenPGPminidriver/CardAndContainerProperties.c
===================================================================
--- trunk/OpenPGPminidriver/CardAndContainerProperties.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CardAndContainerProperties.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,582 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "CryptoOperations.h"
+#include "PinOperations.h"
+
+// 4.4	Card capabilities
+
+/** This function queries the card and card-specific minidriver combination 
+for the functionality that is provided at this level, such as certificate or
+file compression.*/
+
+DWORD WINAPI CardQueryCapabilities(
+    __in PCARD_DATA  pCardData,
+    __inout PCARD_CAPABILITIES  pCardCapabilities
+)
+{
+	DWORD dwReturn = 0, dwVersion;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pCardCapabilities == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardCapabilities == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwVersion = (pCardCapabilities->dwVersion == 0) ? 1 : pCardCapabilities->dwVersion;
+		if ( dwVersion != CARD_CAPABILITIES_CURRENT_VERSION )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwVersion %d", dwVersion);
+			dwReturn  = ERROR_REVISION_MISMATCH;
+			__leave;
+		}
+		pCardCapabilities->fCertificateCompression = TRUE;
+		pCardCapabilities->fKeyGen = TRUE;
+		dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+// 4.5	Card and container properties
+
+/** The CardGetContainerProperty function is modeled after the query 
+functions of CAPI for keys. It takes a LPWSTR  that indicates which parameter
+is being requested. Then it returns data written into the pbData parameter.*/
+
+DWORD WINAPI CardGetContainerProperty(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bContainerIndex,
+    __in LPCWSTR  wszProperty,
+    __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE  pbData,
+    __in DWORD  cbData,
+    __out PDWORD  pdwDataLen,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter bContainerIndex = %d wszProperty = %s", bContainerIndex, wszProperty);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pdwDataLen == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pdwDataLen == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( wszProperty == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (bContainerIndex >= MaxContainer)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"bContainerIndex == %d", bContainerIndex);
+			dwReturn  = SCARD_E_NO_KEY_CONTAINER ;
+			__leave;
+		}
+		if (wcscmp(wszProperty,CCP_CONTAINER_INFO) == 0)
+		{
+			if (cbData < sizeof(CONTAINER_INFO))
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			*pdwDataLen = cbData;
+			dwReturn = CardGetContainerInfo(pCardData, bContainerIndex, dwFlags, (PCONTAINER_INFO) pbData);
+		}
+		else if (wcscmp(wszProperty,CCP_PIN_IDENTIFIER) == 0)
+		{
+			if (cbData < sizeof(PIN_ID))
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			*pdwDataLen = cbData;
+			if(bContainerIndex < MaxContainer)
+			{
+				dwReturn = SCARD_E_NO_KEY_CONTAINER;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", bContainerIndex);
+				__leave;
+			}
+			(*(PDWORD)pbData) = Containers[bContainerIndex].PinId;
+			dwReturn = 0;
+		}
+		/*else if (wcscmp(wszProperty,CCP_ASSOCIATED_ECDH_KEY) == 0)
+		{
+		}*/
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** This function sets the properties on containers. Only two container
+properties are supported:
+•	CCP_PIN_IDENTIFIER
+•	 CCP_ASSOCIATED_ECDH_KEY 
+*/
+
+DWORD WINAPI CardSetContainerProperty(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bContainerIndex,
+    __in LPCWSTR  wszProperty,
+    __in_bcount(cbDataLen) PBYTE  pbData,
+    __in DWORD  cbDataLen,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter bContainerIndex = %d wszProperty = %s", bContainerIndex, wszProperty);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( wszProperty == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (wcscmp(wszProperty,CCP_PIN_IDENTIFIER) == 0)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			__leave;
+		}
+		else if (wcscmp(wszProperty,CCP_ASSOCIATED_ECDH_KEY) == 0)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			__leave;
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardGetProperty function is modeled after the query functions of
+CAPI for keys. It takes a LPWSTR that indicates which parameter is being 
+requested. The function returns data in the pbData parameter.*/
+
+DWORD WINAPI CardGetProperty(
+    __in PCARD_DATA  pCardData,
+    __in LPCWSTR  wszProperty,
+    __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE  pbData,
+    __in DWORD  cbData,
+    __out PDWORD  pdwDataLen,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	PBYTE pbTempData = NULL;
+	DWORD dwTempSize = 0;
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter wszProperty = %s", wszProperty);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( wszProperty == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pdwDataLen == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pdwDataLen == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0)
+		{
+			*pdwDataLen = sizeof(CARD_FREE_SPACE_INFO);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			dwReturn = CardQueryFreeSpace(pCardData, dwFlags, (PCARD_FREE_SPACE_INFO) pbData);
+		}
+		else if (wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0)
+		{
+			*pdwDataLen = sizeof(CARD_CAPABILITIES);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			dwReturn = CardQueryCapabilities(pCardData, (PCARD_CAPABILITIES) pbData);
+		}
+		else if (wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0)
+		{
+			*pdwDataLen = sizeof(CARD_KEY_SIZES);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			dwReturn = CardQueryKeySizes(pCardData, dwFlags, 0, (PCARD_KEY_SIZES) pbData);
+		}
+		else if (wcscmp(wszProperty,CP_CARD_READ_ONLY) == 0)
+		{
+			*pdwDataLen = sizeof(BOOL);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			*((PBOOL)pbData) = TRUE;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0)
+		{
+			*pdwDataLen = sizeof(DWORD);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			*((PDWORD)pbData) = CP_CACHE_MODE_NO_CACHE;
+		}
+		else if (wcscmp(wszProperty,CP_SUPPORTS_WIN_X509_ENROLLMENT) == 0)
+		{
+			*pdwDataLen = sizeof(BOOL);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			*((PBOOL)pbData) = FALSE;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_GUID) == 0)
+		{
+			dwReturn = CardReadFile(pCardData, NULL, szCARD_IDENTIFIER_FILE, 0, &pbTempData, &dwTempSize);
+			if (dwReturn)
+			{
+				__leave;
+			}
+			*pdwDataLen = dwTempSize;
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			memcpy(pbData, pbTempData, dwTempSize);
+		}
+		else if (wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0)
+		{
+			*pdwDataLen = sizeof(OPENPGP_AID);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			memcpy(pbData, &(((POPENPGP_CONTEXT)pCardData->pvVendorSpecific)->Aid), sizeof(OPENPGP_AID));
+			dwReturn = 0;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_PIN_INFO) == 0)
+		{
+			PPIN_INFO pPinInfo;
+			*pdwDataLen = sizeof(PIN_INFO);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			pPinInfo = (PPIN_INFO) pbData;
+			dwReturn = GetPinInfo(dwFlags, pPinInfo);
+		}
+		else if (wcscmp(wszProperty,CP_CARD_LIST_PINS) == 0)
+		{
+			PPIN_SET pPinSet;
+			*pdwDataLen = sizeof(PIN_SET);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			pPinSet = (PPIN_SET) pbData;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_AUTHENTICATED_STATE) == 0)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_PIN_STRENGTH_VERIFY) == 0)
+		{
+			PPIN_SET pPinSet;
+			*pdwDataLen = sizeof(PIN_SET);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			pPinSet = (PPIN_SET) pbData;
+			*pPinSet = CARD_PIN_STRENGTH_PLAINTEXT;
+		}
+		else if (wcscmp(wszProperty,CP_KEY_IMPORT_SUPPORT) == 0)
+		{
+			*pdwDataLen = sizeof(DWORD);
+			if (cbData < *pdwDataLen)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+				dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+				__leave;
+			}
+			*((PDWORD)pbData) = CARD_KEY_IMPORT_RSA_KEYEST;
+		}
+		else if (wcscmp(wszProperty,CP_ENUM_ALGORITHMS ) == 0)
+		{
+			if (dwFlags == CARD_CIPHER_OPERATION)
+			{
+				*pdwDataLen = sizeof(OPENPGP_SUPPORTED_CYPHER_ALGORITHM);
+				if (cbData < *pdwDataLen)
+				{
+					Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+					dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+					__leave;
+				}
+				memcpy(pbData,OPENPGP_SUPPORTED_CYPHER_ALGORITHM,*pdwDataLen);
+			}
+			else if (dwFlags == CARD_ASYMMETRIC_OPERATION   )
+			{
+				*pdwDataLen = sizeof(OPENPGP_SUPPORTED_ASYMETRIC_ALGORITHM);
+				if (cbData < *pdwDataLen)
+				{
+					Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+					dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+					__leave;
+				}
+				memcpy(pbData,OPENPGP_SUPPORTED_ASYMETRIC_ALGORITHM,*pdwDataLen);
+			}
+			else
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
+				dwReturn  = SCARD_E_INVALID_PARAMETER;
+			}
+		}
+		else if (wcscmp(wszProperty,CP_PADDING_SCHEMES ) == 0)
+		{
+			if (dwFlags == CARD_CIPHER_OPERATION)
+			{
+				dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			}
+			else if (dwFlags == CARD_ASYMMETRIC_OPERATION   )
+			{
+				*pdwDataLen = sizeof(DWORD);
+				if (cbData < *pdwDataLen)
+				{
+					Trace(WINEVENT_LEVEL_ERROR, L"cbData == %d", cbData);
+					dwReturn  = ERROR_INSUFFICIENT_BUFFER;
+					__leave;
+				}
+				*((PDWORD)pbData) = CARD_PADDING_PKCS1;
+			}
+			else
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
+				dwReturn  = SCARD_E_INVALID_PARAMETER;
+			}
+
+		}
+		else if (wcscmp(wszProperty,CP_CHAINING_MODES ) == 0)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+	}
+	__finally
+	{
+		if (pbTempData)
+		{
+			pCardData->pfnCspFree(pbTempData);
+		}
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** This function can be used to set properties on the card.*/
+
+DWORD WINAPI CardSetProperty(
+    __in PCARD_DATA  pCardData,
+    __in LPCWSTR  wszProperty,
+    __in_bcount(cbDataLen) PBYTE  pbData,
+    __in DWORD  cbDataLen,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter wszProperty = %s", wszProperty);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( wszProperty == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0
+			|| wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0
+			|| wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0
+			|| wcscmp(wszProperty,CP_CARD_LIST_PINS) == 0
+			|| wcscmp(wszProperty,CP_CARD_AUTHENTICATED_STATE) == 0
+			|| wcscmp(wszProperty,CP_KEY_IMPORT_SUPPORT) == 0
+			|| wcscmp(wszProperty,CP_ENUM_ALGORITHMS) == 0
+			|| wcscmp(wszProperty,CP_PADDING_SCHEMES) == 0
+			|| wcscmp(wszProperty,CP_CHAINING_MODES) == 0)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s SCARD_E_UNSUPPORTED_FEATURE", wszProperty);
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+			__leave;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_READ_ONLY) == 0)
+		{
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0)
+		{
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+		}
+		else if (wcscmp(wszProperty,CP_SUPPORTS_WIN_X509_ENROLLMENT) == 0)
+		{
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_GUID) == 0)
+		{
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0)
+		{
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_PIN_INFO) == 0)
+		{
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+		}
+		else if (wcscmp(wszProperty,CP_CARD_PIN_STRENGTH_VERIFY) == 0)
+		{
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE ;
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wszProperty == %s", wszProperty);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+

Added: trunk/OpenPGPminidriver/CardCryptographicOperations.c
===================================================================
--- trunk/OpenPGPminidriver/CardCryptographicOperations.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CardCryptographicOperations.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,264 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "CryptoOperations.h"
+
+// 4.7 Cryptographic operations
+
+/** This function performs an RSA decryption operation on the passed buffer
+by using the private key that a container index refers to. Note that for
+ECC-only smart cards, this entry point is not defined and is set to NULL 
+in the returned CARD_DATA structure from CardAcquireContext. This operation
+is restricted to a single buffer of a size equal to the key modulus.*/
+
+DWORD WINAPI CardRSADecrypt(
+    __in PCARD_DATA  pCardData,
+    __inout PCARD_RSA_DECRYPT_INFO  pInfo
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+
+		if ( pInfo == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pInfo == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pInfo->pbData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pInfo->pbData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION 
+			&& pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"ERROR_REVISION_MISMATCH");
+			dwReturn  = ERROR_REVISION_MISMATCH;
+			__leave;
+		}
+		if (pInfo->dwKeySpec != AT_KEYEXCHANGE)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"AT_KEYEXCHANGE %d", pInfo->dwKeySpec);
+			dwReturn  = SCARD_E_NO_KEY_CONTAINER ;
+			__leave;
+		}
+		if (pInfo->bContainerIndex != Confidentiality)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"Confidentiality %d", pInfo->bContainerIndex);
+			dwReturn  = SCARD_E_NO_KEY_CONTAINER ;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardDecrypt(pCardData, pInfo);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+
+/** The CardSignData function signs a block of unpadded data. This entry either performs
+padding on the card or pads the data by using the PFN_CSP_PAD_DATA callback. All card 
+minidrivers must support this entry point.*/
+
+DWORD WINAPI CardSignData(
+    __in PCARD_DATA  pCardData,
+    __in PCARD_SIGNING_INFO  pInfo
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+
+		if ( pInfo == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pInfo == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pInfo->pbData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pInfo->pbData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardSign(pCardData, pInfo);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** This function returns the public key sizes that are supported by the card in use.*/
+DWORD WINAPI CardQueryKeySizes(
+    __in PCARD_DATA  pCardData,
+    __in DWORD  dwKeySpec,
+    __in DWORD  dwFlags,
+    __inout PCARD_KEY_SIZES  pKeySizes
+)
+{
+	DWORD dwReturn = 0, dwVersion;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+
+		if ( dwFlags != 0 )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags != 0 : %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pKeySizes == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pKeySizes == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwVersion = (pKeySizes->dwVersion == 0) ? 1 : pKeySizes->dwVersion;
+		if ( dwVersion != CARD_KEY_SIZES_CURRENT_VERSION )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwVersion == %d", pKeySizes->dwVersion);
+			dwReturn  = ERROR_REVISION_MISMATCH;
+			__leave;
+		}
+
+		switch(dwKeySpec)
+		{
+			case AT_ECDHE_P256 :
+			case AT_ECDHE_P384 :
+			case AT_ECDHE_P521 :
+			case AT_ECDSA_P256 :
+			case AT_ECDSA_P384 :
+			case AT_ECDSA_P521 :
+				Trace(WINEVENT_LEVEL_ERROR, L"dwKeySpec == %d", dwKeySpec);
+				dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+				__leave;
+				break;
+			case AT_KEYEXCHANGE:
+			case AT_SIGNATURE  :
+				break;
+			default:
+				Trace(WINEVENT_LEVEL_ERROR, L"dwKeySpec == %d", dwKeySpec);
+				dwReturn = SCARD_E_INVALID_PARAMETER;
+				__leave;
+				break;
+		}
+
+	   pKeySizes->dwMinimumBitlen     = 1024;
+	   pKeySizes->dwDefaultBitlen     = 2048;
+	   pKeySizes->dwMaximumBitlen     = 2048;
+	   pKeySizes->dwIncrementalBitlen = 0;
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+
+/** The CardConstructDHAgreement function performs a secret agreement calculation 
+for Diffie Hellman (DH) key exchange by using a private key that is present on the
+card. For RSA-only card minidrivers, this entry point is not defined and is set to
+NULL in the CARD_DATA structure that is returned from CardAcquireContext. 
+The CARD_DH_AGREEMENT structure changes to allow for return of a handle to
+the agreed secret. This raises a point about how to index the DH agreement 
+on the card in an opaque manner. Maintaining a map file is unnecessary because
+Ncrypt makes no provision for persistent DH agreements and there is no way to 
+retrieve one after a provider is closed. DH agreements are addressable on card 
+through an opaque BYTE that the card minidriver maintains. This BYTE should be 
+associated with a handle to a card-side agreement.*/
+
+DWORD WINAPI CardConstructDHAgreement(
+    __in PCARD_DATA  pCardData,
+    __inout PCARD_DH_AGREEMENT_INFO  pSecretInfo
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The key derivation structure represents the majority of the required changes
+for FIPS 140-2 compliance for smart cards. It holds the requested key derivation
+function (KDF) and the associated input. The KDFs are defined in the “CNG Reference” 
+documentation on MSDN. For RSA-only card minidrivers, this entry point is not defined
+and is set to NULL in the CARD_DATA structure that is returned from CardAcquireContext.*/
+
+DWORD WINAPI CardDeriveKey(
+    __in PCARD_DATA  pCardData,
+    __inout PCARD_DERIVE_KEY  pAgreementInfo
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The CardDestroyDHAgreement function removes an agreed secret from the card.
+For RSA-only card minidrivers, this entry point is not defined and is set to
+NULL in the CARD_DATA structure that was returned from CardAcquireContext.*/
+
+DWORD WINAPI CardDestroyDHAgreement(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bSecretAgreementIndex,
+    __in DWORD  dwFlags
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c
===================================================================
--- trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,176 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "SmartCard.h"
+
+// 4.1	Initialization and Deconstruct
+
+
+
+/** The CardAcquireContext function, defined by a smart card module, 
+initializes communication between the smart card module and either the
+Microsoft Base Smart Card Cryptographic Service Provider (CSP) or smart 
+card key storage provider (KSP).
+*/
+DWORD WINAPI CardAcquireContext(
+  __in  PCARD_DATA pCardData,
+  __in  DWORD dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+
+		if ( dwFlags != 0 )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags != 0");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CreateContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		if (!(dwFlags & CARD_SECURE_KEY_INJECTION_NO_CARD_MODE))
+		{
+			if (pCardData->hSCardCtx == 0)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"pCardData->hSCardCtx == NULL");
+				dwReturn  = SCARD_E_INVALID_PARAMETER;
+				__leave;
+			}
+			if (pCardData->hScard == 0)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"pCardData->hScard == NULL");
+				dwReturn  = SCARD_E_INVALID_PARAMETER;
+				__leave;
+			}
+		}
+
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		// select the application on the card
+		dwReturn = SelectOpenPGPApplication(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+
+		/* CardInitializationAndDeconstruct.c */
+		pCardData->pfnCardDeleteContext           = CardDeleteContext;
+
+		/* CardPinOperation.c */
+		pCardData->pfnCardAuthenticatePin         = CardAuthenticatePin;
+		pCardData->pfnCardGetChallenge            = CardGetChallenge;
+		pCardData->pfnCardAuthenticateChallenge   = CardAuthenticateChallenge;
+		// CardDeauthenticate not implemented
+		pCardData->pfnCardDeauthenticate          = CardDeauthenticate;
+		pCardData->pfnCardAuthenticateEx          = CardAuthenticateEx;
+		pCardData->pfnCardGetChallengeEx          = CardGetChallengeEx;
+		pCardData->pfnCardDeauthenticateEx        = CardDeauthenticateEx;
+		pCardData->pfnCardChangeAuthenticatorEx   = CardChangeAuthenticatorEx;
+		pCardData->pfnCardUnblockPin              = CardUnblockPin;
+		pCardData->pfnCardChangeAuthenticator     = CardChangeAuthenticator;
+
+		/* CardPublicDataOperation.c */
+		pCardData->pfnCardCreateDirectory         = CardCreateDirectory;
+		pCardData->pfnCardDeleteDirectory         = CardDeleteDirectory;
+		pCardData->pfnCardReadFile                = CardReadFile;
+		pCardData->pfnCardCreateFile              = CardCreateFile;
+		pCardData->pfnCardGetFileInfo             = CardGetFileInfo;
+		pCardData->pfnCardWriteFile               = CardWriteFile;
+		pCardData->pfnCardDeleteFile              = CardDeleteFile;
+		pCardData->pfnCardEnumFiles               = CardEnumFiles;
+		pCardData->pfnCardQueryFreeSpace          = CardQueryFreeSpace;
+
+		/* CardCapabilities.c */
+		pCardData->pfnCardQueryCapabilities       = CardQueryCapabilities;
+
+		/* CardAndContainerProperties.c */
+		pCardData->pfnCardGetContainerProperty    = CardGetContainerProperty;
+		pCardData->pfnCardSetContainerProperty    = CardSetContainerProperty;
+		pCardData->pfnCardGetProperty             = CardGetProperty;
+		pCardData->pfnCardSetProperty             = CardSetProperty;
+
+		/* CardKeyContainer.c */
+		pCardData->pfnCardCreateContainer         = CardCreateContainer;
+		pCardData->pfnCardCreateContainerEx       = CardCreateContainerEx;
+		pCardData->pfnCardDeleteContainer         = CardDeleteContainer;
+		pCardData->pfnCardGetContainerInfo        = CardGetContainerInfo;
+
+		/* CardCryptographicOperations.c */
+		pCardData->pfnCardRSADecrypt              = CardRSADecrypt;
+		pCardData->pfnCardSignData                = CardSignData;
+
+		// should be null for RSA only card
+		pCardData->pfnCardConstructDHAgreement    = NULL; //CardConstructDHAgreement;
+		pCardData->pfnCardDeriveKey               = NULL; //CardDeriveKey;
+		pCardData->pfnCardDestroyDHAgreement      = NULL; //CardDestroyDHAgreement;
+
+		pCardData->pfnCardSignData                = CardSignData;
+		pCardData->pfnCardQueryKeySizes           = CardQueryKeySizes;
+
+		/* Not found :
+		The pfnCardDeriveKey, pfnCardDestroyDHAgreement, and pfnCspGetDHAgreement 
+		members of the CARD_DATA structure are described in later sections. 
+		Starting with Version 5 of this specification, the necessary modifications
+		to the pfnCardConstructDHAgreement function are handled through versioning
+		the structure that is associated with that function.
+		=> what's the prototype for this function ?
+		*/
+
+		pCardData->pfnCspGetDHAgreement           = NULL;
+	}
+	__finally
+	{
+		if (dwReturn)
+		{
+			CleanContext(pCardData);
+		}
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardDeleteContext function reverses the effect of CardAcquireContext
+and severs the communication between the Base CSP/KSP and the card minidriver.
+This function also performs any needed deallocations and cleanup. 
+*/
+
+DWORD WINAPI CardDeleteContext(
+    __inout PCARD_DATA pCardData
+     )
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	CleanContext(pCardData);
+	return 0;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriver/CardKeyContainer.c
===================================================================
--- trunk/OpenPGPminidriver/CardKeyContainer.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CardKeyContainer.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,239 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "CryptoOperations.h"
+
+// 4.6 Key Container
+
+/** The CardCreateContainer function creates a new key container that is 
+identified by the container index that the bContainerIndex argument specifies.
+For applications in which the card does not support on-card key generation or
+if it is desired to archive the keys, the key material can be supplied with
+the call by specifying in flags that the card is to import the supplied key material.*/
+
+DWORD WINAPI CardCreateContainer(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bContainerIndex,
+    __in DWORD  dwFlags,
+    __in DWORD  dwKeySpec,
+    __in DWORD  dwKeySize,
+    __in PBYTE  pbKeyData
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter bContainerIndex=%d",bContainerIndex);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (bContainerIndex >= MaxContainer)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"bContainerIndex == %d",bContainerIndex);
+			dwReturn  = SCARD_E_NO_KEY_CONTAINER;
+			__leave; 
+		}
+		if (Containers[bContainerIndex].dwKeySpec != dwKeySpec)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwKeySpec == %d",dwKeySpec);
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE;
+			__leave; 
+		}
+		dwReturn = CardCreateContainerEx(pCardData, 
+								bContainerIndex,
+								dwFlags,
+								dwKeySpec,
+								dwKeySize,
+								pbKeyData,
+								Containers[bContainerIndex].PinId);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardCreateContainerEx function creates a new key container that the 
+container index identifies and the bContainerIndex parameter specifies. The function 
+associates the key container with the PIN that the PinId parameter specified.
+This function is useful if the card-edge does not allow for changing the key attributes
+after the key container is created. This function replaces the need to call 
+CardSetContainerProperty to set the CCP_PIN_IDENTIFIER property CardCreateContainer
+is called.
+The caller of this function can provide the key material that the card imports.
+This is useful in those situations in which the card either does not support internal
+key generation or the caller requests that the key be archived in the card.*/
+
+DWORD WINAPI CardCreateContainerEx(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bContainerIndex,
+    __in DWORD  dwFlags,
+    __in DWORD  dwKeySpec,
+    __in DWORD  dwKeySize,
+    __in PBYTE  pbKeyData,
+    __in PIN_ID  PinId
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter bContainerIndex=%d",bContainerIndex);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (bContainerIndex >= MaxContainer)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"bContainerIndex == %d",bContainerIndex);
+			dwReturn  = SCARD_E_NO_KEY_CONTAINER;
+			__leave; 
+		}
+		if (Containers[bContainerIndex].dwKeySpec != dwKeySpec)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwKeySpec == %d",dwKeySpec);
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE;
+			__leave; 
+		}
+		if (Containers[bContainerIndex].PinId != PinId)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"PinId == %d",PinId);
+			dwReturn  = SCARD_E_UNSUPPORTED_FEATURE;
+			__leave; 
+		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		if ((dwFlags & CARD_CREATE_CONTAINER_KEY_GEN) == CARD_CREATE_CONTAINER_KEY_GEN )
+		{
+			dwReturn = SCardCreateKey(pCardData, bContainerIndex, dwKeySize);
+		}
+		else if ((dwFlags & CARD_CREATE_CONTAINER_KEY_IMPORT ) == CARD_CREATE_CONTAINER_KEY_IMPORT  )
+		{
+			if (pbKeyData == NULL)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"pbKeyData == NULL");
+				dwReturn  = SCARD_E_INVALID_PARAMETER;
+				__leave;
+			}
+			dwReturn = SCardImportKey(pCardData, bContainerIndex, pbKeyData, dwKeySize);
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d",dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave; 
+		}
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardDeleteContainer function deletes the key container specified by its index value.
+This is done by deleting all key material (public and private) that is associated with 
+that index value.*/
+
+DWORD WINAPI CardDeleteContainer(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bContainerIndex,
+    __in DWORD  dwReserved
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The CardGetContainerInfo function queries the specified key container for more
+information about which keys are present, such as its key specification (such as AT_ECDSA_P384).*/
+
+DWORD WINAPI CardGetContainerInfo(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bContainerIndex,
+    __in DWORD  dwFlags,
+    __inout PCONTAINER_INFO  pContainerInfo
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter bContainerIndex=%d",bContainerIndex);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pContainerInfo == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pContainerInfo == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( dwFlags )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (bContainerIndex >= MaxContainer)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"bContainerIndex == %d",bContainerIndex);
+			dwReturn  = SCARD_E_NO_KEY_CONTAINER;
+			__leave; 
+		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		pContainerInfo->pbSigPublicKey = NULL;
+		pContainerInfo->pbKeyExPublicKey = NULL;
+		pContainerInfo->cbSigPublicKey = 0;
+		pContainerInfo->cbKeyExPublicKey = 0;
+		switch(bContainerIndex)
+		{
+			case Signature:
+			case Authentication:
+				dwReturn = SCardReadPublicKey(pCardData, bContainerIndex, 
+					&(pContainerInfo->pbSigPublicKey),&(pContainerInfo->cbSigPublicKey));
+				break;
+			case Confidentiality:
+				dwReturn = SCardReadPublicKey(pCardData, bContainerIndex, 
+					&(pContainerInfo->pbKeyExPublicKey),&(pContainerInfo->cbKeyExPublicKey));
+				break;
+		}
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}

Added: trunk/OpenPGPminidriver/CardPinOperation.c
===================================================================
--- trunk/OpenPGPminidriver/CardPinOperation.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CardPinOperation.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,607 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "SmartCard.h"
+#include "PinOperations.h"
+
+
+// 4.2 Card PIN Operations
+
+/** The CardAuthenticatePin function submits a PIN value as a string
+to the card to establish the user’s identity and to satisfy access 
+conditions for an operation to be undertaken on the user’s behalf. 
+Submission of a PIN to the card may involve some processing by the card
+minidriver to render the PIN information to a card-specific form. */
+
+DWORD WINAPI CardAuthenticatePin(
+    __in PCARD_DATA  pCardData,
+    __in LPWSTR  pwszUserId,
+    __in_bcount(cbPin) PBYTE  pbPin,
+    __in DWORD  cbPin,
+    __out_opt PDWORD  pcAttemptsRemaining
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter authenticate %s", pwszUserId);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pwszUserId == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbPin == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbPin == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( dwReturn )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( wcscmp(pwszUserId, wszCARD_USER_USER) == 0 ) 
+		{
+			dwReturn = CheckPinLength(pCardData, ROLE_USER, cbPin);
+			if (dwReturn)
+			{
+				__leave;
+			}
+			dwReturn = VerifyPIN(pCardData, ROLE_USER, pbPin, cbPin);
+			if (pcAttemptsRemaining)
+			{
+				GetRemainingPin(pCardData, ROLE_USER, pcAttemptsRemaining);
+			}
+		}
+		else if ( wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0)
+		{
+			dwReturn = CheckPinLength(pCardData, ROLE_ADMIN, cbPin);
+			if (dwReturn)
+			{
+				__leave;
+			}
+			dwReturn = VerifyPIN(pCardData, ROLE_ADMIN, pbPin, cbPin);
+			if (pcAttemptsRemaining)
+			{
+				GetRemainingPin(pCardData, ROLE_ADMIN, pcAttemptsRemaining);
+			}
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId unknown : %s", pwszUserId);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** A card principal can be authenticated by using either a PIN 
+or a challenge/response protocol in which the card generates a block
+of challenge data by using its administrative key. The authenticating
+caller must compute the response to the challenge by using shared
+knowledge of that key and submit the response back to the card. 
+If the response is correct, the principal is authenticated to the card. */
+
+DWORD WINAPI CardGetChallenge(
+    __in PCARD_DATA  pCardData,
+    __deref_out_bcount(*pcbChallengeData) PBYTE  *ppbChallengeData,
+    __out PDWORD  pcbChallengeData
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The CardAuthenticateChallenge function performs authentication of
+a card principal by using a challenge/response protocol. The caller of
+this function must have previously called CardGetChallenge to retrieve
+the challenge data from the card and computed the correct response data
+to submit with this call. */
+
+DWORD WINAPI CardAuthenticateChallenge(
+    __in PCARD_DATA  pCardData,
+    __in_bcount(cbResponseData) PBYTE pbResponseData,
+    __in DWORD  cbResponseData,
+    __out_opt PDWORD  pcAttemptsRemaining
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The CardDeauthenticate function is an optional export that should be
+provided if it is possible within the card minidriver to efficiently reverse
+the effect of authenticating a user or administrator without resetting 
+the card. If this function is not implemented, the card minidriver should 
+put NULL in the CARD_DATA structure pointer for this function.
+The Base CSP/KSP tests this pointer for NULL value before calling it. If it
+is found NULL, the Base CSP/KSP deauthenticates a user by resetting the 
+card. Because a card reset is a time-consuming operation, the card minidriver
+should implement this function if it can be done.
+*/
+
+DWORD WINAPI CardDeauthenticate(
+    __in PCARD_DATA  pCardData,
+    __in LPWSTR  pwszUserId,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pwszUserId == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( dwFlags != 0 )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags != 0 : %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( dwReturn )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = Deauthenticate(pCardData);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardAuthenticateEx function handles PIN authentication operations to the card.
+This function replaces the CardAuthenticate function of earlier versions of these 
+specifications and adds support for the following PIN types:
+•	External PINs, which are PINs that are accessed from a device that is connected to the computer.
+•	Challenge/response PINs.
+•	Secure PIN channels.
+•	Session PINs.
+*/
+DWORD WINAPI CardAuthenticateEx(
+    __in PCARD_DATA  pCardData,
+    __in PIN_ID  PinId,
+    __in DWORD  dwFlags,
+    __in_bcount(cbPinData) PBYTE  pbPinData,
+    __in  DWORD  cbPinData,
+    __deref_opt_out_bcount(*pcbSessionPin) PBYTE  *ppbSessionPin,
+    __out_opt PDWORD  pcbSessionPin,
+    __out_opt PDWORD  pcAttemptsRemaining
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter authenticate %d", PinId);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbPinData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbPinData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ((dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN)
+			|| (dwFlags & CARD_AUTHENTICATE_SESSION_PIN))
+		{
+			if ( ( ppbSessionPin == NULL ) ||
+					( pcbSessionPin == NULL ) )
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"ppbSessionPin == NULL");
+				dwReturn  = SCARD_E_INVALID_PARAMETER;
+				__leave;
+			}
+			else
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"SESSION_PIN SCARD_E_UNSUPPORTED_FEATURE");
+				dwReturn  = SCARD_E_UNSUPPORTED_FEATURE;
+				__leave;
+			}
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( dwReturn )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckPinLength(pCardData, PinId, cbPinData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = VerifyPIN(pCardData, PinId, pbPinData, cbPinData);
+		if (pcAttemptsRemaining)
+		{
+			GetRemainingPin(pCardData, PinId, pcAttemptsRemaining);
+		}
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** Besides authentication by using a PIN, a card principal can be authenticated
+by using a challenge/response protocol in which the card generates a block of challenge data.
+The authenticating caller must compute the response to the challenge by using
+shared knowledge of a key and submit the response back to the card by calling
+CardGetChallengeEx. If the response is correct, the principal is authenticated to the card.
+*/
+
+DWORD WINAPI CardGetChallengeEx(
+    __in PCARD_DATA  pCardData,
+    __in PIN_ID  PinId,
+    __deref_out_bcount(*pcbChallengeData) PBYTE  *ppbChallengeData,
+    __out PDWORD  pcbChallengeData,
+    __in DWORD  dwFlags
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The CardDeauthenticateEx function must always be provided. If it is not
+possible within the card minidriver to efficiently reverse the effect of an 
+authentication operation without resetting the card, the call must return 
+SCARD_E_UNSUPPORTED_FEATURE. In this situation, the Base CSP/KSP performs 
+deauthentication by resetting the card. Because a card reset is a time-consuming 
+operation, the card minidriver must implement this function if it can be done.*/
+
+DWORD WINAPI CardDeauthenticateEx(
+    __in PCARD_DATA  pCardData,
+    __in PIN_SET  PinId,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( dwFlags != 0 )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags != 0 : %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( dwReturn )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = Deauthenticate(pCardData);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardUnblockPin function is used to unblock a card that has become
+blocked by too many incorrect PIN entry attempts. The unblock function is
+atomic in that authentication and unblocking the card must occur as a single
+operation. Therefore, authentication information and the new user PIN must
+be presented when the call is made.*/
+
+DWORD WINAPI CardUnblockPin(
+    __in PCARD_DATA  pCardData,
+    __in LPWSTR  pwszUserId,
+    __in_bcount(cbAuthenticationData) PBYTE  pbAuthenticationData,
+    __in DWORD  cbAuthenticationData,
+    __in_bcount(cbNewPinData) PBYTE  pbNewPinData,
+    __in DWORD  cbNewPinData,
+    __in DWORD  cRetryCount,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pwszUserId == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbAuthenticationData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbAuthenticationData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbNewPinData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbNewPinData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (!(dwFlags & CARD_AUTHENTICATE_PIN_PIN))
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( !dwReturn )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( wcscmp(pwszUserId, wszCARD_USER_USER) == 0 ) 
+		{
+			dwReturn = ResetUserPIN(pCardData, ROLE_PUK,
+									pbAuthenticationData, cbAuthenticationData,
+									pbNewPinData, cbNewPinData);
+		}
+		else if ( wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"wszCARD_USER_ADMIN");
+			__leave;
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId unknown : %s", pwszUserId);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** This function changes the authenticator for the affected card principal. 
+It can be used to change a user’s PIN or to change the challenge/response key.
+The two usages are distinguished by use of a flag value.*/
+
+DWORD WINAPI CardChangeAuthenticator(
+    __in PCARD_DATA  pCardData,
+    __in LPWSTR  pwszUserId,
+    __in_bcount(cbCurrentAuthenticator) 
+        PBYTE  pbCurrentAuthenticator,
+    __in DWORD  cbCurrentAuthenticator,
+    __in_bcount(cbNewAuthenticator) PBYTE  pbNewAuthenticator,
+    __in DWORD  cbNewAuthenticator,
+    __in DWORD   cRetryCount,
+    __in DWORD  dwFlags,
+    __out_opt PDWORD  pcAttemptsRemaining
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pwszUserId == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbCurrentAuthenticator == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbCurrentAuthenticator == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbNewAuthenticator == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbNewAuthenticator == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (!(dwFlags & CARD_AUTHENTICATE_PIN_PIN))
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( !dwReturn )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( wcscmp(pwszUserId, wszCARD_USER_USER) == 0 ) 
+		{
+			dwReturn = ChangePIN(pCardData, ROLE_USER,
+								pbCurrentAuthenticator, cbCurrentAuthenticator,
+								pbNewAuthenticator, cbNewAuthenticator);
+			if (pcAttemptsRemaining)
+			{
+				GetRemainingPin(pCardData, ROLE_USER, pcAttemptsRemaining);
+			}
+		}
+		else if ( wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0)
+		{
+			dwReturn = ChangePIN(pCardData, ROLE_ADMIN,
+								pbCurrentAuthenticator, cbCurrentAuthenticator,
+								pbNewAuthenticator, cbNewAuthenticator);
+			if (pcAttemptsRemaining)
+			{
+				GetRemainingPin(pCardData,ROLE_ADMIN, pcAttemptsRemaining);
+			}
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pwszUserId unknown : %s", pwszUserId);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+
+/** This function changes the authenticator for the affected card principal.
+It can be used to change a PIN or unblock a PIN. The usages are distinguished 
+by use of a flag value.*/
+
+DWORD WINAPI CardChangeAuthenticatorEx(
+    __in PCARD_DATA  pCardData,
+    __in DWORD  dwFlags,
+    __in PIN_ID  dwAuthenticatingPinId,
+    __in_bcount(cbAuthenticatingPinData) 
+          PBYTE  pbAuthenticatingPinData,
+    __in DWORD  cbAuthenticatingPinData,
+    __in PIN_ID  dwTargetPinId,
+    __in_bcount(cbTargetData) PBYTE  pbTargetData,
+    __in DWORD  cbTargetData,
+    __in  DWORD  cRetryCount,
+    __out_opt PDWORD  pcAttemptsRemaining
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbAuthenticatingPinData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbAuthenticatingPinData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbTargetData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbTargetData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (!(dwFlags & CARD_AUTHENTICATE_PIN_PIN))
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if ( !dwReturn )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"GetContext dwReturn == 0x%08X", dwReturn);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( dwAuthenticatingPinId == dwTargetPinId) 
+		{
+			dwReturn = ChangePIN(pCardData, dwAuthenticatingPinId,
+								pbAuthenticatingPinData, cbAuthenticatingPinData,
+								pbTargetData, cbTargetData);
+			if (pcAttemptsRemaining)
+			{
+				GetRemainingPin(pCardData, dwAuthenticatingPinId, pcAttemptsRemaining);
+			}
+		}
+		else if ( dwAuthenticatingPinId == ROLE_ADMIN &&  dwTargetPinId == ROLE_USER) 
+		{
+			dwReturn = ResetUserPIN(pCardData, ROLE_ADMIN,
+								pbAuthenticatingPinData, cbAuthenticatingPinData,
+								pbTargetData, cbTargetData);
+			if (pcAttemptsRemaining)
+			{
+				GetRemainingPin(pCardData,dwTargetPinId, pcAttemptsRemaining);
+			}
+		}
+		else
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"unknown role match: %d %d", dwAuthenticatingPinId, dwTargetPinId);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}

Added: trunk/OpenPGPminidriver/CardPublicDataOperation.c
===================================================================
--- trunk/OpenPGPminidriver/CardPublicDataOperation.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CardPublicDataOperation.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,421 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "PublicDataOperations.h"
+
+// 4.3 Public Data Operations
+
+/** This function creates a subdirectory from the root in the file system of 
+the card and applies the provided access condition. Directories are generally 
+created for segregating the files that belong to a single application on the card.
+As an example, the files that belong to the Microsoft cryptographic application 
+are in the “mscp” directory.*/
+
+DWORD WINAPI CardCreateDirectory(
+    __in PCARD_DATA  pCardData,
+    __in LPSTR  pszDirectoryName,
+    __in CARD_DIRECTORY_ACCESS_CONDITION  AccessCondition
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** This function deletes a directory from the card. This operation fails if it violates
+permissions on the directory or if the directory is not empty. */
+DWORD WINAPI CardDeleteDirectory(
+    __in CARD_DATA  *pCardData,
+    __in LPSTR  pszDirectoryName
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The CardReadFile function reads the entire file at the specified location into the 
+user-supplied buffer.*/
+DWORD WINAPI CardReadFile(
+    __in PCARD_DATA  pCardData,
+    __in_opt LPSTR  pszDirectoryName,
+    __in LPSTR  pszFileName,
+    __in DWORD  dwFlags,
+    __deref_out_bcount_opt(*pcbData) PBYTE  *ppbData,
+    __out PDWORD  pcbData
+)
+{
+	DWORD dwReturn = 0;	
+	PSTR szFiles = NULL;
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter %S\\%S",pszDirectoryName,pszFileName);
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pszFileName == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pszFileName == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (ppbData == NULL)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"ppbData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (pcbData == NULL)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pcbData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags != 0)
+		{
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardReadFile(pCardData, pszDirectoryName, pszFileName, ppbData, pcbData);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardCreateFile function creates a file on the card with a specified name and
+access permission. This function cannot be used to create directories. If the directory 
+that is named by pszDirectoryName does not exist, the function fails with SCARD_E_DIR_NOT_FOUND.*/
+DWORD WINAPI CardCreateFile(
+    __in PCARD_DATA  pCardData,
+    __in_opt LPSTR  pszDirectoryName,
+    __in LPSTR  pszFileName,
+    __in DWORD  cbInitialCreationSize,
+    __in CARD_FILE_ACCESS_CONDITION  AccessCondition
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pszFileName == NULL || pszFileName[0] == 0)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pszFileName == NULL or empty");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardCreateFile(pCardData, pszDirectoryName, pszFileName);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** This function retrieves information about a file, specifically its size and ACL information.*/
+
+DWORD WINAPI CardGetFileInfo(
+    __in PCARD_DATA  pCardData,
+    __in_opt LPSTR  pszDirectoryName,
+    __in LPSTR  pszFileName,
+    __inout PCARD_FILE_INFO  pCardFileInfo
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pszFileName == NULL || pszFileName[0] == 0)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pszFileName == NULL or empty");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pCardFileInfo == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardFileInfo == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardGetFileInfo(pCardData, pszDirectoryName, pszFileName, pCardFileInfo);
+
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardWriteFile function writes the entire contents of a data buffer to a file. 
+The file contents are replaced, starting at the beginning of the file. The file must 
+exist, or CardWriteFile fails.*/
+
+DWORD WINAPI CardWriteFile(
+    __in PCARD_DATA  pCardData,
+    __in_opt LPSTR  pszDirectoryName,
+    __in LPSTR  pszFileName,
+    __in DWORD  dwFlags,
+    __in_bcount(cbData) PBYTE  pbData,
+    __in DWORD  cbData
+)
+{
+	DWORD dwReturn = 0;	
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pszFileName == NULL || pszFileName[0] == 0)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pszFileName == NULL or empty");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pbData == NULL)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pbData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( cbData == 0)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"cbData == 0");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == %d", dwFlags);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardWriteFile(pCardData, pszDirectoryName, pszFileName, pbData, cbData);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardDeleteFile function deletes the specified file. If the file does not exist,
+the returned Status value should indicate that the file did not exist.*/
+
+DWORD WINAPI CardDeleteFile(
+    __in PCARD_DATA  pCardData,
+    __in_opt LPSTR  pszDirectoryName,
+    __in LPSTR  pszFileName,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	
+	PBYTE pbData = NULL;
+	DWORD dwSize = 0;
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pszFileName == NULL || pszFileName[0] == 0)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pszFileName == NULL or empty");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == 0");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		// try to read the file to see if it exists and return the right error code
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardDeleteFile(pCardData, pszDirectoryName, pszFileName);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardEnumFiles function returns name information about available files in a 
+directory as a multistring list.*/
+
+DWORD WINAPI CardEnumFiles(
+    __in PCARD_DATA  pCardData,
+    __in_opt LPSTR  pszDirectoryName,
+    __deref_out_ecount(*pdwcbFileName) LPSTR  *pmszFileNames,
+    __out LPDWORD  pdwcbFileName,
+    __in DWORD  dwFlags
+)
+{
+	DWORD dwReturn = 0;	
+	PSTR szFiles = NULL;
+	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pmszFileNames == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pmszFileNames == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pmszFileNames == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pmszFileNames == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags != 0)
+		{
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags = 0x%08X", dwFlags);
+			__leave;
+		}
+		if (pszDirectoryName != NULL)
+		{
+			DWORD dwLen = (DWORD) strlen(pszDirectoryName);
+			if (dwLen > 8 || dwLen == 0)
+			{
+				dwReturn = SCARD_E_INVALID_PARAMETER;
+				Trace(WINEVENT_LEVEL_ERROR, L"Invalid directory %S", pszDirectoryName);
+				__leave;
+			}
+		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = SCardEnumFile(pCardData, pszDirectoryName, pmszFileNames, pdwcbFileName);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+/** The CardQueryFreeSpace function determines the amount of available card storage space.*/
+DWORD WINAPI CardQueryFreeSpace(
+    __in PCARD_DATA  pCardData,
+    __in DWORD  dwFlags,
+    __inout PCARD_FREE_SPACE_INFO  pCardFreeSpaceInfo
+)
+{
+	DWORD dwReturn = 0;	
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if ( pCardFreeSpaceInfo == NULL)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardFreeSpaceInfo == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (dwFlags)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFlags == 0");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		pCardFreeSpaceInfo->dwVersion = CARD_FREE_SPACE_INFO_CURRENT_VERSION;
+		pCardFreeSpaceInfo->dwMaxKeyContainers = 3;
+		pCardFreeSpaceInfo->dwKeyContainersAvailable = CARD_DATA_VALUE_UNKNOWN;
+		pCardFreeSpaceInfo->dwBytesAvailable = CARD_DATA_VALUE_UNKNOWN;
+		dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+

Added: trunk/OpenPGPminidriver/CardSecureKeyInjection.c
===================================================================
--- trunk/OpenPGPminidriver/CardSecureKeyInjection.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CardSecureKeyInjection.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,163 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+
+// 4.8 Secure key injection
+
+
+/** The CardImportSessionKey function imports a temporary session key to the card.
+The session key is encrypted with a key exchange key, and the function returns a
+handle of the imported session key to the caller.*/
+
+DWORD WINAPI CardImportSessionKey(
+    __in PCARD_DATA  pCardData,
+    __in BYTE  bContainerIndex,
+    __in VOID  *pPaddingInfo,
+    __in LPCWSTR  pwszBlobType,
+    __in LPCWSTR  pwszAlgId,
+    __out CARD_KEY_HANDLE  *phKey,
+    __in_bcount(cbInput) PBYTE  pbInput,
+    __in DWORD  cbInput,
+    __in DWORD  dwFlags
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The MDImportSessionKey function imports a temporary session key to the card minidriver
+and returns a key handle to the caller.*/
+
+DWORD WINAPI MDImportSessionKey(
+    __in PCARD_DATA  pCardData,
+    __in LPCWSTR  pwszBlobType,
+    __in LPCWSTR  pwszAlgId,
+    __out PCARD_KEY_HANDLE  phKey,
+    __in_bcount(cbInput) PBYTE  pbInput,
+    __in DWORD  cbInput
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The MDEncryptData function uses a key handle to encrypt data with a symmetric key.
+The data is encrypted in a format that the smart card supports.*/
+
+DWORD WINAPI MDEncryptData(
+    __in PCARD_DATA  pCardData,
+    __in CARD_KEY_HANDLE  hKey,
+    __in LPCWSTR  pwszSecureFunction,
+    __in_bcount(cbInput) PBYTE  pbInput,
+    __in DWORD  cbInput,
+    __in DWORD  dwFlags,
+    __deref_out_ecount(*pcEncryptedData) 
+        PCARD_ENCRYPTED_DATA  *ppEncryptedData,
+    __out PDWORD  pcEncryptedData
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+
+/** The CardGetSharedKeyHandle function returns a session key handle to the caller.
+Note:  The manner in which this session key has been established is outside the 
+scope of this specification. For example, the session key could be established 
+by either a permanent shared key or a key derivation algorithm that has occurred 
+before the call to CardGetSharedKeyHandle.*/
+
+DWORD WINAPI CardGetSharedKeyHandle(
+    __in PCARD_DATA  pCardData,
+    __in_bcount(cbInput) PBYTE  pbInput,
+    __in DWORD  cbInput,
+    __deref_opt_out_bcount(*pcbOutput)
+        PBYTE  *ppbOutput,
+    __out_opt PDWORD  pcbOutput,
+    __out PCARD_KEY_HANDLE  phKey
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** The CardDestroyKey function releases a temporary key on the card. The card 
+should delete all of the key material that is associated with that key handle.*/
+
+DWORD WINAPI CardDestroyKey(
+    __in PCARD_DATA  pCardData,
+    __in CARD_KEY_HANDLE  hKey
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** This function can be used to get properties for a cryptographic algorithm.*/
+DWORD WINAPI CardGetAlgorithmProperty (
+    __in PCARD_DATA  pCardData,
+    __in LPCWSTR   pwszAlgId,
+    __in LPCWSTR   pwszProperty,
+    __out_bcount_part_opt(cbData, *pdwDataLen)
+        PBYTE  pbData,
+    __in DWORD  cbData,
+    __out PDWORD  pdwDataLen,
+    __in DWORD  dwFlags
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** This function is used to set the properties of a key.*/
+DWORD WINAPI CardSetKeyProperty(
+    __in PCARD_DATA  pCardData,
+    __in CARD_KEY_HANDLE  hKey,
+    __in LPCWSTR  pwszProperty,
+    __in_bcount(cbInput) PBYTE  pbInput,
+    __in DWORD  cbInput,
+    __in DWORD  dwFlags
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+
+/** CardProcessEncryptedData processes a set of encrypted data BLOBs by 
+sending them to the card where the data BLOBs are decrypted.*/
+
+DWORD WINAPI CardProcessEncryptedData(
+    __in PCARD_DATA  pCardData,
+    __in CARD_KEY_HANDLE  hKey,
+    __in LPCWSTR  pwszSecureFunction,
+    __in_ecount(cEncryptedData)
+        PCARD_ENCRYPTED_DATA  pEncryptedData,
+    __in DWORD  cEncryptedData,
+    __out_bcount_part_opt(cbOutput, *pdwOutputLen)
+        PBYTE  pbOutput,
+    __in DWORD  cbOutput,
+    __out_opt PDWORD  pdwOutputLen,
+    __in DWORD  dwFlags
+)
+{
+	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+	return SCARD_E_UNSUPPORTED_FEATURE;
+}
+

Added: trunk/OpenPGPminidriver/Context.h
===================================================================
--- trunk/OpenPGPminidriver/Context.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/Context.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,67 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+typedef struct _OPENPGP_AID
+{
+	BYTE					AidRid[5];
+	BYTE					AidApplication[1];
+	BYTE					AidVersion[2];
+	BYTE					AidManufacturer[2];
+	BYTE					AidSerialNumber[4];
+	BYTE					AidRFU[2];
+} OPENPGP_AID;
+
+#define FEATURE_VERIFY_PIN_START         0x01 
+#define FEATURE_VERIFY_PIN_FINISH        0x02 
+#define FEATURE_MODIFY_PIN_START         0x03 
+#define FEATURE_MODIFY_PIN_FINISH        0x04 
+#define FEATURE_GET_KEY_PRESSED          0x05 
+#define FEATURE_VERIFY_PIN_DIRECT        0x06 
+#define FEATURE_MODIFY_PIN_DIRECT        0x07 
+#define FEATURE_MCT_READERDIRECT         0x08 
+#define FEATURE_MCT_UNIVERSAL            0x09 
+#define FEATURE_IFD_PIN_PROPERTIES       0x0A 
+#define FEATURE_ABORT                    0x0B 
+
+typedef struct _FEATURES
+{
+	DWORD VERIFY_PIN_START;
+	DWORD VERIFY_PIN_FINISH;
+	DWORD VERIFY_PIN_DIRECT;
+	DWORD MODIFY_PIN_START;
+	DWORD MODIFY_PIN_FINISH;
+	DWORD MODIFY_PIN_DIRECT;
+	DWORD ABORT;
+	DWORD GET_KEY_PRESSED;
+} FEATURES, *PFEATURES;
+
+typedef struct _OPENPGP_CONTEXT
+{
+	OPENPGP_AID				Aid;
+	FEATURES				SmartCardReaderFeatures;
+	BOOL					fSupportCommandChaining;
+	BOOL					fExtentedLeLcFields;
+	DWORD					dwMaxLength;
+	BOOL					fHasSignature;
+	BOOL					fHasDecryption;
+	BOOL					fHasAuthentication;
+} OPENPGP_CONTEXT, *POPENPGP_CONTEXT ;
+
+DWORD CreateContext(__in PCARD_DATA pCardData);
+DWORD CheckContext(__in PCARD_DATA pCardData);
+DWORD CleanContext(__in PCARD_DATA pCardData);
\ No newline at end of file

Added: trunk/OpenPGPminidriver/ContextManagement.c
===================================================================
--- trunk/OpenPGPminidriver/ContextManagement.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/ContextManagement.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,291 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "Smartcard.h"
+#include "PublicDataOperations.h"
+
+SCARD_ATRMASK SupportedATR [] =
+{
+	{ // v2 
+		21, 
+		//3B DA 18 FF 81 B1 FE 75 1F 03 00 31 C5 73 C0 01 40 00 90 00 0C
+		{0x3B,0xDA,0x18,0xFF,0x81,0xB1,0xFE,0x75,0x1F,0x03,
+			0x00,0x31,0xC5,0x73,0xC0,0x01,0x40,0x00,0x90,0x00,0x0C},
+		{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+			0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}
+	},
+	{ // v1
+		20, 
+		//3B FA 13 00 FF 81 31 80 45 00 31 C1 73 C0 01 00 00 90 00 B1
+		{0x3B,0xFA,0x13,0x00,0xFF,0x81,0x31,0x80,0x45,0x00,
+			0x31,0xC1,0x73,0xC0,0x01,0x00,0x00,0x90,0x00,0xB1},
+		{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+			0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}
+	}
+};
+DWORD dwSupportedATRCount = ARRAYSIZE(SupportedATR);
+
+BOOL find_compacttlv(__in PBYTE pbData, __in DWORD dwTotalSize, __in BYTE bCode, __out PBYTE *pbDataOut, __out_opt PDWORD pdwSize)
+{
+	DWORD dwOffset = 0;
+	DWORD dwSize;
+	while (dwOffset < dwTotalSize)
+	{
+		if (bCode * 0x10 == (pbData[dwOffset] & 0xF0) )
+		{
+			dwSize = (pbData[dwOffset] & 0x0F);
+			if (pdwSize)
+			{
+				*pdwSize = dwSize;
+			}
+			dwOffset++;
+			// size sequence
+			
+			*pbDataOut = pbData + dwOffset;
+			return TRUE;
+		}
+		else
+		{
+			
+			dwSize = (pbData[dwOffset] & 0x0F);
+			dwOffset += dwSize + 1;
+		}
+	}
+	return FALSE;
+}
+
+
+DWORD CreateContext(__in PCARD_DATA pCardData)
+{
+	DWORD dwReturn;
+	PBYTE					pbCapabilities = NULL, pbCardCapabilities;
+	PBYTE					pbExtendedCapabilities = NULL;
+	PBYTE					pbApplicationIdentifier = NULL;
+	DWORD					dwCapabilitiesSize, 
+							dwCardCapabilitiesSize,
+							dwApplicationIdentifierSize;
+	BYTE bCategoryIndicator, bStatusIndicator;
+	__try
+	{
+		POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+		if (pContext)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pContext != NULL");
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		// not found => initialize context
+		pContext = pCardData->pfnCspAlloc(sizeof(OPENPGP_CONTEXT));
+		if (!pContext)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
+			dwReturn = SCARD_E_NO_MEMORY;
+			__leave;
+		}
+		memset(pContext, 0, sizeof(OPENPGP_CONTEXT));
+		pCardData->pvVendorSpecific = pContext;
+
+		dwReturn = SelectOpenPGPApplication(pCardData);
+		if (dwReturn)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"No SelectOpenPGPApplication");
+			__leave;
+		}
+		dwReturn = SCardReadFile(pCardData, szOpenPGPDir, szOpenPGPApplicationIdentifier, &pbApplicationIdentifier, &dwApplicationIdentifierSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		if (dwApplicationIdentifierSize != sizeof(OPENPGP_AID))
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwApplicationIdentifierSize = %02X", dwApplicationIdentifierSize);
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		memcpy(&(pContext->Aid),pbApplicationIdentifier,sizeof(OPENPGP_AID));
+		dwReturn = SCardReadFile(pCardData, szOpenPGPDir, szOpenPGPHistoricalBytes, &pbCapabilities, &dwCapabilitiesSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		bCategoryIndicator = pbCapabilities[0];
+		if (bCategoryIndicator != 0)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"bCategoryIndicator = %02X", bCategoryIndicator);
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		bStatusIndicator = pbCapabilities[dwCapabilitiesSize -3];
+		if (bStatusIndicator != 0 && bStatusIndicator != 03 && bStatusIndicator != 05)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"bStatusIndicator = %02X", bStatusIndicator);
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		if (!find_compacttlv(pbCapabilities + 1, dwCapabilitiesSize - 1, 7, &pbCardCapabilities, &dwCardCapabilitiesSize))
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"tlv not found");
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		if (dwCardCapabilitiesSize != 3)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwCardCapabilitiesSize = %02X", dwCardCapabilitiesSize);
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		//dwReturn = SCardReadFile(pCardData, szOpenPGPDir, szOpenPGPExtendedCap, &pbExtendedCapabilities, &dwExtendedCapabilitiesSize);
+		if (dwReturn)
+		{
+			//__leave;
+		}
+		pContext->fExtentedLeLcFields = ((pbCardCapabilities[2] & 0x40)?TRUE:FALSE);
+		pContext->fSupportCommandChaining = ((pbCardCapabilities[2] & 0x80)?TRUE:FALSE);
+		pContext->dwMaxLength = 0x0800;// pbCapabilities[8] * 256 + pbCapabilities[9];
+		dwReturn = CCIDgetFeatures(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = 0;
+	}
+	__finally
+	{
+		if (pbApplicationIdentifier)
+			pCardData->pfnCspFree(pbApplicationIdentifier);
+		if (pbCapabilities)
+			pCardData->pfnCspFree(pbCapabilities);
+		if (pbExtendedCapabilities)
+			pCardData->pfnCspFree(pbExtendedCapabilities);
+	}
+	return dwReturn;
+}
+
+
+DWORD CheckContext(__in PCARD_DATA pCardData)
+{
+	DWORD dwReturn;
+	DWORD dwI, dwJ;
+	BOOL fFound = FALSE;
+	BOOL fRightATRLenFound = FALSE;
+	__try
+	{
+		if ( pCardData == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (pCardData->pbAtr == NULL)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData->pbAtr == NULL");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+
+		if (pCardData->dwVersion < CARD_DATA_VERSION_SIX)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData->dwVersion(%d) < CARD_DATA_VERSION_SIX", pCardData->dwVersion);
+			dwReturn  = ERROR_REVISION_MISMATCH;
+			__leave;
+		}
+		pCardData->dwVersion = min(pCardData->dwVersion, CARD_DATA_VERSION_SIX);
+		for (dwI = 0; dwI < dwSupportedATRCount; dwI++)
+		{
+			if (SupportedATR[dwI].cbAtr == pCardData->cbAtr)
+			{
+				BYTE pbAtr[36];
+				fRightATRLenFound = TRUE;
+				memcpy(pbAtr, pCardData->pbAtr, SupportedATR[dwI].cbAtr);
+				for( dwJ = 0; dwJ < SupportedATR[dwI].cbAtr; dwJ++)
+				{
+					pbAtr[dwJ] &= SupportedATR[dwI].rgbMask[dwJ];
+				}
+				if (memcmp(pbAtr, pCardData->pbAtr, SupportedATR[dwI].cbAtr) == 0)
+				{
+					fFound = TRUE;
+					//Trace(WINEVENT_LEVEL_VERBOSE, L"card match ATR %d", dwI);
+					break;
+				}
+
+			}
+		}
+		if (!fRightATRLenFound)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"card doesn't match ATR len %d",pCardData->cbAtr);
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (!fFound)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"card doesn't match ATR");
+			dwReturn  = SCARD_E_UNKNOWN_CARD;
+			__leave;
+		}
+
+		if ( pCardData->pwszCardName == NULL )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData->pwszCardName");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		/* Memory management functions */
+		if ( ( pCardData->pfnCspAlloc   == NULL ) ||
+			( pCardData->pfnCspReAlloc == NULL ) ||
+			( pCardData->pfnCspFree    == NULL ) )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"Memory functions null");
+			dwReturn  = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (!pCardData->pvVendorSpecific)
+		{
+			// not found =>
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD CleanContext(__in PCARD_DATA pCardData)
+{
+	DWORD dwReturn = 0;
+	__try
+	{
+		if (pCardData)
+		{
+			if ( pCardData->pvVendorSpecific)
+			{
+				pCardData->pfnCspFree( pCardData->pvVendorSpecific);
+				pCardData->pvVendorSpecific = NULL;
+			}
+		}
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriver/CryptoOperations.c
===================================================================
--- trunk/OpenPGPminidriver/CryptoOperations.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CryptoOperations.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,779 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "SmartCard.h"
+#include "CryptoOperations.h"
+#include "PinOperations.h"
+#include "PublicDataOperations.h"
+
+OPENPGP_CONTAINER_INFO Containers[] = 
+{
+	{0xB6, CALG_RSA_SIGN, AT_SIGNATURE, ROLE_SIGNATURE},
+	{0xA4, CALG_RSA_SIGN, AT_SIGNATURE, ROLE_AUTHENTICATION},
+	{0xB8, CALG_RSA_KEYX, AT_KEYEXCHANGE, ROLE_CONFIDENTIALITY}
+	
+};
+
+typedef struct _OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM
+{
+	ALG_ID aiHashAlg;
+	DWORD  dwHashSize;
+	PBYTE pbEncodedOid;
+	DWORD dwEncodedOidSize;
+} OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM, *POPENPGP_SUPPORTED_SIGNATURE_ALGORITHM;
+
+BYTE dwSHA1EncodedOid[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
+			0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
+BYTE dwSHA256EncodedOid[] = {0x30, 0x31, 0x30, 0x0D,0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+			0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+BYTE dwSHA384EncodedOid[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+			0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
+BYTE dwSHA512EncodedOid[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+			0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+
+OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM SignatureAlgorithm[] = 
+{
+	{CALG_SHA1,20, 
+			dwSHA1EncodedOid,
+			ARRAYSIZE(dwSHA1EncodedOid)},
+	{CALG_SHA-256,32,
+			dwSHA256EncodedOid,
+			ARRAYSIZE(dwSHA256EncodedOid)},
+	{CALG_SHA-384,48,
+			dwSHA384EncodedOid,
+			ARRAYSIZE(dwSHA384EncodedOid)},
+	{CALG_SHA-512,64,
+			dwSHA512EncodedOid,
+			ARRAYSIZE(dwSHA512EncodedOid)},
+};
+
+DWORD dwSignatureAlgorithmCount = ARRAYSIZE(SignatureAlgorithm);
+
+#pragma pack(push,1)
+typedef struct _OPENPGP_ALGORITHM_ATTRIBUTE
+{
+	BYTE bAlgoId;
+	unsigned short wModulusLength;
+	unsigned short wExponentLength;
+	BYTE bFormat;
+} OPENPGP_ALGORITHM_ATTRIBUTE, *POPENPGP_ALGORITHM_ATTRIBUTE;
+#pragma pack(pop)
+
+typedef struct _RSAPUBLICKEYBLOB
+{
+	BLOBHEADER blobheader;
+	RSAPUBKEY rsapubkey;
+	BYTE modulus[sizeof(DWORD)];
+} RSAPUBLICKEYBLOB, *PRSAPUBLICKEYBLOB;
+
+DWORD getTlvSize(__in PBYTE pbPointer, __in PDWORD pdwOffset)
+{
+	DWORD dwSize;
+	switch(*pbPointer)
+	{
+	case 0x81:
+		*pdwOffset+=2;
+		dwSize = pbPointer[1];
+		break;
+	case 0x82:
+		*pdwOffset+=3;
+		dwSize = pbPointer[1] * 0x100 + pbPointer[2];
+		break;
+	default:
+		dwSize = *pbPointer;
+		*pdwOffset+=1;
+		break;
+	}
+	return dwSize;
+}
+
+BOOL find_tlv(__in PBYTE pbData, __in BYTE bCode, __out PBYTE *pbDataOut, __out_opt PDWORD pdwSize)
+{
+	DWORD dwOffset = 2;
+	DWORD dwSize;
+	DWORD dwTotalSize = getTlvSize(pbData + 2,&dwOffset) + 2;
+	while (dwOffset < dwTotalSize)
+	{
+		if (bCode == pbData[dwOffset])
+		{
+			dwOffset++;
+			// size sequence
+			dwSize = getTlvSize(pbData + dwOffset,&dwOffset);
+			if (pdwSize)
+			{
+				*pdwSize = dwSize;
+			}
+			*pbDataOut = pbData + dwOffset;
+			return TRUE;
+		}
+		else
+		{
+			dwOffset++;
+			dwSize = getTlvSize(pbData + dwOffset,&dwOffset);
+			dwOffset += dwSize;
+		}
+	}
+	return FALSE;
+}
+
+
+DWORD GetKeyAlgorithmAttributes(__in PCARD_DATA pCardData, 
+								__in OPENPGP_CONTAINER dwContainer,
+								__out POPENPGP_ALGORITHM_ATTRIBUTE pAttributes)
+{
+	DWORD dwReturn;
+	PSTR szAlgorithmAttributes = NULL;
+	PBYTE pbData = NULL;
+	DWORD dwResponseSize;
+	WORD wTemp;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
+		switch(dwContainer)
+		{
+		case Signature:
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesSignature;
+			break;
+		case Authentication:
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
+			break;
+		case Confidentiality:
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
+			break;
+		default:
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
+			__leave;
+		}
+		dwReturn = SCardReadFile(pCardData, szOpenPGPDir, szAlgorithmAttributes, &pbData, &dwResponseSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		if (dwResponseSize != sizeof(OPENPGP_ALGORITHM_ATTRIBUTE))
+		{
+			dwReturn = SCARD_E_UNEXPECTED;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED");
+			__leave;
+		}
+		memcpy(pAttributes, pbData, dwResponseSize);
+		// big endian, little endian ...
+		wTemp = pAttributes->wExponentLength;
+		pAttributes->wExponentLength = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
+		wTemp = pAttributes->wModulusLength;
+		pAttributes->wModulusLength = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
+		
+		dwReturn = 0;
+	}
+	__finally
+	{
+		if (pbData)
+			pCardData->pfnCspFree(pbData);
+	}
+	return dwReturn;
+}
+
+DWORD SetKeyAlgorithmAttributes(__in PCARD_DATA pCardData, 
+								__in OPENPGP_CONTAINER dwContainer,
+								__out POPENPGP_ALGORITHM_ATTRIBUTE pAttributes)
+{
+	DWORD dwReturn;
+	PSTR szAlgorithmAttributes = NULL;
+	OPENPGP_ALGORITHM_ATTRIBUTE TempAttributes;
+	WORD wTemp;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
+		switch(dwContainer)
+		{
+		case Signature:
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesSignature;
+			break;
+		case Authentication:
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
+			break;
+		case Confidentiality:
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
+			break;
+		default:
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
+			__leave;
+		}
+		memcpy(&TempAttributes, pAttributes, sizeof(OPENPGP_ALGORITHM_ATTRIBUTE));
+		wTemp = TempAttributes.wExponentLength;
+		TempAttributes.wExponentLength = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
+		wTemp = TempAttributes.wModulusLength;
+		TempAttributes.wModulusLength = (wTemp % 0x100) * 0x100 + (wTemp / 0x100);
+
+		dwReturn = SCardWriteFile(pCardData, szOpenPGPDir, szAlgorithmAttributes, (PBYTE) &TempAttributes, sizeof(OPENPGP_ALGORITHM_ATTRIBUTE));
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD BuildPrivateKeyTlv(__in PCARD_DATA pCardData, __in PRSAPUBLICKEYBLOB pbPublicKeyBlob,
+						 __out PBYTE * ppbTlv, __out PDWORD pdwTlvSize)
+{
+	DWORD dwReturn;
+	__try
+	{
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD SCardReadPublicKey(PCARD_DATA pCardData, OPENPGP_CONTAINER dwContainer, PBYTE *pbPublicKey, PDWORD pdwPublicKeySize)
+{
+	DWORD dwReturn;
+	PBYTE pbData = NULL;
+	DWORD dwResponseSize = 0;
+	BYTE pbCmd[] = {0x00, 
+				    0x47,
+					0x81,
+					0x00,
+					0x00,
+					0x00,
+					0x02,
+					0x00,
+					0x00,
+					0x00,
+					0x00
+					};
+	DWORD dwCmdSize;
+	POPENPGP_CONTEXT pContext;
+	PBYTE pbModulus;
+	DWORD dwModulusSize;
+	PBYTE pbExponent;
+	PRSAPUBLICKEYBLOB pbBlob = NULL;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
+		if (dwContainer >= MaxContainer)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
+			__leave;
+		}
+		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+		pbCmd[7] = Containers[dwContainer].Tag;
+		dwCmdSize = 9;
+		if (pContext->fExtentedLeLcFields)
+		{
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
+		}
+		else
+		{
+			pbCmd[dwCmdSize++] = 0xFF;
+		}
+
+		dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		//TraceDump(WINEVENT_LEVEL_INFO, pbData,dwSize);
+		if (!find_tlv(pbData,0x81,&pbModulus,&dwModulusSize))
+		{
+			dwReturn = SCARD_E_UNEXPECTED;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
+			__leave;
+		}
+		if (!find_tlv(pbData,0x82,(PBYTE*)&pbExponent,NULL))
+		{
+			dwReturn = SCARD_E_UNEXPECTED;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
+			__leave;
+		}
+		*pdwPublicKeySize = sizeof(RSAPUBLICKEYBLOB) + dwModulusSize - sizeof(DWORD);
+		*pbPublicKey = pCardData->pfnCspAlloc(*pdwPublicKeySize);
+		if (!*pbPublicKey)
+		{
+			dwReturn = SCARD_E_NO_MEMORY;
+			Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_MEMORY %d", dwContainer);
+			__leave;
+		}
+		pbBlob = (PRSAPUBLICKEYBLOB) *pbPublicKey;
+		memset(pbBlob,0,*pdwPublicKeySize);
+		pbBlob->blobheader.bType = PUBLICKEYBLOB;
+		pbBlob->blobheader.bVersion = CUR_BLOB_VERSION;
+		pbBlob->blobheader.reserved = 0;
+		pbBlob->blobheader.aiKeyAlg = Containers[dwContainer].aiKeyAlg;
+		pbBlob->rsapubkey.magic = 0x31415352; //'RSA1';
+		pbBlob->rsapubkey.bitlen = dwModulusSize*8;
+		pbBlob->rsapubkey.pubexp = pbExponent[0] * 0x1000000  + pbExponent[1] * 0x10000  + pbExponent[2] * 0x100 + pbExponent[3];
+		memcpy(pbBlob->modulus, pbModulus, dwModulusSize);
+		//TraceDump(WINEVENT_LEVEL_INFO, (PBYTE) pbBlob,*pdwPublicKeySize);
+		dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD SCardCreateKey(PCARD_DATA pCardData, OPENPGP_CONTAINER dwContainer, DWORD dwBitLen)
+{
+	DWORD dwReturn;
+	PBYTE pbData = NULL;
+	DWORD dwResponseSize = 0, dwCmdSize;
+	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
+	POPENPGP_CONTEXT pContext;
+	BYTE pbCmd[] = {0x00, 
+				    0x47,
+					0x80,
+					0x00,
+					0x00,
+					0x00,
+					0x02,
+					0x00,
+					0x00,
+					0x00,
+					0x00
+					};
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
+		if (dwContainer >= MaxContainer)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwContainer);
+			__leave;
+		}
+		// key len
+		dwReturn = GetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
+		if (dwReturn == SCARD_E_FILE_NOT_FOUND)
+		{
+			Attributes.bAlgoId = 0x01;
+			Attributes.bFormat = 0;
+			Attributes.wExponentLength = 0x20;
+		} 
+		else if (dwReturn)
+		{
+			__leave;
+		}
+		Attributes.wModulusLength = (WORD) dwBitLen;
+		dwReturn = SetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
+		if (dwReturn)
+		{
+			__leave;
+		}
+
+		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+		pbCmd[7] = Containers[dwContainer].Tag;
+		dwCmdSize = 9;
+		if (pContext->fExtentedLeLcFields)
+		{
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
+		}
+		else
+		{
+			pbCmd[dwCmdSize++] = 0xFF;
+		}
+		
+		dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+	}
+	__finally
+	{
+		if (pbData)
+			pCardData->pfnCspFree(pbData);
+	}
+	return dwReturn;
+}
+
+DWORD SCardImportKey(PCARD_DATA pCardData, 
+					 OPENPGP_CONTAINER dwContainer,
+					 PBYTE pBlob,
+					 DWORD dwKeySize)
+{
+	DWORD dwReturn;
+	PSTR szAlgorithmAttributes = NULL;
+	PBYTE pbData = NULL;
+	DWORD dwResponseSize;
+	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
+	PRSAPUBLICKEYBLOB pbPublicKeyBlob = (PRSAPUBLICKEYBLOB) pBlob;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer);
+		// check blob
+		if (pbPublicKeyBlob->blobheader.aiKeyAlg != Containers[dwContainer].aiKeyAlg)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"Wrong aiKeyAlg %d", pbPublicKeyBlob->blobheader.aiKeyAlg);
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (pbPublicKeyBlob->blobheader.bType != PUBLICKEYBLOB)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"Wrong bType %d", pbPublicKeyBlob->blobheader.bType);
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (pbPublicKeyBlob->rsapubkey.magic != 0x32415352)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"Wrong magic");
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		
+		dwReturn = GetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
+		if (dwReturn == SCARD_E_FILE_NOT_FOUND)
+		{
+			Attributes.bAlgoId = 0x01;
+			Attributes.bFormat = 0;
+			Attributes.wExponentLength = 0x20;
+		} 
+		else if (dwReturn)
+		{
+			__leave;
+		}
+		Attributes.wModulusLength = (WORD) pbPublicKeyBlob->rsapubkey.bitlen;
+		dwReturn = SetKeyAlgorithmAttributes(pCardData, dwContainer, &Attributes);
+		if (dwReturn)
+		{
+			__leave;
+		}
+	}
+	__finally
+	{
+		if (dwReturn)
+		{
+			
+		}
+	}
+	return dwReturn;
+}
+
+DWORD SCardSign(PCARD_DATA pCardData,
+				PCARD_SIGNING_INFO  pInfo)
+{
+	DWORD dwReturn;
+	PBYTE pbData = NULL;
+	DWORD dwCmdSize = 0, dwI;
+	POPENPGP_CONTEXT pContext;
+	BYTE pbCmd[6 + 256 + 256] = {0x00, 
+				    0x2A,
+					0x9E,
+					0x9A,
+					0x00,
+					0x00,
+					};
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
+		if (pInfo->bContainerIndex >= MaxContainer)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
+			__leave;
+		}
+		if (pInfo->bContainerIndex != Signature)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
+			__leave;
+		}
+		if (CARD_PADDING_PKCS1 & pInfo->dwPaddingType)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PKCS1");
+			__leave;
+		}
+		else if (CARD_PADDING_PSS & pInfo->dwPaddingType)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PSS");
+			__leave;
+		}
+		for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
+		{
+			if (SignatureAlgorithm[dwI].aiHashAlg == pInfo->aiHashAlg)
+			{
+				// found
+				break;
+			}
+		}
+		if (dwI >= dwSignatureAlgorithmCount)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"alg not found %d", pInfo->aiHashAlg);
+			__leave;
+		}
+		if (SignatureAlgorithm[dwI].dwHashSize != pInfo->cbData)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wrong hash size %d", pInfo->cbData);
+			__leave;
+		}
+		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+
+		dwCmdSize = 5;
+		if (pContext->fExtentedLeLcFields)
+		{
+			dwCmdSize++;
+		}
+		pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwI].dwEncodedOidSize + pInfo->cbData);
+		memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwI].pbEncodedOid,SignatureAlgorithm[dwI].dwEncodedOidSize);
+		dwCmdSize += SignatureAlgorithm[dwI].dwEncodedOidSize;
+		for(dwI = 0 ; dwI < pInfo->cbData ; dwI++)
+		{
+			pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData - dwI -1];
+		}
+		//memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
+		dwCmdSize += pInfo->cbData;
+
+		
+		if (pContext->fExtentedLeLcFields)
+		{
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
+		}
+		else
+		{
+			pbCmd[dwCmdSize++] = 0;
+		}
+		dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &(pInfo->pbSignedData), &(pInfo->cbSignedData));
+		if (dwReturn == SCARD_W_WRONG_CHV)
+		{
+			dwReturn = SCARD_W_SECURITY_VIOLATION;
+			__leave;
+		}
+		if (dwReturn)
+		{
+			__leave;
+		}
+		// revert the BYTES
+		for(dwI = 0 ; dwI < pInfo->cbSignedData / 2 ; dwI++)
+		{
+			BYTE bTemp = pInfo->pbSignedData[dwI];
+			pInfo->pbSignedData[dwI] = pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI];
+			pInfo->pbSignedData[pInfo->cbSignedData - 1 - dwI] = bTemp;
+		}
+		TraceDump(WINEVENT_LEVEL_ERROR,pInfo->pbSignedData,pInfo->cbSignedData);
+	}
+	__finally
+	{
+		if (dwReturn)
+		{
+			if (pInfo->pbSignedData)
+				pCardData->pfnCspFree(pInfo->pbSignedData);
+		}
+	}
+	return dwReturn;
+}
+
+DWORD SCardDecrypt(PCARD_DATA pCardData,
+				PCARD_RSA_DECRYPT_INFO  pInfo)
+{
+	DWORD dwReturn;
+	PBYTE pbData = NULL;
+	DWORD dwCmdSize = 0, dwResponseSize;
+	BYTE pbCmd[6 + 256 + 256] = {0x00, 
+				    0x2A,
+					0x80,
+					0x86,
+					0x00,
+					};
+	POPENPGP_CONTEXT pContext;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
+		if (pInfo->bContainerIndex >= MaxContainer)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
+			__leave;
+		}
+		if (pInfo->bContainerIndex != Confidentiality)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
+			__leave;
+		}
+		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+		dwCmdSize = 5;
+		if (pContext->fExtentedLeLcFields)
+		{
+			pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) / 0x100);
+			pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
+		}
+		else
+		{
+			pbCmd[dwCmdSize++] = (BYTE)((pInfo->cbData +1) % 0x100);
+		}
+		pbCmd[dwCmdSize++] = 0;
+		memcpy(pbCmd + dwCmdSize, pInfo->pbData, pInfo->cbData);
+		dwCmdSize += pInfo->cbData;
+		if (pContext->fExtentedLeLcFields)
+		{
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength / 0x100);
+			pbCmd[dwCmdSize++] = (BYTE)(pContext->dwMaxLength % 0x100);
+		}
+		else
+		{
+			pbCmd[dwCmdSize++] = 0;
+		}
+		dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, &pbData, &dwResponseSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		if ( pInfo->cbData < dwResponseSize)
+		{
+			dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d expected = %d", pInfo->cbData, dwResponseSize);
+			__leave;
+		}
+		pInfo->cbData = dwResponseSize;
+		memcpy( pInfo->pbData, pbData, dwResponseSize);
+	}
+	__finally
+	{
+		if (pbData)
+			pCardData->pfnCspFree(pbData);
+	}
+	return dwReturn;
+}
+
+DWORD SCardAuthenticate(PCARD_DATA pCardData,
+							PCARD_SIGNING_INFO  pInfo)
+{
+	DWORD dwReturn;
+	PBYTE pbData = NULL;
+	DWORD dwSize = 0, dwI;
+	BYTE pbCmd[6 + 256 + 256] = {0x00, 
+				    0x88,
+					0x00,
+					0x00,
+					0x00,
+					};
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
+		if (pInfo->bContainerIndex >= MaxContainer)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
+			__leave;
+		}
+		if (pInfo->bContainerIndex != Authentication)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
+			__leave;
+		}
+		if (CARD_PADDING_PKCS1 & pInfo->dwPaddingType)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PKCS1");
+			__leave;
+		}
+		else if (CARD_PADDING_PSS & pInfo->dwPaddingType)
+		{
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			Trace(WINEVENT_LEVEL_ERROR, L"CARD_PADDING_PSS");
+			__leave;
+		}
+		for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
+		{
+			if (SignatureAlgorithm[dwI].aiHashAlg == pInfo->aiHashAlg)
+			{
+				// found
+				break;
+			}
+		}
+		if (dwI >= dwSignatureAlgorithmCount)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"alg not found %d", pInfo->aiHashAlg);
+			__leave;
+		}
+		if (SignatureAlgorithm[dwI].dwHashSize != pInfo->cbData)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"wrong hash size %d", pInfo->cbData);
+			__leave;
+		}
+		memcpy(pbCmd +5, SignatureAlgorithm[dwI].pbEncodedOid,SignatureAlgorithm[dwI].dwEncodedOidSize);
+		memcpy(pbCmd +5 + SignatureAlgorithm[dwI].dwEncodedOidSize, pInfo->pbData,pInfo->cbData);
+
+		dwReturn = SCardGetData(pCardData, pbCmd, ARRAYSIZE(pbCmd), &(pInfo->pbSignedData), &(pInfo->cbSignedData));
+		if (dwReturn)
+		{
+			__leave;
+		}
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD GetPinInfo(DWORD __in dwPinIndex, __inout PPIN_INFO pPinInfo)
+{
+	DWORD dwReturn=0;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwPinIndex=%d",dwPinIndex);
+		switch(dwPinIndex)
+		{
+		case ROLE_SIGNATURE:
+			pPinInfo->PinType = AlphaNumericPinType;
+			pPinInfo->PinPurpose = DigitalSignaturePin;
+			pPinInfo->dwChangePermission = PIN_CHANGE_FLAG_CHANGEPIN;
+			pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
+			pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
+			break;
+		case ROLE_AUTHENTICATION:
+			pPinInfo->PinType = AlphaNumericPinType;
+			pPinInfo->PinPurpose = AuthenticationPin;
+			pPinInfo->dwChangePermission = PIN_CHANGE_FLAG_CHANGEPIN;
+			pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
+			pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
+			break;
+		case ROLE_CONFIDENTIALITY:
+			pPinInfo->PinType = AlphaNumericPinType;
+			pPinInfo->PinPurpose = EncryptionPin;
+			pPinInfo->dwChangePermission = PIN_CHANGE_FLAG_CHANGEPIN;
+			pPinInfo->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
+			pPinInfo->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
+			break;
+		default:
+			Trace(WINEVENT_LEVEL_ERROR, L"dwPinIndex == %d", dwPinIndex);
+			dwReturn  = SCARD_E_INVALID_PARAMETER ;
+			__leave;
+		}
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriver/CryptoOperations.h
===================================================================
--- trunk/OpenPGPminidriver/CryptoOperations.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/CryptoOperations.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,59 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+typedef enum _OPENPGP_CONTAINER
+{
+	Signature,
+	Authentication,
+	Confidentiality,
+	MaxContainer
+} OPENPGP_CONTAINER;
+
+typedef struct _OPENPGP_CONTAINER_INFO
+{
+	BYTE Tag;
+	ALG_ID aiKeyAlg;
+	DWORD  dwKeySpec;
+	PIN_ID  PinId;
+} OPENPGP_CONTAINER_INFO, *POPENPGP_CONTAINER_INFO;
+
+extern OPENPGP_CONTAINER_INFO Containers[];
+
+#define OPENPGP_SUPPORTED_CYPHER_ALGORITHM L"\0"
+#define OPENPGP_SUPPORTED_ASYMETRIC_ALGORITHM L"RSA\0"
+
+DWORD SCardReadPublicKey(PCARD_DATA  pCardData, 
+						 OPENPGP_CONTAINER dwContainer, 
+						 PBYTE *pbPublicKey, PDWORD pdwPublicKeySize);
+
+DWORD SCardCreateKey(PCARD_DATA pCardData, OPENPGP_CONTAINER dwContainer, DWORD dwBitLen);
+
+DWORD SCardImportKey(PCARD_DATA pCardData, 
+					 OPENPGP_CONTAINER dwContainer,
+					 PBYTE pBlob,
+					 DWORD dwKeySize);
+
+DWORD SCardSign(PCARD_DATA  pCardData,
+				PCARD_SIGNING_INFO  pInfo);
+
+DWORD SCardDecrypt(PCARD_DATA  pCardData,
+				PCARD_RSA_DECRYPT_INFO  pInfo);
+
+DWORD SCardAuthenticate(PCARD_DATA  pCardData,
+							PCARD_SIGNING_INFO  pInfo);
+
+DWORD GetPinInfo(DWORD __in bContainerIndex, __inout PPIN_INFO pPinInfo);
\ No newline at end of file

Added: trunk/OpenPGPminidriver/DllMain.c
===================================================================
--- trunk/OpenPGPminidriver/DllMain.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/DllMain.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,40 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+
+
+/** This function provides handling for load/unload and attach/detach notifications
+to allow the DLL to manage its state and allocated resources. For more information,
+see “DllMain Callback Function” on MSDN®.
+
+return TRUE on DLL_PROCESS_ATTACH if initialization of the DLL was successful;
+otherwise, FALSE. Value ignored at other times by caller. */
+BOOL WINAPI DllMain(HINSTANCE    hinstDLL,
+                    DWORD        dwReason,
+                    LPVOID       lpReserved)
+{
+   // Perform actions based on the reason for calling.
+   if (dwReason == DLL_PROCESS_ATTACH)
+   {
+	   return TRUE;
+   }
+   else
+   {
+	   return FALSE;
+   }
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriver/OpenPGPminidriver.def
===================================================================
--- trunk/OpenPGPminidriver/OpenPGPminidriver.def	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/OpenPGPminidriver.def	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,6 @@
+LIBRARY
+
+EXPORTS
+CardAcquireContext
+EnableLogging
+DisableLogging
\ No newline at end of file

Added: trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj
===================================================================
--- trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,449 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9,00"
+	Name="OpenPGPminidriver"
+	ProjectGUID="{775DAB1D-5A49-4A57-B259-AD3DC833A75F}"
+	RootNamespace="OpenPGPminidriver"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OPENPGPMINIDRIVER_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\openpgpmdrv32.dll"
+				LinkIncremental="2"
+				ModuleDefinitionFile="OpenPGPminidriver.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OPENPGPMINIDRIVER_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\openpgpmdrv64.dll"
+				LinkIncremental="2"
+				ModuleDefinitionFile="OpenPGPminidriver.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OPENPGPMINIDRIVER_EXPORTS"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\openpgpmdrv32.dll"
+				LinkIncremental="1"
+				ModuleDefinitionFile="OpenPGPminidriver.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OPENPGPMINIDRIVER_EXPORTS"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\openpgpmdrv64.dll"
+				LinkIncremental="1"
+				ModuleDefinitionFile="OpenPGPminidriver.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="3) Microsoft Interface"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\CardAndContainerProperties.c"
+				>
+			</File>
+			<File
+				RelativePath=".\CardCryptographicOperations.c"
+				>
+			</File>
+			<File
+				RelativePath=".\CardInitializationAndDeconstruct.c"
+				>
+			</File>
+			<File
+				RelativePath=".\CardKeyContainer.c"
+				>
+			</File>
+			<File
+				RelativePath=".\CardPinOperation.c"
+				>
+			</File>
+			<File
+				RelativePath=".\CardPublicDataOperation.c"
+				>
+			</File>
+			<File
+				RelativePath=".\CardSecureKeyInjection.c"
+				>
+			</File>
+			<File
+				RelativePath=".\DllMain.c"
+				>
+			</File>
+			<File
+				RelativePath=".\Tracing.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Context.h"
+				>
+			</File>
+			<File
+				RelativePath=".\CryptoOperations.h"
+				>
+			</File>
+			<File
+				RelativePath=".\PinOperations.h"
+				>
+			</File>
+			<File
+				RelativePath=".\PublicDataOperations.h"
+				>
+			</File>
+			<File
+				RelativePath=".\SmartCard.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Tracing.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="1) Low level"
+			>
+			<File
+				RelativePath=".\SmartCard.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resources Files"
+			>
+			<File
+				RelativePath=".\driver.inf"
+				>
+			</File>
+			<File
+				RelativePath=".\OpenPGPminidriver.def"
+				>
+			</File>
+			<File
+				RelativePath=".\version.rc"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="2) Application"
+			>
+			<File
+				RelativePath=".\ContextManagement.c"
+				>
+			</File>
+			<File
+				RelativePath=".\CryptoOperations.c"
+				>
+			</File>
+			<File
+				RelativePath=".\PinOperations.c"
+				>
+			</File>
+			<File
+				RelativePath=".\PublicDataOperations.c"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\README.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

Added: trunk/OpenPGPminidriver/PinOperations.c
===================================================================
--- trunk/OpenPGPminidriver/PinOperations.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/PinOperations.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,321 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "SmartCard.h"
+#include "PublicDataOperations.h"
+#include "PinOperations.h"
+
+
+DWORD CheckPinLength(__in PCARD_DATA  pCardData, __in PIN_ID  PinId, __in DWORD  cbPin)
+{
+	DWORD dwReturn;
+	PBYTE pbResponse = NULL;
+	DWORD dwMinPinSize = 0, dwMaxPinSize;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
+		// check min Pin length
+		// (hard coded in specication)
+		switch(PinId)
+		{
+		case ROLE_SIGNATURE:
+		case ROLE_AUTHENTICATION:
+		case ROLE_CONFIDENTIALITY:
+			dwMinPinSize = 6;
+		case ROLE_PUK:
+			break;
+		case ROLE_ADMIN:
+			dwMinPinSize = 8;
+			break;
+		default:
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (cbPin < dwMinPinSize)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV ROLE = %d cbPin = %d minPinSize = %d",PinId, cbPin, dwMinPinSize);
+			dwReturn = SCARD_W_WRONG_CHV;
+			__leave;
+		}
+		// check in status DO
+		dwReturn = SCardReadFile(pCardData, szOpenPGPDir, szOpenPGPStatus, &pbResponse, NULL);
+		switch(PinId)
+		{
+		case ROLE_SIGNATURE:
+		case ROLE_AUTHENTICATION:
+		case ROLE_CONFIDENTIALITY:
+			dwMaxPinSize = pbResponse[1];
+			break;
+		case ROLE_PUK:
+			dwMaxPinSize = pbResponse[2];
+			break;
+		case ROLE_ADMIN:
+			dwMaxPinSize = pbResponse[3];
+			break;
+		default:
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		if (cbPin > dwMaxPinSize)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV ROLE = %d cbPin = %d dwMaxPinSize = %d", PinId, cbPin, dwMaxPinSize);
+			dwReturn = SCARD_W_WRONG_CHV;
+			__leave;
+		}
+		dwReturn = 0;
+	}
+	__finally
+	{
+		if (pbResponse)
+			pCardData->pfnCspFree(pbResponse);
+	}
+	return dwReturn;
+}
+
+DWORD GetRemainingPin(__in PCARD_DATA  pCardData, __in PIN_ID  PinId, __out PDWORD pdwCounter)
+{
+	DWORD dwReturn;
+	PBYTE pbResponse = NULL;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
+		dwReturn = SCardReadFile(pCardData, szOpenPGPDir, szOpenPGPStatus, &pbResponse, NULL);
+		switch(PinId)
+		{
+		case ROLE_SIGNATURE:
+		case ROLE_AUTHENTICATION:
+		case ROLE_CONFIDENTIALITY:
+			*pdwCounter = pbResponse[4];
+			break;
+		case ROLE_PUK:
+			*pdwCounter = pbResponse[5];
+			break;
+		case ROLE_ADMIN:
+			*pdwCounter = pbResponse[6];
+			break;
+		default:
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+	}
+	__finally
+	{
+		if (pbResponse)
+			pCardData->pfnCspFree(pbResponse);
+	}
+	return dwReturn;
+}
+
+DWORD VerifyPIN(__in PCARD_DATA  pCardData,__in PIN_ID  PinId, 
+				__in_bcount(cbPin) PBYTE  pbPin, __in DWORD  cbPin)
+{
+	DWORD dwReturn;
+	// 256 because the size of the PIN must fit in a Byte
+	BYTE pbCmd[256 + 5] = {0x00, 
+				    0x20,
+					0x00,
+					0x82,
+					0x00 
+					};
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
+		switch(PinId)
+		{
+		case ROLE_SIGNATURE:
+			pbCmd[3] = 0x81;
+			break;
+		case ROLE_AUTHENTICATION:
+		case ROLE_CONFIDENTIALITY:
+			pbCmd[3] = 0x82;
+			break;
+		case ROLE_ADMIN:
+			pbCmd[3] = 0x83;
+			break;
+		case ROLE_PUK:
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			__leave;
+		default:
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		pbCmd[4] = (BYTE) cbPin;
+		memcpy(pbCmd + 5, pbPin, cbPin);
+		dwReturn = SCardSendCommand(pCardData, pbCmd, 5 + cbPin);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		switch(PinId)
+		{
+			case ROLE_AUTHENTICATION:
+			case ROLE_CONFIDENTIALITY:
+				dwReturn = VerifyPIN(pCardData, ROLE_SIGNATURE, pbPin, cbPin);
+				break;
+		}
+			
+	}
+	__finally
+	{
+		SecureZeroMemory(pbCmd, ARRAYSIZE(pbCmd));
+	}
+	
+	return dwReturn;
+}
+
+DWORD ChangePIN(__in PCARD_DATA  pCardData, __in PIN_ID  PinId,
+				__in_bcount(cbPin) PBYTE  pbOldPin, __in DWORD  cbOldPin,
+				__in_bcount(cbPin) PBYTE  pbNewPin, __in DWORD  cbNewPin
+				)
+{
+	DWORD dwReturn;
+	// 256 because the size of the PIN must fit in a Byte
+	BYTE pbCmd[256 + 256 + 6] = {0x00, 
+				    0x24,
+					0x00,
+					0x81,
+					0x00 
+					};
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
+		dwReturn = CheckPinLength(pCardData, PinId, cbOldPin);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		switch(PinId)
+		{
+		case ROLE_SIGNATURE:
+		case ROLE_AUTHENTICATION:
+		case ROLE_CONFIDENTIALITY:
+			pbCmd[3] = 0x81;
+			break;
+		case ROLE_ADMIN:
+			pbCmd[3] = 0x83;
+			break;
+		case ROLE_PUK:
+			dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+			__leave;
+		default:
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		pbCmd[4] = (BYTE) (cbOldPin + cbNewPin);
+		memcpy(pbCmd + 5, pbOldPin, cbOldPin);
+		memcpy(pbCmd + 5 + cbOldPin, pbNewPin, cbNewPin);
+		dwReturn = SCardSendCommand(pCardData, pbCmd, 5 + cbOldPin + cbNewPin);
+	}
+	__finally
+	{
+		SecureZeroMemory(pbCmd, ARRAYSIZE(pbCmd));
+	}
+	return dwReturn;
+}
+
+/** only the user PIN can be reseted => target is implicit*/
+DWORD ResetUserPIN(__in PCARD_DATA  pCardData,  __in PIN_ID  PinId,
+				__in_bcount(cbPin) PBYTE  pbAuthenticator, __in DWORD  cbAuthenticator,
+				__in_bcount(cbPin) PBYTE  pbNewPin, __in DWORD  cbNewPin
+				)
+{
+	DWORD dwReturn;
+	BYTE pbCmd[256 + 5] = {0x00, 
+				    0x2C,
+					0x02,
+					0x81,
+					0x00 
+					};
+	DWORD dwCmdSize;
+	
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter PinId=%d",PinId);
+		switch(PinId)
+		{
+		case ROLE_ADMIN:
+			// authenticate the admin
+			dwReturn = VerifyPIN(pCardData, PinId, pbAuthenticator, cbAuthenticator);
+			if (!dwReturn)
+			{
+				return dwReturn;
+			}
+			pbCmd[4] = (BYTE) cbAuthenticator;
+			memcpy(pbCmd + 5, pbNewPin, cbNewPin);
+			dwCmdSize = 5 + cbNewPin;
+			break;
+		case ROLE_PUK:
+			dwReturn = CheckPinLength(pCardData, PinId, cbAuthenticator);
+			if (dwReturn)
+			{
+				__leave;
+			}
+			pbCmd[2] = 0x00;
+			pbCmd[4] = (BYTE) (cbAuthenticator + cbNewPin);
+			memcpy(pbCmd + 5, pbAuthenticator, cbAuthenticator);
+			memcpy(pbCmd + 5 + cbAuthenticator, pbNewPin, cbNewPin);
+			dwCmdSize = 5 + cbNewPin + cbAuthenticator;
+			break;
+		default:
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwReturn = SCardSendCommand(pCardData, pbCmd, dwCmdSize);
+	}
+	__finally
+	{
+		SecureZeroMemory(pbCmd, ARRAYSIZE(pbCmd));
+	}
+	return dwReturn;
+}
+
+DWORD Deauthenticate(__in PCARD_DATA  pCardData)
+{
+	DWORD     dwAP;
+	DWORD dwReturn;
+	__try
+	{
+		// reset the card
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter");
+		dwReturn = SCardReconnect(pCardData->hScard,
+                         SCARD_SHARE_SHARED,
+                         SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
+                         SCARD_LEAVE_CARD,
+                         &dwAP );
+		if (dwReturn)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCardControl 0x%08X", dwReturn);
+			__leave;
+		}
+		// regain the ownership of a transaction
+		dwReturn = SCardBeginTransaction(pCardData->hScard);
+		if (dwReturn)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCardBeginTransaction 0x%08X", dwReturn);
+			__leave;
+		}
+		dwReturn = SelectOpenPGPApplication(pCardData);
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriver/PinOperations.h
===================================================================
--- trunk/OpenPGPminidriver/PinOperations.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/PinOperations.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,37 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#define ROLE_SIGNATURE ROLE_USER
+#define ROLE_AUTHENTICATION 3
+#define ROLE_CONFIDENTIALITY 4
+#define ROLE_PUK 5
+
+DWORD CheckPinLength(__in PCARD_DATA  pCardData, __in PIN_ID  PinId, __in DWORD  cbPin);
+DWORD GetRemainingPin(__in PCARD_DATA  pCardData, __in PIN_ID  PinId, __out PDWORD pdwCounter);
+DWORD VerifyPIN(__in PCARD_DATA  pCardData,__in PIN_ID  PinId, 
+				__in_bcount(cbPin) PBYTE  pbPin, __in DWORD  cbPin)
+;
+DWORD ChangePIN(__in PCARD_DATA  pCardData, __in PIN_ID  PinId,
+				__in_bcount(cbPin) PBYTE  pbOldPin, __in DWORD  cbOldPin,
+				__in_bcount(cbPin) PBYTE  pbNewPin, __in DWORD  cbNewPin
+				);
+DWORD ResetUserPIN(__in PCARD_DATA  pCardData,  __in PIN_ID  PinId,
+				__in_bcount(cbPin) PBYTE  pbAuthenticator, __in DWORD  cbAuthenticator,
+				__in_bcount(cbPin) PBYTE  pbNewPin, __in DWORD  cbNewPin
+				);
+DWORD Deauthenticate(__in PCARD_DATA  pCardData);
\ No newline at end of file

Added: trunk/OpenPGPminidriver/PublicDataOperations.c
===================================================================
--- trunk/OpenPGPminidriver/PublicDataOperations.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/PublicDataOperations.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,491 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <cardmod.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "SmartCard.h"
+#include "PublicDataOperations.h"
+#include "CryptoOperations.h"
+
+typedef enum _OPENPGP_FILE_TYPE
+{
+	StoredOnSmartCard,
+	Virtual,
+} OPENPGP_FILE_TYPE;
+
+typedef struct _OPENPGP_FILE
+{
+	PCHAR szDirectory;
+	PCHAR szFile;
+	OPENPGP_FILE_TYPE dwFileType;
+	BYTE  bP1;
+	BYTE  bP2;
+	CARD_FILE_ACCESS_CONDITION dwAccess;
+} OPENPGP_FILE, *POPENPGP_FILE;
+
+
+#define szCARD_APPLICATION_FILE "cardapps"
+
+OPENPGP_FILE Files[] =
+{
+	{szOpenPGPDir, szOpenPGPFingerprint, StoredOnSmartCard, 0x00, 0xC5, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPStatus, StoredOnSmartCard, 0x00, 0xC4, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPApplicationIdentifier, StoredOnSmartCard, 0x00, 0x4F, UnknownAc},
+	{szOpenPGPDir, szOpenPGPLogin, StoredOnSmartCard, 0x00, 0x5E, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPName, StoredOnSmartCard, 0x00, 0x5B, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPLanguage, StoredOnSmartCard, 0x5F, 0x2D, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPSex, StoredOnSmartCard, 0x5F, 0x35, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPUrl, StoredOnSmartCard, 0x5F, 0x50, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPHistoricalBytes, StoredOnSmartCard, 0x5F, 0x52, UnknownAc},
+	{szOpenPGPDir, szOpenPGPCertificate, StoredOnSmartCard, 0x7F, 0x21, EveryoneReadAdminWriteAc},
+	{szOpenPGPDir, szOpenPGPExtendedCap, StoredOnSmartCard, 0x00, 0xC0, UnknownAc},
+	{szOpenPGPDir, szOpenPGPAlgoAttributesSignature, StoredOnSmartCard, 0x00, 0xC1, UnknownAc},
+	{szOpenPGPDir, szOpenPGPAlgoAttributesDecryption, StoredOnSmartCard, 0x00, 0xC2, UnknownAc},
+	{szOpenPGPDir, szOpenPGPAlgoAttributesAuthentication, StoredOnSmartCard, 0x00, 0xC3, UnknownAc },
+	{NULL, szCARD_IDENTIFIER_FILE, StoredOnSmartCard, 0x00, 0x4F, EveryoneReadAdminWriteAc},
+	{NULL, szCARD_APPLICATION_FILE, Virtual, 0, 0, EveryoneReadAdminWriteAc},
+	{NULL, szCACHE_FILE, Virtual, 0, 0, EveryoneReadUserWriteAc},
+	{szBASE_CSP_DIR, szCONTAINER_MAP_FILE, Virtual, 0, 0, EveryoneReadUserWriteAc},
+
+};
+
+DWORD dwFileCount = ARRAYSIZE(Files);
+
+DWORD SCardDirectoryList(__in PCARD_DATA  pCardData, 
+					__in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)
+{
+	// hardcoded
+	*pdwResponseSize = 16;
+	*pbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
+	if (!*pbResponse)
+	{
+		return SCARD_E_NO_MEMORY;
+	}
+	memcpy(*pbResponse, "openpgp\0mscp\0\0\0\0", *pdwResponseSize);
+	return 0;
+}
+
+// read file
+DWORD SCardReadFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile,
+					__in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)
+{
+	DWORD dwI;
+	DWORD dwReturn = 0;
+	BOOL fDirectoryFound = FALSE;
+	BOOL fFileFound = FALSE;
+	BYTE pbCmd[] = {0x00, 0xCA, 0x00, 0x00, 0x00};
+	DWORD dwCmdSize = ARRAYSIZE(pbCmd);
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+	__try
+	{
+		for(dwI = 0; dwI < dwFileCount; dwI++)
+		{
+			BOOL fMatch = FALSE;
+			if (szDirectory == NULL)
+			{
+				if (!Files[dwI].szDirectory) fMatch = TRUE;
+			}
+			else
+			{
+				if (Files[dwI].szDirectory && strcmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
+			}
+			if (fMatch)
+			{
+				fDirectoryFound = TRUE;
+				if (strcmp(szFile, Files[dwI].szFile) == 0)
+				{
+					fFileFound = TRUE;
+					break;
+				}
+			}
+		}
+		if (!fFileFound)
+		{
+			if (fDirectoryFound)
+			{
+				dwReturn = SCARD_E_FILE_NOT_FOUND;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
+			}
+			else
+			{
+				dwReturn = SCARD_E_DIR_NOT_FOUND;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szDirectory);
+			}	
+			__leave;
+		}
+		if (Files[dwI].dwFileType == StoredOnSmartCard)
+		{
+			pbCmd[2] = Files[dwI].bP1;
+			pbCmd[3] = Files[dwI].bP2;
+			dwReturn = SCardGetData(pCardData, pbCmd, dwCmdSize, pbResponse, pdwResponseSize);
+		}
+		else
+		{
+			if (szDirectory == NULL)
+			{
+				if (strcmp(szFile, szCARD_APPLICATION_FILE) == 0)
+				{
+					dwReturn = SCardDirectoryList(pCardData, pbResponse, pdwResponseSize);
+				}
+				else if (strcmp(szFile, szCACHE_FILE) == 0)
+				{
+					*pdwResponseSize = sizeof(CARD_CACHE_FILE_FORMAT);
+					*pbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
+					memset(*pbResponse,0,*pdwResponseSize);
+				}
+				else
+				{
+					dwReturn = SCARD_E_FILE_NOT_FOUND;
+					Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
+				}
+			}
+			else if (strcmp(szDirectory,szBASE_CSP_DIR) == 0)
+			{
+				if (strcmp(szFile, szCONTAINER_MAP_FILE) == 0)
+				{
+					PCONTAINER_MAP_RECORD pContainer = NULL;
+					*pdwResponseSize = sizeof(CONTAINER_MAP_RECORD) * MaxContainer;
+					*pbResponse = pCardData->pfnCspAlloc(*pdwResponseSize);
+					if (! *pbResponse )
+					{
+						dwReturn = SCARD_E_NO_MEMORY;
+						Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
+						__leave;
+					}
+					pContainer = (PCONTAINER_MAP_RECORD) *pbResponse;
+					memset(pContainer,0,sizeof(CONTAINER_MAP_RECORD) * 3);
+					swprintf_s(pContainer[Signature].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
+						L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Signature",
+						pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
+						pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
+						pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
+						pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
+					pContainer[Signature].bFlags = CONTAINER_MAP_VALID_CONTAINER;
+					pContainer[Signature].wSigKeySizeBits = 1024;
+					swprintf_s(pContainer[Authentication].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
+						L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Authenticate",
+						pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
+						pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
+						pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
+						pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
+					pContainer[Authentication].bFlags = CONTAINER_MAP_VALID_CONTAINER | CONTAINER_MAP_DEFAULT_CONTAINER;
+					pContainer[Authentication].wSigKeySizeBits = 1024;
+					swprintf_s(pContainer[Confidentiality].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
+						L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Confidential",
+						pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
+						pContext->Aid.AidManufacturer[0],pContext->Aid.AidManufacturer[1],
+						pContext->Aid.AidSerialNumber[0],pContext->Aid.AidSerialNumber[1],
+						pContext->Aid.AidSerialNumber[2],pContext->Aid.AidSerialNumber[3]);
+					pContainer[Confidentiality].bFlags = CONTAINER_MAP_VALID_CONTAINER;
+					pContainer[Confidentiality].wKeyExchangeKeySizeBits = 1024;
+				}
+				else
+				{
+					dwReturn = SCARD_E_FILE_NOT_FOUND;
+					Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
+				}
+			}
+			else
+			{
+				dwReturn = SCARD_E_DIR_NOT_FOUND;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szDirectory);
+			}
+		}
+		if (dwReturn)
+		{
+			__leave;
+		}
+		// add to the cache
+		dwReturn = 0;
+
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"%S\\%S dwReturn = 0x%08X",szDirectory, szFile, dwReturn);
+	return dwReturn;
+}
+
+DWORD SCardEnumFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory,
+					__in PBYTE* pbResponse, __in PDWORD pdwResponseSize)
+{
+	DWORD dwReturn = 0, dwNotExists;
+	DWORD dwI, dwSize;
+	BOOL fDirectoryFound = FALSE;
+
+	__try
+	{
+		*pbResponse = NULL;
+		*pdwResponseSize = 0;
+		for(dwI = 0; dwI < dwFileCount; dwI++)
+		{
+			BOOL fMatch = FALSE;
+			if (szDirectory == NULL)
+			{
+				if (!Files[dwI].szDirectory) fMatch = TRUE;
+			}
+			else
+			{
+				if (Files[dwI].szDirectory && strcmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
+			}
+			if (fMatch)
+			{
+				fDirectoryFound = TRUE;
+				dwNotExists = 0;
+				if (StoredOnSmartCard == Files[dwI].dwFileType)
+				{
+					PBYTE pbData = NULL;
+					DWORD dwSize;
+					// check if the file exists and be read
+					dwNotExists = SCardReadFile(pCardData, szDirectory, Files[dwI].szFile, &pbData, &dwSize);
+					if (!dwNotExists)
+					{
+						pCardData->pfnCspFree(pbData);
+					}
+				}
+				if (!dwNotExists)
+				{
+					dwSize = (DWORD) strlen( Files[dwI].szFile) + 1;
+					// + 1 to add the final \0
+					if (*pbResponse)
+					{
+						*pbResponse = pCardData->pfnCspReAlloc(*pbResponse, *pdwResponseSize + dwSize + 1);
+					}
+					else
+					{
+						*pbResponse = pCardData->pfnCspAlloc(*pdwResponseSize + dwSize + 1);
+					}
+					if (!*pbResponse)
+					{
+						dwReturn = SCARD_E_NO_MEMORY;
+						__leave;
+					}
+					memcpy(*pbResponse + *pdwResponseSize,  Files[dwI].szFile, dwSize);
+					*pdwResponseSize += dwSize;
+				}
+			}
+		}
+		if (!fDirectoryFound)
+		{
+			dwReturn = SCARD_E_DIR_NOT_FOUND;
+			__leave;
+		}
+		(*pbResponse)[*pdwResponseSize] = '\0';
+		*pdwResponseSize += 1;
+		dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+// read file
+DWORD SCardGetFileInfo(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile,
+					 __inout PCARD_FILE_INFO  pCardFileInfo)
+{
+	DWORD dwReturn = 0;
+	PBYTE pbData = NULL;
+	DWORD dwSize, dwI;
+	__try
+	{
+		dwReturn = SCardReadFile(pCardData, szDirectory, szFile, &pbData, &dwSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		pCardData->pfnCspFree(pbData);
+		pCardFileInfo->cbFileSize = dwSize;
+		pCardFileInfo->AccessCondition = InvalidAc;
+		for(dwI = 0; dwI < dwFileCount; dwI++)
+		{
+			if ((strcmp(szDirectory, Files[dwI].szDirectory) == 0)
+				|| (!szDirectory && !Files[dwI].szDirectory) )
+			{
+				if (strcmp(szFile, Files[dwI].szFile) == 0)
+				{
+					pCardFileInfo->AccessCondition = Files[dwI].dwAccess;
+					break;
+				}
+			}
+		}
+		dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;	
+}
+
+DWORD SCardWriteFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile,
+					__in PBYTE pbData, __in DWORD dwSize)
+{
+	DWORD dwI;
+	DWORD dwReturn = 0;
+	BOOL fDirectoryFound = FALSE;
+	BOOL fFileFound = FALSE;
+	BYTE pbCmd[5 + 256] = {0x00, 0xDA, 0x00, 0x00, 0x00};
+	DWORD dwCmdSize = 0;
+	__try
+	{
+		if (dwSize > 255)
+		{
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			Trace(WINEVENT_LEVEL_ERROR, L"dwSize %d",dwSize);
+			__leave;
+		}
+
+
+		for(dwI = 0; dwI < dwFileCount; dwI++)
+		{
+			BOOL fMatch = FALSE;
+			if (szDirectory == NULL)
+			{
+				if (!Files[dwI].szDirectory) fMatch = TRUE;
+			}
+			else
+			{
+				if (Files[dwI].szDirectory && strcmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
+			}
+			if (fMatch)
+			{
+				fDirectoryFound = TRUE;
+				if (strcmp(szFile, Files[dwI].szFile) == 0)
+				{
+					fFileFound = TRUE;
+					break;
+				}
+			}
+		}
+		if (!fFileFound)
+		{
+			if (fDirectoryFound)
+			{
+				dwReturn = SCARD_E_FILE_NOT_FOUND;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND %S",szFile);
+			}
+			else
+			{
+				dwReturn = SCARD_E_DIR_NOT_FOUND;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szDirectory);
+			}	
+			__leave;
+		}
+		if (Files[dwI].dwFileType == StoredOnSmartCard)
+		{
+			// fail because the PUT DO doesn't work => too much data
+			if (Files[dwI].bP1 != 0)
+			{
+				dwReturn = SCARD_E_WRITE_TOO_MANY ;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_WRITE_TOO_MANY  %S",szFile);
+				__leave;
+			}
+			pbCmd[3] = Files[dwI].bP2;
+			pbCmd[4] = (BYTE) dwSize;
+			if (dwSize)
+			{
+				memcpy(pbCmd + 5, pbData, dwSize);
+			}
+			dwCmdSize = dwSize + 5;
+			dwReturn = SCardSendCommand(pCardData, pbCmd, dwCmdSize);
+			if (dwReturn)
+			{
+				__leave;
+			}
+		}
+		else
+		{
+			dwReturn = SCARD_W_SECURITY_VIOLATION;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION %S",szFile);
+			__leave;
+		}
+
+		
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+DWORD SCardDeleteFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile)
+{
+	return SCardWriteFile(pCardData, szDirectory, szFile, NULL, 0);
+}
+
+// just change the flag in Files
+DWORD SCardCreateFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile)
+{
+	DWORD dwI;
+	DWORD dwReturn = 0;
+	BOOL fDirectoryFound = FALSE;
+	BOOL fFileFound = FALSE;
+	__try
+	{
+		for(dwI = 0; dwI < dwFileCount; dwI++)
+		{
+			BOOL fMatch = FALSE;
+			if (szDirectory == NULL)
+			{
+				if (!Files[dwI].szDirectory) fMatch = TRUE;
+			}
+			else
+			{
+				if (Files[dwI].szDirectory && strcmp(szDirectory, Files[dwI].szDirectory) == 0) fMatch = TRUE;
+			}
+			if (fMatch)
+			{
+				fDirectoryFound = TRUE;
+				if (strcmp(szFile, Files[dwI].szFile) == 0)
+				{
+					fFileFound = TRUE;
+					break;
+				}
+			}
+		}
+		if (!fDirectoryFound)
+		{
+			dwReturn = SCARD_E_DIR_NOT_FOUND;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_DIR_NOT_FOUND %S",szFile);
+			__leave;
+		}
+		if (!fFileFound)
+		{
+			dwReturn = SCARD_W_SECURITY_VIOLATION;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION %S",szFile);
+			__leave;
+		}
+		
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}

Added: trunk/OpenPGPminidriver/PublicDataOperations.h
===================================================================
--- trunk/OpenPGPminidriver/PublicDataOperations.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/PublicDataOperations.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,56 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// max len = 8 bytes
+#define szOpenPGPDir "openpgp"
+#define szOpenPGPFingerprint "fingerpr"
+#define szOpenPGPStatus "status"
+#define szOpenPGPApplicationIdentifier "aid"
+#define szOpenPGPLogin "logindat"
+#define szOpenPGPName "name"
+#define szOpenPGPLanguage "language"
+#define szOpenPGPSex "sex"
+#define szOpenPGPUrl "url"
+#define szOpenPGPHistoricalBytes "histo"
+#define szOpenPGPCertificate "certific"
+#define szOpenPGPExtendedCap "extcapab"
+#define szOpenPGPAlgoAttributesSignature "algsign"
+#define szOpenPGPAlgoAttributesDecryption "algcryp"
+#define szOpenPGPAlgoAttributesAuthentication "algauth"
+
+
+DWORD SCardReadFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR file,
+					__in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize);
+
+DWORD SCardEnumFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory,
+					__in PBYTE* pbResponse, __in PDWORD pdwResponseSize);
+
+DWORD SCardGetFileInfo(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile,
+					 __inout PCARD_FILE_INFO  pCardFileInfo);
+
+DWORD SCardWriteFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile,
+					__in PBYTE pbData, __in DWORD dwSize);
+
+DWORD SCardDeleteFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile);
+
+DWORD SCardCreateFile(__in PCARD_DATA  pCardData, 
+					__in_opt PSTR szDirectory, __in PSTR szFile);
\ No newline at end of file

Added: trunk/OpenPGPminidriver/README.txt
===================================================================
--- trunk/OpenPGPminidriver/README.txt	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/README.txt	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,21 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+Testing
+http://msdn.microsoft.com/en-us/library/dd327365.aspx
+
+cmck.exe is included in the "Windows Driver Kit (WDK)"
\ No newline at end of file

Added: trunk/OpenPGPminidriver/SmartCard.c
===================================================================
--- trunk/OpenPGPminidriver/SmartCard.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/SmartCard.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,272 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <cardmod.h>
+#include <stdio.h>
+#include "Tracing.h"
+#include "Context.h"
+#include "SmartCard.h"
+
+#pragma comment(lib,"Winscard")
+
+
+DWORD SCardSendCommand(__in PCARD_DATA  pCardData, __in PBYTE pbCmd, __in DWORD dwCmdSize)
+{
+	DWORD             dwReturn = 0;
+
+	SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
+	SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
+	BYTE     recvbuf[256];
+	DWORD     recvlen = sizeof(recvbuf);
+	BYTE              SW1, SW2;
+	__try
+	{
+
+		dwReturn = SCardTransmit(pCardData->hScard, 
+									SCARD_PCI_T1, 
+									pbCmd, 
+									dwCmdSize, 
+									NULL, 
+									recvbuf, 
+									&recvlen);
+		if ( dwReturn != SCARD_S_SUCCESS )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
+			__leave;
+		}
+		SW1 = recvbuf[recvlen-2];
+		SW2 = recvbuf[recvlen-1];
+		if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
+		{
+
+		}
+		else if ( (SW1 == 0x69) && (SW2 == 0x82) )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV");
+			dwReturn = SCARD_W_WRONG_CHV;
+			__leave;
+		}
+		else if ( (SW1 == 0x69) && (SW2 == 0x83) )
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_CHV_BLOCKED");
+			dwReturn = SCARD_W_CHV_BLOCKED;
+			__leave;
+		}
+		else
+		{
+			TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
+			Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
+			dwReturn = SCARD_F_UNKNOWN_ERROR;
+			__leave;
+		}
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD SelectOpenPGPApplication(__in PCARD_DATA  pCardData)
+{
+	BYTE pbCmd[] = {0x00, 
+				    0xA4,
+					0x04,
+					0x00,
+					0x06,
+					0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
+					0x00
+					};
+	
+	return SCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
+}
+
+
+DWORD SCardGetData(__in PCARD_DATA  pCardData, 
+					__in PBYTE pbCmd, __in DWORD dwCmdSize,
+					__in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)
+{
+
+	DWORD dwReturn;
+	BYTE pbGetResponse[] = {0x00, 
+				    0xC0,
+					0x00,
+					0x00,
+					0x00
+					};
+	DWORD dwGetResponseSize = ARRAYSIZE(pbGetResponse);
+	BYTE			recvbuf[0x800];
+	DWORD			recvlen = sizeof(recvbuf);
+	BYTE            SW1, SW2;
+	DWORD			dwDataSize = 0;
+	__try
+	{
+
+		*pbResponse = NULL;
+		dwReturn = SCardTransmit(pCardData->hScard, 
+									SCARD_PCI_T1, 
+									pbCmd, 
+									dwCmdSize, 
+									NULL, 
+									recvbuf, 
+									&recvlen);
+		
+		do
+		{
+			if ( dwReturn != SCARD_S_SUCCESS )
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"SCardTransmit errorcode: [0x%02X]", dwReturn);
+				__leave;
+			}
+			SW1 = recvbuf[recvlen-2];
+			SW2 = recvbuf[recvlen-1];
+			if ( ( SW1 == 0x90 ) && ( SW2 == 0x00 ) )
+			{
+				dwDataSize = recvlen-2;
+				*pbResponse = pCardData->pfnCspAlloc(dwDataSize);
+				memcpy(*pbResponse, recvbuf, dwDataSize);
+			}
+			else if (SW1 == 0x61)
+			{
+				dwDataSize += SW2;
+				if (*pbResponse)
+				{
+					*pbResponse = pCardData->pfnCspReAlloc(*pbResponse, dwDataSize);
+				}
+				else
+				{
+					*pbResponse = pCardData->pfnCspAlloc(dwDataSize);
+				}
+				dwGetResponseSize = ARRAYSIZE(pbGetResponse);
+				dwReturn = SCardTransmit(pCardData->hScard, 
+									SCARD_PCI_T1, 
+									pbGetResponse, 
+									dwGetResponseSize, 
+									NULL, 
+									recvbuf, 
+									&recvlen);
+			}
+			else if ( (SW1 == 0x69) && (SW2 == 0x82) )
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_WRONG_CHV");
+				dwReturn = SCARD_W_WRONG_CHV;
+				__leave;
+			}
+			else if ( (SW1 == 0x69) && (SW2 == 0x83) )
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_CHV_BLOCKED");
+				dwReturn = SCARD_W_CHV_BLOCKED;
+				__leave;
+			}
+			else if ( (SW1 == 0x6A) && (SW2 == 0x88) )
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_FILE_NOT_FOUND");
+				dwReturn = SCARD_E_FILE_NOT_FOUND;
+				__leave;
+			}
+			else if ( (SW1 == 0x69) && (SW2 == 0x85) )
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_W_SECURITY_VIOLATION");
+				dwReturn = SCARD_W_SECURITY_VIOLATION;
+				__leave;
+			}
+			else
+			{
+				TraceDump(WINEVENT_LEVEL_ERROR, pbCmd,dwCmdSize);
+				Trace(WINEVENT_LEVEL_ERROR, L"SW1=0x%02X SW2=0x%02X", SW1, SW2);
+				dwReturn = SCARD_F_UNKNOWN_ERROR;
+				__leave;
+			}
+
+		} while (SW1 == 0x61);
+		if (pdwResponseSize)
+		{
+			*pdwResponseSize = dwDataSize;
+		}
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD CCIDfindFeature(BYTE featureTag, BYTE* features, DWORD featuresLength) 
+{
+    DWORD idx = 0;
+    int count;
+    while (idx < featuresLength) {
+        BYTE tag = features[idx];
+        idx++;
+        idx++;
+        if (featureTag == tag) {
+            DWORD feature = 0;
+            for (count = 0; count < 3; count++) {
+                feature |= features[idx] & 0xff;
+                idx++;
+                feature <<= 8;
+            }
+            feature |= features[idx] & 0xff;
+            return feature;
+        }
+        idx += 4;
+    }
+    return 0;
+}
+
+DWORD CCIDgetFeatures(__in PCARD_DATA  pCardData) 
+{
+	BYTE pbRecvBuffer[200];
+	DWORD dwRecvLength, dwReturn;
+	__try
+	{
+		POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+
+		pContext->SmartCardReaderFeatures.VERIFY_PIN_START = 0;
+		pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = 0;
+		pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = 0;
+		pContext->SmartCardReaderFeatures.MODIFY_PIN_START = 0;
+		pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = 0;
+		pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = 0;
+		pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = 0;
+		pContext->SmartCardReaderFeatures.ABORT = 0;
+
+		dwReturn = SCardControl(pCardData->hScard, 
+			SCARD_CTL_CODE(3400),
+			NULL,
+			0,
+			pbRecvBuffer,
+			sizeof(pbRecvBuffer),
+			&dwRecvLength);
+		if ( dwReturn ) 
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"SCardControl errorcode: [0x%02X]", dwReturn);
+			__leave;
+		}
+		pContext->SmartCardReaderFeatures.VERIFY_PIN_START = CCIDfindFeature(FEATURE_VERIFY_PIN_START, pbRecvBuffer, dwRecvLength);
+		pContext->SmartCardReaderFeatures.VERIFY_PIN_FINISH = CCIDfindFeature(FEATURE_VERIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
+		pContext->SmartCardReaderFeatures.VERIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_VERIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
+		pContext->SmartCardReaderFeatures.MODIFY_PIN_START = CCIDfindFeature(FEATURE_MODIFY_PIN_START, pbRecvBuffer, dwRecvLength);
+		pContext->SmartCardReaderFeatures.MODIFY_PIN_FINISH = CCIDfindFeature(FEATURE_MODIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
+		pContext->SmartCardReaderFeatures.MODIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_MODIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
+		pContext->SmartCardReaderFeatures.GET_KEY_PRESSED = CCIDfindFeature(FEATURE_GET_KEY_PRESSED, pbRecvBuffer, dwRecvLength);
+		pContext->SmartCardReaderFeatures.ABORT = CCIDfindFeature(FEATURE_ABORT, pbRecvBuffer, dwRecvLength);
+	}
+	__finally
+	{
+	}
+   return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriver/SmartCard.h
===================================================================
--- trunk/OpenPGPminidriver/SmartCard.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/SmartCard.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,25 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+DWORD SCardSendCommand(__in PCARD_DATA  pCardData, __in PBYTE pbCmd, __in DWORD dwCmdSize);
+DWORD SelectOpenPGPApplication(__in PCARD_DATA  pCardData);
+
+DWORD SCardGetData(__in PCARD_DATA  pCardData, 
+					__in PBYTE pbCmd, __in DWORD dwCmdSize,
+					__in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize);
+
+DWORD CCIDgetFeatures(__in PCARD_DATA  pCardData) ;
\ No newline at end of file

Added: trunk/OpenPGPminidriver/SmartCardOperations.c
===================================================================
--- trunk/OpenPGPminidriver/SmartCardOperations.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/SmartCardOperations.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,3 @@
+
+#include "SmartCardOperations.h"
+

Added: trunk/OpenPGPminidriver/Tracing.c
===================================================================
--- trunk/OpenPGPminidriver/Tracing.c	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/Tracing.c	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,290 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <Evntprov.h>
+#include <initguid.h>
+#include <Wmistr.h>
+#include <Evntrace.h>
+#include <cardmod.h>
+#include "Tracing.h"
+
+#define MessageBoxWin32(status) MessageBoxWin32Ex (status, __FILE__,__LINE__);
+
+// to enable tracing in kernel debugger, issue the following command in windbg : ed nt!Kd_DEFAULT_MASK  0xFFFFFFFF
+// OR
+// Open up the registry and go to this path,
+// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter 
+// and add the following value "DEFAULT" : REG_DWORD : 0xFFFFFFFF and then reboot
+
+// {081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}
+DEFINE_GUID(TracingGuid, 
+0x81cce5f, 0x5f9c, 0x4b43, 0x9a, 0x15, 0x1d, 0xcf, 0x5d, 0x2d, 0x45, 0xf5);
+
+REGHANDLE hPub = 0;
+
+void TracingRegister() {
+	EventRegister(&TracingGuid,NULL,NULL,&hPub);
+}
+
+void TracingUnRegister() {
+	EventUnregister(hPub);
+}
+
+
+void TraceEx(LPCSTR szFile, DWORD dwLine, LPCSTR szFunction, UCHAR dwLevel, PCWSTR szFormat,...) {
+#ifndef _DEBUG
+	UNREFERENCED_PARAMETER(dwLine);
+	UNREFERENCED_PARAMETER(szFile);
+#endif
+	WCHAR Buffer[256];
+	WCHAR Buffer2[356];
+	int ret;
+	va_list ap;
+
+	if (!hPub) TracingRegister();
+
+	va_start (ap, szFormat);
+	ret = _vsnwprintf_s (Buffer, 256, 256, szFormat, ap);
+	va_end (ap);
+	if (ret <= 0) return;
+	if (ret > 256) ret = 255;
+	Buffer[255] = L'\0';
+#ifdef _DEBUG
+	swprintf_s(Buffer2,356,L"%S(%d) : %S - %s\r\n",szFile,dwLine,szFunction,Buffer);
+	OutputDebugString(Buffer2);
+#endif
+	swprintf_s(Buffer2,356,L"%S(%d) : %s",szFunction,dwLine,Buffer);
+	EventWriteString(hPub,dwLevel,0,Buffer2);
+
+}
+
+void TraceDumpEx(LPCSTR szFile, DWORD dwLine, LPCSTR szFunction, UCHAR dwLevel,
+			  __in PBYTE pbCmd, __in DWORD dwCmdSize)
+{
+	WCHAR szData[10 * 3 + 1];
+	DWORD dwI;
+	PWSTR szPointer = szData;
+	for(dwI = 0; dwI < dwCmdSize; dwI++)
+	{
+		if (dwI%10 == 0 && dwI != 0)
+		{
+			TraceEx(szFile,dwLine,szFunction,dwLevel,L"DUMP : %s",szData);
+			szPointer = szData;
+		}
+		swprintf_s(szPointer + 3 * (dwI%10),4,L"%02X ",pbCmd[dwI]);
+		
+	}
+	TraceEx(szFile,dwLine,szFunction,dwLevel,L"DUMP : %s",szData);
+}
+
+/**
+ *  Display a messagebox giving an error code
+ */
+void MessageBoxWin32Ex(DWORD status, LPCSTR szFile, DWORD dwLine) {
+	LPVOID Error;
+	TCHAR szTitle[1024];
+#ifdef UNICODE
+	_stprintf_s(szTitle,ARRAYSIZE(szTitle),TEXT("%S(%d)"),szFile, dwLine);
+#else
+	_stprintf_s(szTitle,ARRAYSIZE(szTitle),TEXT("%s(%d)"),szFile, dwLine);
+#endif
+	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,status,0,(LPTSTR)&Error,0,NULL);
+	MessageBox(NULL,(LPCTSTR)Error,szTitle ,MB_ICONASTERISK);
+	LocalFree(Error);
+}
+
+BOOL StartLogging()
+{
+	BOOL fReturn = FALSE;
+	TRACEHANDLE SessionHandle;
+	struct _Prop
+	{
+		EVENT_TRACE_PROPERTIES TraceProperties;
+		TCHAR LogFileName[1024];
+		TCHAR LoggerName[1024];
+	} Properties;
+	ULONG err;
+	__try
+	{
+		memset(&Properties, 0, sizeof(Properties));
+		Properties.TraceProperties.Wnode.BufferSize = sizeof(Properties);
+		Properties.TraceProperties.Wnode.Guid = TracingGuid;
+		Properties.TraceProperties.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
+		Properties.TraceProperties.Wnode.ClientContext = 1;
+		Properties.TraceProperties.LogFileMode = 4864; 
+		Properties.TraceProperties.LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
+		Properties.TraceProperties.LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + 1024;
+		Properties.TraceProperties.MaximumFileSize = 8;
+		_tcscpy_s(Properties.LogFileName,1024,TEXT("c:\\Windows\\system32\\LogFiles\\WMI\\OpenPGPmdrv.etl"));
+		DeleteFile(Properties.LogFileName);
+		err = StartTrace(&SessionHandle, TEXT("OpenPGPmdrv"), &(Properties.TraceProperties));
+		if (err != ERROR_SUCCESS)
+		{
+			MessageBoxWin32(err);
+			__leave;
+		}
+		err = EnableTraceEx(&TracingGuid,NULL,SessionHandle,TRUE,WINEVENT_LEVEL_VERBOSE,0,0,0,NULL);
+		if (err != ERROR_SUCCESS)
+		{
+			MessageBoxWin32(err);
+			__leave;
+		}
+		fReturn = TRUE;
+	}
+	__finally
+	{
+	}
+	return fReturn;
+}
+
+void StopLogging()
+{
+	LONG err;
+	struct _Prop
+	{
+		EVENT_TRACE_PROPERTIES TraceProperties;
+		TCHAR LogFileName[1024];
+		TCHAR LoggerName[1024];
+	} Properties;
+	memset(&Properties, 0, sizeof(Properties));
+	Properties.TraceProperties.Wnode.BufferSize = sizeof(Properties);
+	Properties.TraceProperties.Wnode.Guid = TracingGuid;
+	Properties.TraceProperties.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
+	Properties.TraceProperties.LogFileMode = 4864; 
+	Properties.TraceProperties.LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
+	Properties.TraceProperties.LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + 1024 * sizeof(TCHAR);
+	Properties.TraceProperties.MaximumFileSize = 8;
+	err = ControlTrace((TRACEHANDLE)NULL, TEXT("OpenPGPmdrv"), &(Properties.TraceProperties),EVENT_TRACE_CONTROL_STOP);
+	if (err != ERROR_SUCCESS && err != 0x00001069)
+	{
+		MessageBoxWin32(err);
+	}
+}
+
+void EnableLogging()
+{
+	DWORD64 qdwValue;
+	DWORD dwValue;
+	LONG err;
+
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("Guid"), REG_SZ, TEXT("{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}"),sizeof(TEXT("{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}")));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("FileName"), REG_SZ, TEXT("c:\\windows\\system32\\LogFiles\\WMI\\OpenPGPmdrv.etl"),sizeof(TEXT("c:\\windows\\system32\\LogFiles\\WMI\\OpenPGPmdrv.etl")));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 8;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("FileMax"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 1;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("Start"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 8;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("BufferSize"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("FlushTimer"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("MaximumBuffers"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("MinimumBuffers"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 1;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("ClockType"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 64;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("MaxFileSize"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 4864;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("LogFileMode"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 5;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("FileCounter"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"), 
+		TEXT("Status"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+
+	dwValue = 1;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv\\{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}"), 
+		TEXT("Enabled"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 5;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv\\{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}"), 
+		TEXT("EnableLevel"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv\\{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}"), 
+		TEXT("EnableProperty"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	dwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv\\{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}"), 
+		TEXT("Status"), REG_DWORD,&dwValue,sizeof(DWORD));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	qdwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv\\{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}"), 
+		TEXT("MatchAllKeyword"), REG_QWORD,&qdwValue,sizeof(DWORD64));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	qdwValue = 0;
+	err = RegSetKeyValue(	HKEY_LOCAL_MACHINE, 
+		TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv\\{081CCE5F-5F9C-4b43-9A15-1DCF5D2D45F5}"), 
+		TEXT("MatchAnyKeyword"), REG_QWORD,&qdwValue,sizeof(DWORD64));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	StartLogging();
+}
+
+void DisableLogging()
+{
+	
+	LONG err = RegDeleteTree(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\WMI\\Autologger\\OpenPGPmdrv"));
+	if (err != ERROR_SUCCESS) {MessageBoxWin32(err); return;}
+	StopLogging();
+}

Added: trunk/OpenPGPminidriver/Tracing.h
===================================================================
--- trunk/OpenPGPminidriver/Tracing.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/Tracing.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,38 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#pragma once
+
+#define WINEVENT_LEVEL_CRITICAL 1
+#define WINEVENT_LEVEL_ERROR    2
+#define WINEVENT_LEVEL_WARNING  3
+#define WINEVENT_LEVEL_INFO     4
+#define WINEVENT_LEVEL_VERBOSE  5
+
+void TracingRegister();
+void TracingUnRegister();
+
+#define Trace(dwLevel, ...) \
+	TraceEx(__FILE__,__LINE__,__FUNCTION__, dwLevel, __VA_ARGS__);
+
+void TraceEx(PCSTR szFile, DWORD dwLine, PCSTR szFunction, UCHAR dwLevel, PCWSTR szFormat,...);
+
+void TraceDumpEx(LPCSTR szFile, DWORD dwLine, LPCSTR szFunction, UCHAR dwLevel,
+			   __in PBYTE pbCmd, __in DWORD dwCmdSize);
+
+#define TraceDump(dwLevel, pbCmd,dwCmdSize) \
+	TraceDumpEx(__FILE__,__LINE__,__FUNCTION__, dwLevel, pbCmd,dwCmdSize);
\ No newline at end of file

Added: trunk/OpenPGPminidriver/driver.inf
===================================================================
--- trunk/OpenPGPminidriver/driver.inf	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/driver.inf	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,142 @@
+;
+;OpenPGP Smartcard Minidriver for an x86 and x64 based package.
+;
+
+[Version]
+Signature="$Windows NT$"
+Class=SmartCard
+ClassGuid={990A2BD7-E738-46c7-B26F-1CF8FB9F1391}
+Provider=%OPENPGP%
+CatalogFile=delta.cat
+DriverVer=02/23/2010,0.0.0.1
+
+[Manufacturer]
+%OPENPGP%=OpenPGP,NTamd64,NTamd64.6.1,NTx86,NTx86.6.1
+
+[OpenPGP.NTamd64]
+%OpenPGPCardDeviceName%=OpenPGP64_Install,SCFILTER\CID_0031c573c00140009000
+
+[OpenPGP.NTx86]
+%OpenPGPCardDeviceName%=OpenPGP32_Install,SCFILTER\CID_0031c573c00140009000
+
+[OpenPGP.NTamd64.6.1]
+%OpenPGPCardDeviceName%=OpenPGP64_61_Install,SCFILTER\CID_0031c573c00140009000
+
+[OpenPGP.NTx86.6.1]
+%OpenPGPCardDeviceName%=OpenPGP32_61_Install,SCFILTER\CID_0031c573c00140009000
+
+[SourceDisksFiles]
+openpgpmdrv64.dll=1
+openpgpmdrv32.dll=1
+
+[SourceDisksNames]
+1 = %MediaDescription%
+
+[OpenPGP64_Install.NT]
+CopyFiles=amd64_CopyFiles
+CopyFiles=wow64_CopyFiles
+AddReg=AddRegWOW64
+AddReg=AddReg64
+
+[OpenPGP64_61_Install.NT]
+CopyFiles=amd64_CopyFiles
+CopyFiles=wow64_CopyFiles
+AddReg=AddRegWOW64
+AddReg=AddReg64
+Include=umpass.inf
+Needs=UmPass
+
+[OpenPGP32_Install.NT]
+CopyFiles=x86_CopyFiles
+AddReg=AddReg32
+
+[OpenPGP32_61_Install.NT]
+CopyFiles=x86_CopyFiles
+AddReg=AddReg32
+Include=umpass.inf
+Needs=UmPass
+
+[OpenPGP64_61_Install.NT.Services]
+Include=umpass.inf
+Needs=UmPass.Services
+
+[OpenPGP32_61_Install.NT.Services]
+Include=umpass.inf
+Needs=UmPass.Services
+
+
+[OpenPGP64_61_Install.NT.HW]
+Include=umpass.inf
+Needs=UmPass.HW
+
+[OpenPGP64_61_Install.NT.CoInstallers]
+Include=umpass.inf
+Needs=UmPass.CoInstallers
+
+
+[OpenPGP64_61_Install.NT.Interfaces]
+Include=umpass.inf
+Needs=UmPass.Interfaces
+
+
+[OpenPGP32_61_Install.NT.HW]
+Include=umpass.inf
+Needs=UmPass.HW
+
+[OpenPGP32_61_Install.NT.CoInstallers]
+Include=umpass.inf
+Needs=UmPass.CoInstallers
+
+
+[OpenPGP32_61_Install.NT.Interfaces]
+Include=umpass.inf
+Needs=UmPass.Interfaces
+
+
+[amd64_CopyFiles]
+%SmartCardCardModule64%
+
+[x86_CopyFiles]
+%SmartCardCardModule32%
+
+[wow64_CopyFiles]
+%SmartCardCardModule32%
+
+[AddRegWOW64]
+HKLM, %SmartCardNameWOW64%,"ATR",0x00000001,3B,DA,18,FF,81,B1,FE,75,1F,03,00,31,C5,73,C0,01,40,00,90,00,0C
+HKLM, %SmartCardNameWOW64%,"ATRMask",0x00000001,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
+HKLM, %SmartCardNameWOW64%,"Crypto Provider",0x00000000,"Microsoft Base Smart Card Crypto Provider"
+HKLM, %SmartCardNameWOW64%,"Smart Card Key Storage Provider",0x00000000,"Microsoft Smart Card Key Storage Provider"
+HKLM, %SmartCardNameWOW64%,"80000001",0x00000000,%SmartCardCardModule32%
+
+[AddReg32]
+HKLM, %SmartCardName%,"ATR",0x00000001,3B,DA,18,FF,81,B1,FE,75,1F,03,00,31,C5,73,C0,01,40,00,90,00,0C
+HKLM, %SmartCardName%,"ATRMask",0x00000001,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
+HKLM, %SmartCardName%,"Crypto Provider",0x00000000,"Microsoft Base Smart Card Crypto Provider"
+HKLM, %SmartCardName%,"Smart Card Key Storage Provider",0x00000000,"Microsoft Smart Card Key Storage Provider"
+HKLM, %SmartCardName%,"80000001",0x00000000,%SmartCardCardModule32%
+
+[AddReg64]
+HKLM, %SmartCardName%,"ATR",0x00000001,3B,DA,18,FF,81,B1,FE,75,1F,03,00,31,C5,73,C0,01,40,00,90,00,0C
+HKLM, %SmartCardName%,"ATRMask",0x00000001,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
+HKLM, %SmartCardName%,"Crypto Provider",0x00000000,"Microsoft Base Smart Card Crypto Provider"
+HKLM, %SmartCardName%,"Smart Card Key Storage Provider",0x00000000,"Microsoft Smart Card Key Storage Provider"
+HKLM, %SmartCardName%,"80000001",0x00000000,%SmartCardCardModule64%
+
+
+[DestinationDirs]
+amd64_CopyFiles=10,system32
+x86_CopyFiles=10,system32
+wow64_CopyFiles=10,syswow64
+
+
+; =================== Generic ==================================
+
+[Strings]
+OPENPGP ="OpenPGP"
+MediaDescription="OpenPGP Smart Card Minidriver Installation Disk"
+OpenPGPCardDeviceName="OpenPGP Minidriver for Smart Card"
+SmartCardName="SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\OpenPGP"
+SmartCardNameWOW64="SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\OpenPGP"
+SmartCardCardModule32="openpgpmdrv32.dll"
+SmartCardCardModule64="openpgpmdrv64.dll"

Added: trunk/OpenPGPminidriver/version.rc
===================================================================
--- trunk/OpenPGPminidriver/version.rc	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver/version.rc	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,25 @@
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION 0,3,0,2
+PRODUCTVERSION 0,3,0,2
+FILEOS 0x00000004
+FILETYPE 0x00000002
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904B0"
+    BEGIN
+      VALUE "CompanyName", "\0"
+      VALUE "FileDescription", "OpenPGP smart card mini driver\0"
+      VALUE "FileVersion", "0.0.0.1\0"
+      VALUE "InternalName", "openpgpmdrv.dll\0"
+      VALUE "OriginalFilename", "openpgpmdrv.dll\0"
+      VALUE "ProductName", "OpenPGP smart card mini driver\0"
+      VALUE "ProductVersion", "0.0.0.1\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x0409, 0x04B0
+  END
+END
+

Added: trunk/OpenPGPminidriver.sln
===================================================================
--- trunk/OpenPGPminidriver.sln	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriver.sln	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,39 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenPGPminidriver", "OpenPGPminidriver\OpenPGPminidriver.vcproj", "{775DAB1D-5A49-4A57-B259-AD3DC833A75F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenPGPminidriverTest", "OpenPGPminidriverTest\OpenPGPminidriverTest.vcproj", "{4E413ED7-0D68-47A9-AB93-39319815E730}"
+	ProjectSection(ProjectDependencies) = postProject
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F} = {775DAB1D-5A49-4A57-B259-AD3DC833A75F}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Debug|Win32.ActiveCfg = Debug|Win32
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Debug|Win32.Build.0 = Debug|Win32
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Debug|x64.ActiveCfg = Debug|x64
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Debug|x64.Build.0 = Debug|x64
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Release|Win32.ActiveCfg = Release|Win32
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Release|Win32.Build.0 = Release|Win32
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Release|x64.ActiveCfg = Release|x64
+		{775DAB1D-5A49-4A57-B259-AD3DC833A75F}.Release|x64.Build.0 = Release|x64
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Debug|Win32.ActiveCfg = Debug|Win32
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Debug|Win32.Build.0 = Debug|Win32
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Debug|x64.ActiveCfg = Debug|x64
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Debug|x64.Build.0 = Debug|x64
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Release|Win32.ActiveCfg = Release|Win32
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Release|Win32.Build.0 = Release|Win32
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Release|x64.ActiveCfg = Release|x64
+		{4E413ED7-0D68-47A9-AB93-39319815E730}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

Added: trunk/OpenPGPminidriverTest/BaseCSP.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/BaseCSP.cpp	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/BaseCSP.cpp	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,482 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <Cryptuiapi.h>
+#include <commctrl.h>
+#include "dialog.h"
+#pragma comment(lib,"Cryptui")
+#pragma comment(lib,"Crypt32")
+
+extern HWND hMainWnd;
+
+BOOL SchGetProviderNameFromCardName(__in LPCTSTR szCardName, __out LPTSTR szProviderName, __out PDWORD pdwProviderNameLen)
+{
+	// get provider name
+	SCARDCONTEXT hSCardContext;
+	LONG lCardStatus;
+	lCardStatus = SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&hSCardContext);
+	if (SCARD_S_SUCCESS != lCardStatus)
+	{
+		return FALSE;
+	}
+	
+	lCardStatus = SCardGetCardTypeProviderName(hSCardContext,
+									   szCardName,
+									   SCARD_PROVIDER_CSP,
+									   szProviderName,
+									   pdwProviderNameLen);
+	if (SCARD_S_SUCCESS != lCardStatus)
+	{
+		SCardReleaseContext(hSCardContext);
+		return FALSE;
+	}
+	SCardReleaseContext(hSCardContext);
+	return TRUE;
+}
+
+DWORD ListContainer()
+{
+	HCRYPTPROV HMainCryptProv = NULL;
+	BOOL bStatus = FALSE;
+	LPTSTR szMainContainerName = NULL;
+	CHAR szContainerName[1024];
+	DWORD dwContainerNameLen = sizeof(szContainerName);
+	DWORD dwErr = 0;
+	DWORD dwFlags = CRYPT_FIRST;
+	DWORD dwContextArrayLen = 0;
+	HCRYPTPROV hProv = NULL;
+	HCRYPTKEY hKey = NULL;
+	LPBYTE pbCert = NULL;
+	DWORD dwCertLen = 0;
+	PCCERT_CONTEXT pCertContext = NULL;
+	DWORD pKeySpecs[2] = { AT_KEYEXCHANGE,AT_SIGNATURE};
+	PCCERT_CONTEXT pSelectedContext = NULL;
+	HCERTSTORE hStore = NULL;
+	TCHAR szCardName[256];
+	TCHAR szReaderName[256];
+	TCHAR szOutProviderName[256];
+	DWORD dwOutProviderLength = ARRAYSIZE(szOutProviderName);
+	OPENCARDNAME_EX  dlgStruct;
+	DWORD dwReturn;
+	SCARDCONTEXT     hSCardContext = NULL;
+	SCARDHANDLE hSCardHandle = NULL;
+	__try
+	{
+		
+		SendMessage(GetDlgItem(hMainWnd, IDC_LSTCONTAINER),LB_RESETCONTENT,0,0);
+		dwReturn = SCardEstablishContext(SCARD_SCOPE_USER,
+										NULL,
+										NULL,
+										&hSCardContext );
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+		// Initialize the structure.
+		memset(&dlgStruct, 0, sizeof(dlgStruct));
+		dlgStruct.dwStructSize = sizeof(dlgStruct);
+		dlgStruct.hSCardContext = hSCardContext;
+		dlgStruct.dwFlags = SC_DLG_MINIMAL_UI;
+		dlgStruct.lpstrRdr = szReaderName;
+		dlgStruct.nMaxRdr = ARRAYSIZE(szReaderName);
+		dlgStruct.lpstrCard = szCardName;
+		dlgStruct.nMaxCard = ARRAYSIZE(szCardName);
+		dlgStruct.lpstrTitle = L"Select Card";
+		dlgStruct.dwShareMode = 0;
+		// Display the select card dialog box.
+		dwReturn = SCardUIDlgSelectCard(&dlgStruct);
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+		dwReturn = SCardUIDlgSelectCard(&dlgStruct);
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+		if (!SchGetProviderNameFromCardName(szCardName, szOutProviderName, &dwOutProviderLength))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+	
+		size_t ulNameLen = _tcslen(szReaderName);
+		szMainContainerName = (LPWSTR) LocalAlloc(0,(DWORD)(ulNameLen + 6) * sizeof(WCHAR));
+		if (!szMainContainerName)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		swprintf_s(szMainContainerName,(ulNameLen + 6), L"\\\\.\\%s\\", szReaderName);
+
+		bStatus = CryptAcquireContext(&HMainCryptProv,
+					szMainContainerName,
+					szOutProviderName,
+					PROV_RSA_FULL,
+					CRYPT_SILENT);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			if (dwReturn == NTE_BAD_KEYSET)
+			{
+				bStatus = CryptAcquireContext(&HMainCryptProv,NULL,	szOutProviderName,	PROV_RSA_FULL,	CRYPT_SILENT);
+				if (!bStatus)
+				{
+					dwReturn = GetLastError();
+					__leave;
+				}
+			}
+			else
+			{
+				__leave;
+			}
+			
+		}
+
+
+
+		/* Enumerate all the containers */
+		while (CryptGetProvParam(HMainCryptProv,
+					PP_ENUMCONTAINERS,
+					(LPBYTE) szContainerName,
+					&dwContainerNameLen,
+					dwFlags) &&
+				(dwContextArrayLen < 128)
+				)
+		{
+
+			// convert the container name to unicode
+			int wLen = MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, NULL, 0);
+			LPWSTR szWideContainerName = (LPWSTR) LocalAlloc(0,wLen * sizeof(WCHAR));
+			MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, szWideContainerName, wLen);
+
+			// Acquire a context on the current container
+			if (CryptAcquireContext(&hProv,
+					szWideContainerName,
+					szOutProviderName,
+					PROV_RSA_FULL,
+					0))
+			{
+				// Loop over all the key specs
+				for (int i = 0; i < 2; i++)
+				{
+					if (CryptGetUserKey(hProv,
+							pKeySpecs[i],
+							&hKey) )
+					{
+						TCHAR szText[256];
+						_stprintf_s(szText, ARRAYSIZE(szText), TEXT("%s %d"),szWideContainerName,pKeySpecs[i]);
+						SendDlgItemMessage(hMainWnd,IDC_LSTCONTAINER,LB_ADDSTRING,0,(LPARAM)szText);
+						CryptDestroyKey(hKey);
+						hKey = NULL;
+					}
+				}
+				CryptReleaseContext(hProv, 0);
+				hProv = NULL;
+			}
+			LocalFree(szWideContainerName);
+			
+			// prepare parameters for the next loop
+			dwContainerNameLen = sizeof(szContainerName);
+			dwFlags = 0;
+		}
+	}
+	__finally
+	{
+		if (hKey)
+			CryptDestroyKey(hKey);
+		if (hProv)
+			CryptReleaseContext(hProv, 0);
+		if (szMainContainerName)
+			LocalFree(szMainContainerName);
+		if (HMainCryptProv)
+			CryptReleaseContext(HMainCryptProv, 0);
+	}
+	return dwReturn;
+}
+
+
+DWORD ViewCertificate(PTSTR szContainer, DWORD dwKeySpec)
+{
+	BOOL bStatus;
+	DWORD dwReturn = 0;
+	HCRYPTPROV hProv = NULL;
+	HCRYPTKEY hKey = NULL;
+	DWORD dwCertLen = 0;
+	PBYTE pbCert = NULL;
+	PCCERT_CONTEXT pCertContext = NULL;
+	CRYPTUI_VIEWCERTIFICATE_STRUCT certViewInfo;
+	BOOL fPropertiesChanged = FALSE;
+	__try
+	{
+		bStatus = CryptAcquireContext(&hProv,szContainer, MS_SCARD_PROV, PROV_RSA_FULL,	CRYPT_SILENT);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptGetUserKey(hProv, dwKeySpec, &hKey);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptGetKeyParam(hKey,
+								KP_CERTIFICATE,
+								NULL,
+								&dwCertLen,
+								0);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		pbCert = (LPBYTE) LocalAlloc(0,dwCertLen);
+		if (!pbCert)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptGetKeyParam(hKey,
+							KP_CERTIFICATE,
+							pbCert,
+							&dwCertLen,
+							0);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		pCertContext = CertCreateCertificateContext(
+						X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, 
+						pbCert,
+						dwCertLen);
+		if (!pCertContext)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+						
+		certViewInfo.dwSize = sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
+		certViewInfo.hwndParent = hMainWnd;
+		certViewInfo.dwFlags = CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE | CRYPTUI_DISABLE_EXPORT | CRYPTUI_DISABLE_HTMLLINK;
+		certViewInfo.szTitle = TEXT("Info");
+		certViewInfo.pCertContext = pCertContext;
+		certViewInfo.cPurposes = 0;
+		certViewInfo.rgszPurposes = 0;
+		certViewInfo.pCryptProviderData = NULL;
+		certViewInfo.hWVTStateData = NULL;
+		certViewInfo.fpCryptProviderDataTrustedUsage = FALSE;
+		certViewInfo.idxSigner = 0;
+		certViewInfo.idxCert = 0;
+		certViewInfo.fCounterSigner = FALSE;
+		certViewInfo.idxCounterSigner = 0;
+		certViewInfo.cStores = 0;
+		certViewInfo.rghStores = NULL;
+		certViewInfo.cPropSheetPages = 0;
+		certViewInfo.rgPropSheetPages = NULL;
+		certViewInfo.nStartPage = 0;
+						
+		dwReturn = CryptUIDlgViewCertificate(&certViewInfo,&fPropertiesChanged);
+		
+	}
+	__finally
+	{
+		if (pCertContext)
+			CertFreeCertificateContext(pCertContext);
+		if (pbCert)
+			LocalFree(pbCert);
+		if (hKey)
+			CryptDestroyKey(hKey);
+		if (hProv)
+			CryptReleaseContext(hProv, 0);
+	}
+	return dwReturn;
+}
+
+DWORD Sign(PTSTR szContainer, DWORD dwKeySpec)
+{
+	BOOL bStatus;
+	DWORD dwReturn = 0;
+	HCRYPTPROV hProv = NULL;
+	HCRYPTKEY hKey = NULL;
+	HCRYPTHASH hHash = NULL;
+	PBYTE pbSignature = NULL;
+	DWORD dwSignatureSize = 0;
+	BYTE pbChallenge[20];
+	TCHAR szDescription[] = TEXT("Test");
+	__try
+	{
+		bStatus = CryptAcquireContext(&hProv,szContainer, MS_SCARD_PROV, PROV_RSA_FULL,	0);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptGetUserKey(hProv, dwKeySpec, &hKey);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptGenRandom(hProv,ARRAYSIZE(pbChallenge),pbChallenge);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (!CryptCreateHash(hProv,CALG_SHA,NULL,0,&hHash))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (!CryptSetHashParam(hHash, HP_HASHVAL, pbChallenge, 0))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (!CryptSignHash(hHash,dwKeySpec, szDescription, 0, NULL, &dwSignatureSize))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		pbSignature = (PBYTE) LocalAlloc(0,dwSignatureSize);
+		if (!pbSignature)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (!CryptSignHash(hHash,dwKeySpec, szDescription, 0, pbSignature, &dwSignatureSize))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (!CryptVerifySignature(hHash, pbSignature, dwSignatureSize, hKey, szDescription, 0))
+		{
+			dwReturn = GetLastError();
+		}
+	}
+	__finally
+	{
+		if (pbSignature)
+			LocalFree(pbSignature);
+		if (hHash)
+			CryptDestroyHash(hHash);
+		if (hKey)
+			CryptDestroyKey(hKey);
+		if (hProv)
+			CryptReleaseContext(hProv, 0);
+	}
+	return dwReturn;
+}
+
+DWORD Decrypt(PTSTR szContainer, DWORD dwKeySpec)
+{
+	BOOL bStatus;
+	DWORD dwReturn = 0;
+	HCRYPTPROV hProv = NULL;
+	HCRYPTKEY hKey = NULL;
+	HCRYPTHASH hHash = NULL;
+	PBYTE pbCrypt = NULL;
+	DWORD dwCryptSize = 0, dwBufferSize;
+	BYTE pbChallenge[]=
+	{0x09,0x59,0x1B,0x38,0x56,0xBD,0x71,0xA2,0x38,0x70,0x4E,0xDC,0x47,0xB3,0x0B,0x19,0xB3,
+	0x33,0x65,0x79,0xF7,0x46,0x4C,0xBF,0x24,0x77,
+	0x7E,0x06,0x1D,0xA6,0x97,0x46,0x08,0x0C,0x95};
+	BYTE pbDecrypt[] = 
+	{0x5D,0x29,0xB8,0xC2,0x27,0x26,0xAC,0x36,0x29,0x40,0xEF,0x38,0x65,0xD0,0x37,0x85,0x11,0x91
+,0x18,0x98,0x6A,0xDF,0xA4,0x5A,0xC2,0x66,0x4F,0x1E,0xF6,0xC5,0xE5,0xEE,0x85,0xC2,0x0A,0xA6,0xFF,0x69,0x6D,0xF1,0xF5,0xEA,0x83,0x49
+,0xB6,0x8E,0xE2,0xE8,0x2C,0x0B,0x38,0x9B,0x70,0x60,0xF8,0x1F,0xE1,0xCC,0xE5,0xA4,0xD9,0xF6,0x39,0x8D,0x94,0x6A,0x36,0xF0,0xA5,0x8B
+,0xF3,0x7F,0xC1,0xC8,0x53,0x42,0x70,0x33,0x6E,0x28,0xFC,0x5E,0xAC,0x7B,0xBC,0xB5,0x0D,0x93,0xD6,0xCC,0xF3,0x05,0x47,0xD8,0xAB,0x5E
+,0x43,0x8B,0x17,0x27,0x38,0x70,0xC9,0x0D,0xFC,0xF6,0x8F,0xEA,0x63,0xBB,0xF4,0x58,0xB1,0x8B,0x8D,0xC7,0x89,0x43,0x7A,0x69,0xEC,0x1E
+,0x9F,0x13,0xFC,0xC2,0x73,0xEA,0x04,0x0C,0x4E,0x1B,0x1B,0x55,0x51,0x14,0x20,0x90,0x60,0x30,0x73,0x11,0xE8,0x6F,0xF0,0x45,0xC0,0x49
+,0x1A,0x0B,0x9F,0x7C,0x30,0x5E,0xF9,0x69,0x2F,0x98,0x2C,0x53,0x06,0x02,0x93,0xAE,0xC8,0x12,0xEE,0x81,0xD4,0x9C,0xE6,0x16,0xB2,0x7D
+,0xF3,0x3E,0x9D,0xB5,0xDC,0x39,0x39,0x43,0xA1,0x37,0x81,0x06,0xC8,0x8D,0x40,0xB0,0x62,0x8F,0xE1,0x6C,0xB3,0xDE,0x08,0xC2,0x06,0xD5
+,0x8A,0x57,0xB5,0x3A,0x24,0x7A,0x75,0x97,0xDD,0x06,0x3B,0x16,0x4D,0xEE,0xC7,0x5E,0x88,0x49,0xF0,0x02,0x3C,0x99,0x93,0xE2,0x98,0xC5
+,0x8A,0x65,0x2F,0x85,0x99,0x25,0xC3,0x91,0x62,0x9E,0x39,0xB7,0xAB,0xB6,0x51,0x0C,0x74,0x98,0x5C,0x58,0x70,0x44,0xDE,0x79,0xF0,0xC5
+,0x04,0xAF,0x59,0xA5};
+	__try
+	{
+		bStatus = CryptAcquireContext(&hProv,szContainer, MS_SCARD_PROV, PROV_RSA_FULL,	0);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptGetUserKey(hProv, dwKeySpec, &hKey);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		//bStatus = CryptGenRandom(hProv,ARRAYSIZE(pbChallenge),pbChallenge);
+		if (!bStatus)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		dwCryptSize = 0;
+		dwBufferSize = ARRAYSIZE(pbChallenge);
+		if (!CryptEncrypt(hKey,NULL, TRUE, 0, NULL, &dwBufferSize,0))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		pbCrypt = (PBYTE) LocalAlloc(0,dwBufferSize);
+		if (!pbCrypt)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		memcpy(pbCrypt, pbChallenge,  ARRAYSIZE(pbChallenge));
+		dwCryptSize =  ARRAYSIZE(pbChallenge);
+		if (!CryptEncrypt(hKey,NULL, FALSE, 0, pbCrypt, &dwCryptSize,dwBufferSize))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+			//if (!CryptDecrypt(hKey, NULL, FALSE, 0, pbCrypt, &dwCryptSize))
+		dwCryptSize = ARRAYSIZE(pbDecrypt);
+		if (!CryptDecrypt(hKey, NULL, FALSE, 0, pbDecrypt, &dwCryptSize))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (dwCryptSize != ARRAYSIZE(pbChallenge))
+		{
+			dwReturn = NTE_BAD_DATA;
+			__leave;
+		}
+		if (memcmp(pbChallenge, pbCrypt, dwCryptSize) != 0)
+		{
+			dwReturn = NTE_BAD_DATA;
+			__leave;
+		}
+	}
+	__finally
+	{
+		if (pbCrypt)
+			LocalFree(pbCrypt);
+		if (hKey)
+			CryptDestroyKey(hKey);
+		if (hProv)
+			CryptReleaseContext(hProv, 0);
+	}
+	return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriverTest/CryptoOperations.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/CryptoOperations.cpp	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/CryptoOperations.cpp	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,126 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <cardmod.h>
+#include "global.h"
+
+DWORD GenerateNewKey(DWORD dwIndex)
+{
+	DWORD dwReturn, dwKeySpec;
+	PIN_ID  PinId;
+	__try
+	{
+		 if (!pCardData)
+		{
+			dwReturn = SCARD_E_COMM_DATA_LOST;
+			__leave;
+		}
+		switch(dwIndex)
+		{
+		case 0:	//Signature,
+			dwKeySpec = AT_SIGNATURE;
+			PinId = ROLE_USER;
+			break;
+		case 1: //Authentication,
+			dwKeySpec = AT_SIGNATURE;
+			PinId = 3;
+			break;
+		case 2: // Confidentiality,
+			dwKeySpec = AT_KEYEXCHANGE;
+			PinId = 4;
+			break;
+		default:
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		dwReturn = pCardData->pfnCardCreateContainerEx(pCardData, (BYTE) dwIndex, 
+											CARD_CREATE_CONTAINER_KEY_GEN, 
+											dwKeySpec, 1024, NULL, PinId);
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
+
+DWORD ImportKey(DWORD dwIndex)
+{
+	DWORD dwReturn, dwKeySpec;
+	PIN_ID  PinId;
+	HCRYPTPROV hProv = NULL;
+	HCRYPTKEY hKey = NULL;
+	TCHAR szContainerName[] = TEXT("Test_OPENPGPG");
+	BYTE pbData[4096];
+	DWORD dwDataSize = ARRAYSIZE(pbData);
+	BOOL bStatus;
+	__try
+	{
+		 if (!pCardData)
+		{
+			dwReturn = SCARD_E_COMM_DATA_LOST;
+			__leave;
+		}
+		switch(dwIndex)
+		{
+		case 0:	//Signature,
+			dwKeySpec = AT_SIGNATURE;
+			PinId = ROLE_USER;
+			break;
+		case 1: //Authentication,
+			dwKeySpec = AT_SIGNATURE;
+			PinId = 3;
+			break;
+		case 2: // Confidentiality,
+			dwKeySpec = AT_KEYEXCHANGE;
+			PinId = 4;
+			break;
+		default:
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		bStatus = CryptAcquireContext(&hProv, szContainerName, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
+		if (!bStatus) 
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey);
+		if (!bStatus) 
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		bStatus = CryptExportKey(hKey,  NULL, PRIVATEKEYBLOB, 0, pbData, &dwDataSize);
+		if (!bStatus) 
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		dwReturn = pCardData->pfnCardCreateContainerEx(pCardData, (BYTE) dwIndex, 
+											CARD_CREATE_CONTAINER_KEY_IMPORT, 
+											dwKeySpec, 1024, pbData, PinId);
+	}
+	__finally
+	{
+		if (hKey)
+			CryptDestroyKey(hKey);
+		CryptAcquireContext(&hProv, szContainerName, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
+	}
+	return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriverTest/Dialog.h
===================================================================
--- trunk/OpenPGPminidriverTest/Dialog.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/Dialog.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,36 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define IDD_DLG 1000
+#define IDC_CONNECT 1001
+#define IDC_CurrentDll 1002
+#define IDC_SystemDll 1003
+#define IDC_DISCONNECT 1004
+#define IDC_TXTPIN 1005
+#define IDC_PIN 1006
+#define IDC_FILES 1007
+#define IDC_LISTFILES 1008
+#define IDC_PINADMIN 1009
+#define IDC_PINUSER 1010
+#define IDC_LSTCONTAINER 1011
+#define IDC_CONTAINER 1012
+#define IDC_STC1 1013
+#define IDC_SIGN 1014
+#define IDC_DECRYPT 1015
+#define IDC_CONTAINERINDEX 1016
+#define IDC_NEWKEY 1017
+#define IDC_IMPORTKEY 1018

Added: trunk/OpenPGPminidriverTest/Dialog.rc
===================================================================
--- trunk/OpenPGPminidriverTest/Dialog.rc	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/Dialog.rc	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,28 @@
+#include <Windows.h>
+#include "Dialog.h"
+
+IDD_DLG DIALOGEX -4,-16,475,385
+CAPTION "IDD_DLG"
+FONT 8,"MS Sans Serif",0,0,0
+STYLE WS_VISIBLE|WS_OVERLAPPEDWINDOW
+BEGIN
+  CONTROL "Connect",IDC_CONNECT,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,9,39,54,21
+  CONTROL "Normal",IDC_CurrentDll,"Button",WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP|BS_AUTORADIOBUTTON,12,21,96,12
+  CONTROL "System Driver",IDC_SystemDll,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,12,6,96,12
+  CONTROL "Disconnect",IDC_DISCONNECT,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,69,39,57,21
+  CONTROL "",IDC_TXTPIN,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP,12,90,93,21,WS_EX_CLIENTEDGE
+  CONTROL "Check PIN",IDC_PIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,123,90,45,21
+  CONTROL "",IDC_FILES,"ListBox",WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_NOINTEGRALHEIGHT|LBS_HASSTRINGS|LBS_NOTIFY,186,9,153,108,WS_EX_CLIENTEDGE
+  CONTROL "List Files",IDC_LISTFILES,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,345,22,48,21
+  CONTROL "Admin",IDC_PINADMIN,"Button",WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP|BS_AUTORADIOBUTTON,57,75,36,12
+  CONTROL "User",IDC_PINUSER,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,12,75,33,13
+  CONTROL "",IDC_LSTCONTAINER,"ListBox",WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_NOINTEGRALHEIGHT|LBS_HASSTRINGS|LBS_NOTIFY,15,237,396,93,WS_EX_CLIENTEDGE
+  CONTROL "List container",IDC_CONTAINER,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,351,213,57,21
+  CONTROL "Double clic = show certificate",IDC_STC1,"Static",WS_CHILD|WS_VISIBLE,15,225,282,9
+  CONTROL "Sign",IDC_SIGN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,15,336,57,21
+  CONTROL "Decrypt",IDC_DECRYPT,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,87,336,57,21
+  CONTROL "",IDC_CONTAINERINDEX,"ComboBox",WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST,15,126,90,15
+  CONTROL "Generate new key",IDC_NEWKEY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,129,123,72,21
+  CONTROL "Import key",IDC_IMPORTKEY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,129,147,72,21
+END
+

Added: trunk/OpenPGPminidriverTest/InitializationAndDeconstruct.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/InitializationAndDeconstruct.cpp	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/InitializationAndDeconstruct.cpp	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,256 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <cardmod.h>
+
+#pragma comment(lib,"Scarddlg")
+#pragma comment(lib,"Winscard")
+
+HMODULE hModule = NULL;
+CARD_DATA CardData;
+PCARD_DATA pCardData = NULL;
+SCARD_ATRMASK atr;
+TCHAR szCard[256];
+
+extern "C" {
+
+	//
+	// Heap helpers
+	//
+
+	LPVOID	WINAPI _Alloc(__in        SIZE_T cBytes)
+	{
+		return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes);
+	}
+
+	LPVOID WINAPI _ReAlloc(
+		__in        LPVOID pvMem,
+		__in        SIZE_T cBytes)
+	{
+		return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pvMem, cBytes);
+	}
+
+	void WINAPI	_Free(
+		__in        LPVOID pvMem)
+	{
+		HeapFree(GetProcessHeap(), 0, pvMem);
+	}
+
+	//
+	// Dummy data caching stubs to satisfy the card module callback requirements
+	//
+
+	DWORD WINAPI _CacheAddFileStub(
+		IN      PVOID       pvCacheContext,
+		IN      LPWSTR      wszTag,
+		IN      DWORD       dwFlags,
+		IN      PBYTE       pbData,
+		IN      DWORD       cbData)
+	{
+		UNREFERENCED_PARAMETER(pvCacheContext);
+		UNREFERENCED_PARAMETER(wszTag);
+		UNREFERENCED_PARAMETER(dwFlags);
+		UNREFERENCED_PARAMETER(pbData);
+		UNREFERENCED_PARAMETER(cbData);
+		return ERROR_SUCCESS;
+	}
+
+	DWORD WINAPI _CacheLookupFileStub(
+		IN      PVOID       pvCacheContext,
+		IN      LPWSTR      wszTag,
+		IN      DWORD       dwFlags,
+		IN      PBYTE      *ppbData,
+		IN      PDWORD      pcbData)
+	{
+		UNREFERENCED_PARAMETER(pvCacheContext);
+		UNREFERENCED_PARAMETER(wszTag);
+		UNREFERENCED_PARAMETER(dwFlags);
+		UNREFERENCED_PARAMETER(ppbData);
+		UNREFERENCED_PARAMETER(pcbData);
+		return ERROR_NOT_FOUND;
+	}
+
+	DWORD WINAPI _CacheDeleteFileStub(
+		IN      PVOID       pvCacheContext,
+		IN      LPWSTR      wszTag,
+		IN      DWORD       dwFlags)
+	{
+		UNREFERENCED_PARAMETER(pvCacheContext);
+		UNREFERENCED_PARAMETER(wszTag);
+		UNREFERENCED_PARAMETER(dwFlags);
+		return ERROR_SUCCESS;
+	}
+}
+
+DWORD Connect(BOOL fSystemDll)
+{
+	DWORD dwReturn = 0;
+	SCARDCONTEXT     hSCardContext = NULL;
+	SCARDHANDLE hSCardHandle = NULL;
+	TCHAR szCardModule[256];
+	TCHAR szReader[256];
+	DWORD dwCardModuleSize = ARRAYSIZE(szCardModule);
+	DWORD dwReaderSize = ARRAYSIZE(szReader);
+	OPENCARDNAME_EX  dlgStruct;
+	PFN_CARD_ACQUIRE_CONTEXT pfnCardAcquireContext;
+	
+	__try
+	{
+		// find a smart card
+		/////////////////////
+		
+		dwReturn = SCardEstablishContext(SCARD_SCOPE_USER,
+										NULL,
+										NULL,
+										&hSCardContext );
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+
+		// Initialize the structure.
+		memset(&dlgStruct, 0, sizeof(dlgStruct));
+		dlgStruct.dwStructSize = sizeof(dlgStruct);
+		dlgStruct.hSCardContext = hSCardContext;
+		dlgStruct.dwFlags = SC_DLG_MINIMAL_UI;
+		dlgStruct.lpstrRdr = szReader;
+		dlgStruct.nMaxRdr = dwReaderSize;
+		dlgStruct.lpstrCard = szCard;
+		dlgStruct.nMaxCard = ARRAYSIZE(szCard);
+		dlgStruct.lpstrTitle = L"Select Card";
+		dlgStruct.dwShareMode = 0;
+		// Display the select card dialog box.
+		dwReturn = SCardUIDlgSelectCard(&dlgStruct);
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+
+		// find the dll path / name
+		////////////////////////////
+		if (fSystemDll)
+		{
+			
+			dwReturn = SCardGetCardTypeProviderName(
+				hSCardContext,
+				szCard,
+				SCARD_PROVIDER_CARD_MODULE,
+				(PTSTR) &szCardModule,
+				&dwCardModuleSize);
+			if (0 == dwCardModuleSize)
+			{
+				dwReturn = (DWORD) SCARD_E_UNKNOWN_CARD;
+				__leave;
+			}
+		}
+		else
+		{
+#ifdef WIN64
+			_tcscpy_s(szCardModule, dwCardModuleSize, TEXT("openpgpmdrv64.dll"));
+#else
+			_tcscpy_s(szCardModule, dwCardModuleSize, TEXT("openpgpmdrv32.dll"));
+#endif
+		}
+		// connect to the smart card
+		////////////////////////////
+		DWORD dwProtocol, dwState;
+		dwReturn = SCardConnect(hSCardContext,szReader,SCARD_SHARE_SHARED,SCARD_PROTOCOL_T1|SCARD_PROTOCOL_T0, &hSCardHandle, &dwProtocol);
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+		atr.cbAtr = 32;
+		dwReturn = SCardStatus(hSCardHandle, szReader, &dwReaderSize, &dwState, &dwProtocol, atr.rgbAtr,&atr.cbAtr);
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+		// load
+		////////
+		if (NULL == (hModule = LoadLibrary(szCardModule)))
+        {
+            dwReturn = GetLastError();
+            __leave;
+        }
+
+        if (NULL == (pfnCardAcquireContext = 
+                     (PFN_CARD_ACQUIRE_CONTEXT) GetProcAddress(
+                         hModule, "CardAcquireContext")))
+        {
+            dwReturn = GetLastError();
+            __leave;
+        }
+		// initialize context
+		//////////////////////
+		pCardData = &CardData;
+		pCardData->dwVersion = CARD_DATA_CURRENT_VERSION;
+        pCardData->pfnCspAlloc = _Alloc;
+        pCardData->pfnCspFree = _Free;
+        pCardData->pfnCspReAlloc = _ReAlloc;
+        pCardData->pfnCspCacheAddFile = _CacheAddFileStub;
+        pCardData->pfnCspCacheLookupFile = _CacheLookupFileStub;
+        pCardData->pfnCspCacheDeleteFile = _CacheDeleteFileStub;
+        pCardData->hScard = hSCardHandle;
+        pCardData->hSCardCtx = hSCardContext;
+		pCardData->cbAtr = atr.cbAtr;
+		pCardData->pbAtr = atr.rgbAtr;
+		pCardData->pwszCardName = szCard;
+		dwReturn = SCardBeginTransaction(hSCardHandle);
+		if ( SCARD_S_SUCCESS != dwReturn )
+		{
+			__leave;
+		}
+		dwReturn = pfnCardAcquireContext(pCardData, 0);
+	}
+	__finally
+	{
+		if (dwReturn != 0)
+		{
+			if (hSCardHandle)
+			{
+				SCardEndTransaction(hSCardHandle,SCARD_LEAVE_CARD);
+				SCardDisconnect(hSCardHandle,0);
+			}
+			if (hSCardContext)
+				SCardReleaseContext(hSCardContext);
+		}
+	}
+	return dwReturn;
+}
+
+DWORD Disconnect()
+{
+	DWORD dwReturn = 0;
+	if (pCardData)
+	{
+		if (pCardData->hScard)
+		{
+			SCardEndTransaction(pCardData->hScard,SCARD_LEAVE_CARD);
+			SCardDisconnect(pCardData->hScard,0);
+		}
+		if (pCardData->hSCardCtx)
+			SCardReleaseContext(pCardData->hSCardCtx);
+		pCardData = NULL;
+	}
+	else
+	{
+		dwReturn = SCARD_E_COMM_DATA_LOST;
+	}
+	return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj
===================================================================
--- trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9,00"
+	Name="OpenPGPminidriverTest"
+	ProjectGUID="{4E413ED7-0D68-47A9-AB93-39319815E730}"
+	RootNamespace="OpenPGPminidriverTest"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\$(ProjectName)32.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\$(ProjectName)64.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\$(ProjectName)32.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\$(ProjectName)64.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\BaseCSP.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\CryptoOperations.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\InitializationAndDeconstruct.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\PINOperations.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\PublicDataOperations.cpp"
+				>
+			</File>
+			<Filter
+				Name="UI"
+				>
+				<File
+					RelativePath=".\main.cpp"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Dialog.h"
+				>
+			</File>
+			<File
+				RelativePath=".\global.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resources Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\Dialog.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\RegisterCardForTestIfTheDriverIsNotInstalled.reg"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

Added: trunk/OpenPGPminidriverTest/PINOperations.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/PINOperations.cpp	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/PINOperations.cpp	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,75 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <cardmod.h>
+#include "global.h"
+
+DWORD Authenticate(PWSTR wszPin, PWSTR wszUserId, PDWORD pcAttemptsRemaining)
+{
+	LPSTR szPin = NULL;
+    DWORD cbPin = 0;
+	DWORD dwReturn;
+    __try
+    {
+        if (!pCardData)
+		{
+			dwReturn = SCARD_E_COMM_DATA_LOST;
+			__leave;
+		}
+		//
+        // Convert the PIN to ANSI
+        //
+        if (0 == (cbPin = WideCharToMultiByte(CP_ACP,0,wszPin,-1,NULL,0,NULL,NULL)))
+        {
+            dwReturn = GetLastError();
+            __leave;
+        }
+
+        szPin = (LPSTR) LocalAlloc(0,cbPin);
+		if (szPin == NULL)
+		{
+			dwReturn = GetLastError();
+            __leave;
+		}
+
+        if (0 == (cbPin = WideCharToMultiByte(CP_ACP,0,wszPin,-1,szPin,cbPin,NULL,NULL)))
+        {
+            dwReturn = GetLastError();
+            __leave;
+        }
+
+        //
+        // Call the card module
+        //
+
+        dwReturn = pCardData->pfnCardAuthenticatePin(
+            pCardData,
+            wszUserId,
+            (PBYTE) szPin,
+            cbPin - 1,
+            pcAttemptsRemaining);
+    }
+    __finally
+    {
+        if (NULL != szPin)
+            LocalFree(szPin);
+    }
+
+    return dwReturn;
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriverTest/PublicDataOperations.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/PublicDataOperations.cpp	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/PublicDataOperations.cpp	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,83 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <cardmod.h>
+#include "global.h"
+#include "dialog.h"
+
+extern HWND hMainWnd;
+
+DWORD ListFiles(PSTR szDirectory)
+{
+	DWORD dwReturn = 0, dwSize;
+	LPSTR pszFiles = NULL;
+	
+	dwSize = 0;
+	dwReturn = pCardData->pfnCardEnumFiles(pCardData, szDirectory, &pszFiles, &dwSize, 0);
+	if (!dwReturn)
+	{
+		LPSTR szCurrentFile = pszFiles;
+		while (szCurrentFile[0] != 0)
+		{
+			CHAR szText[256];
+			if (szDirectory)
+			{
+				sprintf_s(szText, ARRAYSIZE(szText),"%s\\%s",szDirectory, szCurrentFile);
+			}
+			else
+			{
+				sprintf_s(szText, ARRAYSIZE(szText),"%s",szCurrentFile);
+			}
+			SendDlgItemMessageA(hMainWnd,IDC_FILES,LB_ADDSTRING,0,(LPARAM)szText);
+			if (strcmp(szCurrentFile,"cardapps") == 0)
+			{
+				PBYTE pbData = NULL;
+				dwSize = 0;
+				dwReturn = pCardData->pfnCardReadFile(pCardData, szDirectory, szCurrentFile, 0, &pbData, &dwSize);
+				if (dwReturn == 0)
+				{
+					CHAR szDirectory[9];
+					for (DWORD dwI = 0; dwI < dwSize; dwI+=8)
+					{
+						memcpy(szDirectory, pbData + dwI, 8);
+						szDirectory[8] = 0;
+						ListFiles(szDirectory);
+					}
+
+					pCardData->pfnCspFree(pbData);
+				}
+			}
+			
+			szCurrentFile = szCurrentFile + strlen(szCurrentFile)+1;
+		}
+		pCardData->pfnCspFree(pszFiles);
+	}
+	return dwReturn;
+}
+
+DWORD ListFiles()
+{
+	if (!pCardData)
+	{
+		return SCARD_E_COMM_DATA_LOST;
+	}
+	SendMessage(GetDlgItem(hMainWnd, IDC_FILES),LB_RESETCONTENT,0,0);
+	return ListFiles(NULL);
+}
\ No newline at end of file

Added: trunk/OpenPGPminidriverTest/RegisterCardForTestIfTheDriverIsNotInstalled.reg
===================================================================
--- trunk/OpenPGPminidriverTest/RegisterCardForTestIfTheDriverIsNotInstalled.reg	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/RegisterCardForTestIfTheDriverIsNotInstalled.reg	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,15 @@
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\OpenPGP]
+"ATR"=    hex:3B,DA,18,FF,81,B1,FE,75,1F,03,00,31,C5,73,C0,01,40,00,90,00,0C
+"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
+"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
+"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
+"80000001"="openpgpmdrv.dll"
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\OpenPGP]
+"ATR"=    hex:3B,DA,18,FF,81,B1,FE,75,1F,03,00,31,C5,73,C0,01,40,00,90,00,0C
+"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
+"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
+"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
+"80000001"="openpgpmdrv.dll"

Added: trunk/OpenPGPminidriverTest/global.h
===================================================================
--- trunk/OpenPGPminidriverTest/global.h	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/global.h	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,28 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+extern PCARD_DATA pCardData;
+DWORD Connect(BOOL fSystemDll);
+DWORD Disconnect();
+DWORD Authenticate(PWSTR wszPin, PWSTR wszUserId, PDWORD pcAttemptsRemaining);
+DWORD ListFiles();
+DWORD ListContainer();
+DWORD ViewCertificate(PTSTR szContainer, DWORD dwKeySpec);
+DWORD Sign(PTSTR szContainer, DWORD dwKeySpec);
+DWORD Decrypt(PTSTR szContainer, DWORD dwKeySpec);
+DWORD GenerateNewKey(DWORD dwIndex);
+DWORD ImportKey(DWORD dwIndex);
\ No newline at end of file

Added: trunk/OpenPGPminidriverTest/main.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/main.cpp	2010-02-23 12:51:40 UTC (rev 0)
+++ trunk/OpenPGPminidriverTest/main.cpp	2010-02-23 19:18:59 UTC (rev 1)
@@ -0,0 +1,194 @@
+/*	OpenPGP Smart Card Mini Driver
+    Copyright (C) 2009 Vincent Le Toux
+
+    This library is Free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License version 2.1 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <cardmod.h>
+#include <commctrl.h>
+#include "dialog.h"
+#include "global.h"
+
+#ifdef UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+// Variables globales :
+HINSTANCE hInst;								// instance actuelle
+HWND hMainWnd;
+
+INT_PTR CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
+
+int APIENTRY _tWinMain(HINSTANCE hInstance,
+                     HINSTANCE hPrevInstance,
+                     LPTSTR    lpCmdLine,
+                     int       nCmdShow)
+{
+	UNREFERENCED_PARAMETER(hPrevInstance);
+	UNREFERENCED_PARAMETER(lpCmdLine);
+	hInst = hInstance;
+	
+    DialogBox (hInst, MAKEINTRESOURCE (IDD_DLG), 0, WndProc);
+    return 0;
+
+}
+
+void MessageBoxWin32(DWORD status) {
+	LPVOID Error;
+	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,status,0,(LPTSTR)&Error,0,NULL);
+	MessageBox(NULL,(LPCTSTR)Error,NULL,MB_ICONASTERISK);
+	LocalFree(Error);
+}
+
+BOOL GetContainerName(PWSTR szContainer, PDWORD pdwKeySpec)
+{
+	DWORD iItem = SendMessage(GetDlgItem(hMainWnd, IDC_LSTCONTAINER),LB_GETCURSEL,0,0);
+	if (iItem == LB_ERR) return FALSE;
+	SendMessage( GetDlgItem(hMainWnd,IDC_LSTCONTAINER), LB_GETTEXT,iItem,(LPARAM)szContainer);
+	*pdwKeySpec = _tstoi(szContainer + _tcslen(szContainer) - 1);
+	szContainer[ _tcslen(szContainer) - 2] = 0;
+	return TRUE;
+}
+
+INT_PTR CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+	int wmId, wmEvent;
+	DWORD dwReturn;
+	TCHAR szPin[256];
+	TCHAR szContainer[256];
+	DWORD dwKeySpec;
+	switch (message)
+	{
+	case WM_INITDIALOG:
+		hMainWnd = hWnd;
+		CheckDlgButton(hWnd,IDC_CurrentDll,BST_CHECKED);
+		CheckDlgButton(hWnd,IDC_PINUSER,BST_CHECKED);
+		SendDlgItemMessage(hMainWnd,IDC_CONTAINERINDEX,CB_ADDSTRING,0,(LPARAM)TEXT("Signature"));
+		SendDlgItemMessage(hMainWnd,IDC_CONTAINERINDEX,CB_ADDSTRING,0,(LPARAM)TEXT("Authentication"));
+		SendDlgItemMessage(hMainWnd,IDC_CONTAINERINDEX,CB_ADDSTRING,0,(LPARAM)TEXT("Confidentiality"));
+		SendDlgItemMessage(hMainWnd,IDC_CONTAINERINDEX, CB_SETCURSEL, 0, 0);
+		break;
+
+	case WM_CLOSE:
+		EndDialog(hWnd, IDOK);
+		return TRUE;
+	case WM_COMMAND:
+		wmId    = LOWORD(wParam);
+		wmEvent = HIWORD(wParam);
+		
+		switch (wmId)
+		{
+			case IDC_CONNECT:
+			if (IsDlgButtonChecked(hWnd,IDC_SystemDll))
+			{
+				dwReturn = Connect(TRUE);
+			}
+			else
+			{
+				dwReturn = Connect(FALSE);
+			}
+			if (dwReturn)
+			{
+				MessageBoxWin32(dwReturn);
+			}
+			break;
+			case IDC_DISCONNECT:
+				dwReturn = Disconnect();
+				if (dwReturn)
+				{
+					MessageBoxWin32(dwReturn);
+				}
+				break;
+			case IDC_PIN:
+				GetDlgItemText(hWnd,IDC_TXTPIN,szPin,ARRAYSIZE(szPin));
+				DWORD dwRemaining;
+				if (IsDlgButtonChecked(hWnd,IDC_PINADMIN))
+				{
+					dwReturn = Authenticate(szPin, wszCARD_USER_ADMIN, &dwRemaining);
+				}
+				else
+				{
+					dwReturn = Authenticate(szPin, wszCARD_USER_USER, &dwRemaining);
+				}
+				MessageBoxWin32(dwReturn);
+				break;
+			case IDC_LISTFILES:
+				dwReturn = ListFiles();
+				if (dwReturn)
+				{
+					MessageBoxWin32(dwReturn);
+				}
+				break;
+			case IDC_NEWKEY:
+				dwReturn = GenerateNewKey(SendDlgItemMessage(hMainWnd,IDC_CONTAINERINDEX, CB_GETCURSEL, 0, 0));
+				MessageBoxWin32(dwReturn);
+				break;
+			case IDC_IMPORTKEY:
+				dwReturn = ImportKey(SendDlgItemMessage(hMainWnd,IDC_CONTAINERINDEX, CB_GETCURSEL, 0, 0));
+				MessageBoxWin32(dwReturn);
+				break;
+				////////// base CSP
+			case IDC_CONTAINER:
+				dwReturn = ListContainer();
+				if (dwReturn)
+				{
+					MessageBoxWin32(dwReturn);
+				}
+				break;
+			case IDC_SIGN:
+				if (GetContainerName(szContainer, &dwKeySpec))
+				{
+					dwReturn = Sign(szContainer, dwKeySpec);
+					MessageBoxWin32(dwReturn);
+				}
+				break;
+			case IDC_DECRYPT:
+				if (GetContainerName(szContainer, &dwKeySpec))
+				{
+					dwReturn = Decrypt(szContainer, dwKeySpec);
+					MessageBoxWin32(dwReturn);
+				}
+				break;
+			case IDC_LSTCONTAINER:
+				switch(wmEvent)
+				{
+					case LBN_DBLCLK:
+						if (GetContainerName(szContainer, &dwKeySpec))
+						{
+							dwReturn = ViewCertificate(szContainer, dwKeySpec);
+							if (dwReturn)
+							{
+								MessageBoxWin32(dwReturn);
+							}
+						}
+						break;
+				}
+				break;
+		}
+		break;
+	}
+	return FALSE;
+}
+



More information about the Openpgpmdrv-commits mailing list