[Openpgpmdrv-commits] r12 - in trunk: . OpenPGPminidriver OpenPGPminidriverTest makemsi makemsi/Resources

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Mar 31 10:59:05 CEST 2010


Author: vletoux
Date: 2010-03-31 10:58:46 +0200 (Wed, 31 Mar 2010)
New Revision: 12

Added:
   trunk/OpenPGPminidriverTest/Enrollment.cpp
   trunk/OpenPGPminidriverTest/Personnalize.cpp
   trunk/makemsi/
   trunk/makemsi/Resources/
   trunk/makemsi/Resources/gnu-lgpl.rtf
   trunk/makemsi/makemsi.cmd
   trunk/makemsi/openpgpmdrv-include.wxs
   trunk/makemsi/openpgpmdrv32release.wxs
   trunk/makemsi/openpgpmdrv64release.wxs
Modified:
   trunk/OpenPGPminidriver/CardCryptographicOperations.c
   trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c
   trunk/OpenPGPminidriver/CardSecureKeyInjection.c
   trunk/OpenPGPminidriver/Context.h
   trunk/OpenPGPminidriver/ContextManagement.c
   trunk/OpenPGPminidriver/CryptoOperations.c
   trunk/OpenPGPminidriver/DllMain.c
   trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj
   trunk/OpenPGPminidriver/PublicDataOperations.c
   trunk/OpenPGPminidriver/PublicDataOperations.h
   trunk/OpenPGPminidriver/SmartCard.c
   trunk/OpenPGPminidriver/Tracing.c
   trunk/OpenPGPminidriver/Tracing.h
   trunk/OpenPGPminidriver/openpgpmdrv.inf
   trunk/OpenPGPminidriver/tlv.c
   trunk/OpenPGPminidriverTest/BaseCSP.cpp
   trunk/OpenPGPminidriverTest/Dialog.h
   trunk/OpenPGPminidriverTest/Dialog.rc
   trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj
   trunk/OpenPGPminidriverTest/PINOperations.cpp
   trunk/OpenPGPminidriverTest/global.h
   trunk/OpenPGPminidriverTest/main.cpp
Log:
first msi Release

Modified: trunk/OpenPGPminidriver/CardCryptographicOperations.c
===================================================================
--- trunk/OpenPGPminidriver/CardCryptographicOperations.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/CardCryptographicOperations.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -58,13 +58,28 @@
 			dwReturn  = SCARD_E_INVALID_PARAMETER;
 			__leave;
 		}
-		if (pInfo->dwVersion != CARD_RSA_KEY_DECRYPT_INFO_VERSION_ONE 
-			&& pInfo->dwVersion != CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO)
+		if (pInfo->dwVersion > CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION)
 		{
 			Trace(WINEVENT_LEVEL_ERROR, L"ERROR_REVISION_MISMATCH");
 			dwReturn  = ERROR_REVISION_MISMATCH;
 			__leave;
 		}
+		if ( pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION 
+			&& pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
+		{
+			dwReturn = ERROR_REVISION_MISMATCH;
+			Trace(WINEVENT_LEVEL_ERROR, L"ERROR_REVISION_MISMATCH %d", pInfo->dwVersion);
+			__leave;
+		}
+		if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO)
+		{
+			if (pInfo->dwPaddingType != CARD_PADDING_PKCS1)
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"UNSUPPORTED PADDING %d", pInfo->dwPaddingType);
+				dwReturn  = SCARD_E_UNSUPPORTED_FEATURE;
+				__leave;
+			}
+		}
 		if (pInfo->dwKeySpec != AT_KEYEXCHANGE)
 		{
 			Trace(WINEVENT_LEVEL_ERROR, L"AT_KEYEXCHANGE %d", pInfo->dwKeySpec);

Modified: trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c
===================================================================
--- trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/CardInitializationAndDeconstruct.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -58,24 +58,13 @@
 			__leave;
 		}
 
-
-		/* CardInitializationAndDeconstruct.c */
 		pCardData->pfnCardDeleteContext           = CardDeleteContext;
-
-		/* CardPinOperation.c */
 		pCardData->pfnCardAuthenticatePin         = CardAuthenticatePin;
 		pCardData->pfnCardGetChallenge            = CardGetChallenge;
 		pCardData->pfnCardAuthenticateChallenge   = CardAuthenticateChallenge;
-		
 		pCardData->pfnCardDeauthenticate          = NULL; //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;
@@ -85,44 +74,47 @@
 		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;
+		// should be null for RSA only card
+		pCardData->pfnCardConstructDHAgreement    = NULL; //CardConstructDHAgreement;
+		
+		if (pCardData->dwVersion >= CARD_DATA_VERSION_FIVE)
+		{
+			pCardData->pfnCardDeriveKey               = NULL; //CardDeriveKey;
+			pCardData->pfnCardDestroyDHAgreement      = NULL; //CardDestroyDHAgreement;
+		}
+		if (pCardData->dwVersion >= CARD_DATA_VERSION_SIX)
+		{
+			pCardData->pfnCardGetChallengeEx          = CardGetChallengeEx;
+			pCardData->pfnCardAuthenticateEx          = CardAuthenticateEx;
+			pCardData->pfnCardChangeAuthenticatorEx   = CardChangeAuthenticatorEx;
+			pCardData->pfnCardDeauthenticateEx        = CardDeauthenticateEx;
+			pCardData->pfnCardGetContainerProperty    = CardGetContainerProperty;
+			pCardData->pfnCardSetContainerProperty    = CardSetContainerProperty;
+			pCardData->pfnCardGetProperty             = CardGetProperty;
+			pCardData->pfnCardSetProperty             = CardSetProperty;
+		}
+		if (pCardData->dwVersion >= CARD_DATA_VERSION_SEVEN)
+		{
+			pCardData->pfnMDImportSessionKey         = MDImportSessionKey;
+			pCardData->pfnMDEncryptData              = MDEncryptData;
+			pCardData->pfnCardImportSessionKey       = CardImportSessionKey;
+			pCardData->pfnCardGetSharedKeyHandle     = CardGetSharedKeyHandle;
+			pCardData->pfnCardGetAlgorithmProperty   = CardGetAlgorithmProperty;
+			pCardData->pfnCardGetKeyProperty         = CardGetKeyProperty;
+			pCardData->pfnCardSetKeyProperty         = CardSetKeyProperty;
+			pCardData->pfnCardProcessEncryptedData   = CardProcessEncryptedData;
+			pCardData->pfnCardDestroyKey             = CardDestroyKey;
+			pCardData->pfnCardCreateContainerEx      = CardCreateContainerEx;
+		}
 	}
 	__finally
 	{

Modified: trunk/OpenPGPminidriver/CardSecureKeyInjection.c
===================================================================
--- trunk/OpenPGPminidriver/CardSecureKeyInjection.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/CardSecureKeyInjection.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -126,6 +126,21 @@
 	return SCARD_E_UNSUPPORTED_FEATURE;
 }
 
+/** This function is used to get the properties of a key.*/
+DWORD WINAPI CardGetKeyProperty(
+    __in PCARD_DATA  pCardData,
+    __in CARD_KEY_HANDLE  hKey,
+    __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,

Modified: trunk/OpenPGPminidriver/Context.h
===================================================================
--- trunk/OpenPGPminidriver/Context.h	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/Context.h	2010-03-31 08:58:46 UTC (rev 12)
@@ -57,7 +57,6 @@
 	FEATURES				SmartCardReaderFeatures;
 	BOOL					fSupportCommandChaining;
 	BOOL					fExtentedLeLcFields;
-	BYTE					bSecureMessagingAlgorithm;
 	DWORD					dwMaxChallengeLength;
 	DWORD					dwMaxCertificateLength;
 	DWORD					dwMaxCommandDataLength;
@@ -70,6 +69,7 @@
 	DWORD					dwExponent[KEYMAX];
 	LARGE_INTEGER			LastCacheCheck[KEYMAX];
 	BOOL					fDoesTheAdminHasBeenAuthenticatedAtLeastOnce;
+	ALG_ID					aiSecureMessagingAlg;
 } OPENPGP_CONTEXT, *POPENPGP_CONTEXT ;
 
 DWORD CreateContext(__in PCARD_DATA pCardData, __in DWORD dwFlags);

Modified: trunk/OpenPGPminidriver/ContextManagement.c
===================================================================
--- trunk/OpenPGPminidriver/ContextManagement.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/ContextManagement.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -81,6 +81,7 @@
 	DWORD dwI, dwJ;
 	BOOL fFound = FALSE;
 	BOOL fRightATRLenFound = FALSE;
+	DWORD dwMinSupportedVersion;
 	__try
 	{
 		if ( pCardData == NULL )
@@ -95,14 +96,24 @@
 			dwReturn  = SCARD_E_INVALID_PARAMETER;
 			__leave;
 		}
-
-		if (pCardData->dwVersion < CARD_DATA_VERSION_SIX)
+		if (fRunOnVistaAndLater)
 		{
-			Trace(WINEVENT_LEVEL_ERROR, L"pCardData->dwVersion(%d) < CARD_DATA_VERSION_SIX", pCardData->dwVersion);
+			dwMinSupportedVersion = CARD_DATA_VERSION_SIX;
+		}
+		else
+		{
+			// only a subset of functions is supported
+			// so the project don't pass the ms test
+			// we do this so the driver can operate under XP
+			dwMinSupportedVersion = CARD_DATA_VERSION_FIVE;
+		}
+		if (pCardData->dwVersion < dwMinSupportedVersion)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"pCardData->dwVersion(%d) < dwMinSupportedVersion(%d)", pCardData->dwVersion, dwMinSupportedVersion);
 			dwReturn  = ERROR_REVISION_MISMATCH;
 			__leave;
 		}
-		pCardData->dwVersion = min(pCardData->dwVersion, CARD_DATA_VERSION_SIX);
+		pCardData->dwVersion = min(pCardData->dwVersion, CARD_DATA_VERSION_SEVEN);
 		for (dwI = 0; dwI < dwSupportedATRCount; dwI++)
 		{
 			if (SupportedATR[dwI].cbAtr == pCardData->cbAtr)
@@ -160,27 +171,9 @@
 				dwReturn = SCARD_E_UNEXPECTED;
 				__leave;
 			}
-			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;
-			}
 		}
 		else
 		{
-			/*if (pCardData->pvVendorSpecific)
-			{
-				Trace(WINEVENT_LEVEL_ERROR, L"pContext != NULL");
-				dwReturn = SCARD_E_UNEXPECTED;
-				__leave;
-			}*/
 			pCardData->pvVendorSpecific = NULL;
 		}
 		dwReturn = 0;
@@ -342,7 +335,19 @@
 		}
 		pContext->fExtentedLeLcFields = ((pbCardCapabilities[2] & 0x40)?TRUE:FALSE);
 		pContext->fSupportCommandChaining = ((pbCardCapabilities[2] & 0x80)?TRUE:FALSE);
-		pContext->bSecureMessagingAlgorithm = pbExtendedCapabilities[1];
+		if (pbExtendedCapabilities[0] & 0x80)
+		{
+			switch(pbExtendedCapabilities[1])
+			{
+			case 0:
+				pContext->aiSecureMessagingAlg = CALG_3DES;
+				break;
+			case 1:
+				pContext->aiSecureMessagingAlg = CALG_AES_128;
+				break;
+			}
+			Trace(WINEVENT_LEVEL_VERBOSE, L"secure messaging supported with aiAlg = %d", pContext->aiSecureMessagingAlg);
+		}
 		pContext->dwMaxChallengeLength = pbExtendedCapabilities[2] * 0x100 + pbExtendedCapabilities[3];
 		pContext->dwMaxCertificateLength = pbExtendedCapabilities[4] * 0x100 + pbExtendedCapabilities[5];
 		pContext->dwMaxCommandDataLength = pbExtendedCapabilities[6] * 0x100 + pbExtendedCapabilities[7];

Modified: trunk/OpenPGPminidriver/CryptoOperations.c
===================================================================
--- trunk/OpenPGPminidriver/CryptoOperations.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/CryptoOperations.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -1444,8 +1444,7 @@
 					0x00,
 					};
 	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
-	DWORD dwI;
-	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
+	DWORD dwI, dwModulusSizeInBytes;
 	__try
 	{
 		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
@@ -1462,13 +1461,9 @@
 			__leave;
 		}
 		// check the buffer size
-		dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, KeyConfidentiality, &Attributes);
-		if (dwReturn)
+		dwModulusSizeInBytes = pContext->dwModulusSizeInBytes[pInfo->bContainerIndex];
+		if (pInfo->cbData < dwModulusSizeInBytes)
 		{
-			__leave;
-		}
-		if (pInfo->cbData < (DWORD)(Attributes.wModulusLengthInBit/8))
-		{
 			dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d", pInfo->cbData);
 			__leave;
@@ -1505,28 +1500,40 @@
 			__leave;
 		}
 		
-		// CryptDecrypt expects the data decrypted using rsa (only the mathematical computation)
-		// this means the data with the padding (removed by the card)
-		// and in little endian (while the card return the data in big endian)
-		// so we rebuilt the padding in reverse order
-		
 		if ( pInfo->cbData < dwResponseSize + 3 + 11)
 		{
 			dwReturn = SCARD_E_INSUFFICIENT_BUFFER;
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d expected = %d", pInfo->cbData, dwResponseSize);
 			__leave;
 		}
-		
-		pInfo->pbData[pInfo->cbData - 1] = 0; // start byte
-		pInfo->pbData[pInfo->cbData - 2] = 02; // block type
-		// padding
-		memset(pInfo->pbData + dwResponseSize + 1,1,pInfo->cbData - 3 - dwResponseSize);
-		pInfo->pbData[dwResponseSize] = 0; // separator
-		// data field in reverse order
-		for(dwI = 0; dwI < dwResponseSize; dwI++)
+		if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO)
 		{
-			pInfo->pbData[dwI] = pbData[dwResponseSize - 1 - dwI];
+			// data field in reverse order (big endian => little endian)
+			for(dwI = 0; dwI < dwResponseSize; dwI++)
+			{
+				pInfo->pbData[dwI] = pbData[dwResponseSize - 1 - dwI];
+			}
+			pInfo->cbData = dwResponseSize;
 		}
+		else
+		{
+			// CryptDecrypt expects the data decrypted using rsa (only the mathematical computation)
+			// this means the data with the padding (removed by the card)
+			// and in little endian (while the card return the data in big endian)
+			// so we rebuilt the padding in reverse order
+			
+			pInfo->pbData[pInfo->cbData - 1] = 0; // start byte
+			pInfo->pbData[pInfo->cbData - 2] = 02; // block type
+			// padding
+			memset(pInfo->pbData + dwResponseSize + 1,1,pInfo->cbData - 3 - dwResponseSize);
+			pInfo->pbData[dwResponseSize] = 0; // separator
+			// data field in reverse order
+			for(dwI = 0; dwI < dwResponseSize; dwI++)
+			{
+				pInfo->pbData[dwI] = pbData[dwResponseSize - 1 - dwI];
+			}
+		}
+		
 	}
 	__finally
 	{

Modified: trunk/OpenPGPminidriver/DllMain.c
===================================================================
--- trunk/OpenPGPminidriver/DllMain.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/DllMain.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -17,7 +17,30 @@
 
 #include <windows.h>
 
+BOOL fRunOnVistaAndLater;
 
+BOOL Is_Vista_or_Later () 
+{
+   OSVERSIONINFOEX osvi;
+   DWORDLONG dwlConditionMask = 0;
+   int op=VER_GREATER_EQUAL;
+
+   // Initialize the OSVERSIONINFOEX structure.
+
+   ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+   osvi.dwMajorVersion = 6;
+
+   // Initialize the condition mask.
+   VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );
+
+   // Perform the test.
+   return VerifyVersionInfo(
+      &osvi, 
+      VER_MAJORVERSION,
+      dwlConditionMask);
+}
+
 /** 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®.
@@ -31,6 +54,7 @@
    // Perform actions based on the reason for calling.
    if (dwReason == DLL_PROCESS_ATTACH)
    {
+	   fRunOnVistaAndLater = Is_Vista_or_Later();
 	   return TRUE;
    }
    else

Modified: trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj
===================================================================
--- trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/OpenPGPminidriver.vcproj	2010-03-31 08:58:46 UTC (rev 12)
@@ -66,6 +66,7 @@
 				OutputFile="$(OutDir)\openpgpmdrv32.dll"
 				LinkIncremental="2"
 				ModuleDefinitionFile="OpenPGPminidriver.def"
+				DelayLoadDLLs="advapi32.dll"
 				GenerateDebugInformation="true"
 				SubSystem="2"
 				TargetMachine="1"
@@ -140,6 +141,7 @@
 				OutputFile="$(OutDir)\openpgpmdrv64.dll"
 				LinkIncremental="2"
 				ModuleDefinitionFile="OpenPGPminidriver.def"
+				DelayLoadDLLs="advapi32.dll"
 				GenerateDebugInformation="true"
 				SubSystem="2"
 				TargetMachine="17"
@@ -214,6 +216,7 @@
 				OutputFile="$(OutDir)\openpgpmdrv32.dll"
 				LinkIncremental="1"
 				ModuleDefinitionFile="OpenPGPminidriver.def"
+				DelayLoadDLLs="advapi32.dll"
 				GenerateDebugInformation="true"
 				SubSystem="2"
 				OptimizeReferences="2"
@@ -291,6 +294,7 @@
 				OutputFile="$(OutDir)\openpgpmdrv64.dll"
 				LinkIncremental="1"
 				ModuleDefinitionFile="OpenPGPminidriver.def"
+				DelayLoadDLLs="advapi32.dll"
 				GenerateDebugInformation="true"
 				SubSystem="2"
 				OptimizeReferences="2"
@@ -360,10 +364,6 @@
 				RelativePath=".\DllMain.c"
 				>
 			</File>
-			<File
-				RelativePath=".\Tracing.c"
-				>
-			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -446,6 +446,10 @@
 				RelativePath=".\PublicDataOperations.c"
 				>
 			</File>
+			<File
+				RelativePath=".\Tracing.c"
+				>
+			</File>
 		</Filter>
 		<File
 			RelativePath=".\README.txt"

Modified: trunk/OpenPGPminidriver/PublicDataOperations.c
===================================================================
--- trunk/OpenPGPminidriver/PublicDataOperations.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/PublicDataOperations.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -68,6 +68,9 @@
 	{szOpenPGPDir, szOpenPGPAlgoAttributesDecryption, StoredOnSmartCard, 0x6E, 0xC2,UnknownAc},
 	{szOpenPGPDir, szOpenPGPAlgoAttributesAuthentication, StoredOnSmartCard, 0x6E, 0xC3, UnknownAc },
 	{szOpenPGPDir, szOpenPGPPUK, StoredOnSmartCard, 0xD3, 0, UnknownAc, OPENPGP_FILE_WRITE_ONLY },
+	{szOpenPGPDir, szOpenPGPSecureMessaging, StoredOnSmartCard, 0xF4, 0, UnknownAc, OPENPGP_FILE_WRITE_ONLY },
+	{szOpenPGPDir, szOpenPGPSecureMessagingCryptographicCheksum, StoredOnSmartCard, 0xD2, 0, UnknownAc, OPENPGP_FILE_WRITE_ONLY },
+	{szOpenPGPDir, szOpenPGPSecureMessagingCryptogram, StoredOnSmartCard, 0xD1, 0, UnknownAc, OPENPGP_FILE_WRITE_ONLY },
 	{NULL, szCARD_IDENTIFIER_FILE, StoredOnSmartCard, 0x4F, 0, EveryoneReadAdminWriteAc},
 	{NULL, szCARD_APPLICATION_FILE, Virtual, 0, 0, EveryoneReadAdminWriteAc},
 	{NULL, szCACHE_FILE, Virtual, 0, 0, EveryoneReadUserWriteAc},

Modified: trunk/OpenPGPminidriver/PublicDataOperations.h
===================================================================
--- trunk/OpenPGPminidriver/PublicDataOperations.h	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/PublicDataOperations.h	2010-03-31 08:58:46 UTC (rev 12)
@@ -33,6 +33,9 @@
 #define szOpenPGPAlgoAttributesDecryption "algcryp"
 #define szOpenPGPAlgoAttributesAuthentication "algauth"
 #define szOpenPGPPUK "puk"
+#define szOpenPGPSecureMessaging "sm"
+#define szOpenPGPSecureMessagingCryptographicCheksum "smmac"
+#define szOpenPGPSecureMessagingCryptogram "smenc"
 
 
 DWORD OCardReadFile(__in PCARD_DATA  pCardData, 

Modified: trunk/OpenPGPminidriver/SmartCard.c
===================================================================
--- trunk/OpenPGPminidriver/SmartCard.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/SmartCard.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -26,6 +26,7 @@
 
 DWORD SelectOpenPGPApplication(__in PCARD_DATA  pCardData);
 
+/** called to re-select the Openpgp application when a SCARD_W_RESET occured */
 DWORD OCardReconnect(__in PCARD_DATA  pCardData)
 {
 	DWORD     dwAP;
@@ -53,6 +54,7 @@
 	return dwReturn;
 }
 
+/** send a command to the smart card with no response expected */
 DWORD OCardSendCommand(__in PCARD_DATA  pCardData, __in PBYTE pbCmd, __in DWORD dwCmdSize)
 {
 	DWORD             dwReturn = 0;
@@ -144,6 +146,7 @@
 	return dwReturn;
 }
 
+/** send the select open pgp application apdu */
 DWORD SelectOpenPGPApplication(__in PCARD_DATA  pCardData)
 {
 	BYTE pbCmd[] = {0x00, 
@@ -158,7 +161,7 @@
 	return OCardSendCommand(pCardData, pbCmd, sizeof(pbCmd));
 }
 
-
+/** send a command to the smart card with response expected */
 DWORD OCardGetData(__in PCARD_DATA  pCardData, 
 					__in PBYTE pbCmd, __in DWORD dwCmdSize,
 					__in PBYTE* pbResponse, __in_opt PDWORD pdwResponseSize)

Modified: trunk/OpenPGPminidriver/Tracing.c
===================================================================
--- trunk/OpenPGPminidriver/Tracing.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/Tracing.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -22,8 +22,20 @@
 #include <Wmistr.h>
 #include <Evntrace.h>
 #include <cardmod.h>
+#include <DelayImp.h>
+#pragma comment(lib, "Delayimp.lib")
 #include "Tracing.h"
 
+/** We are doing a lot of complicated stuff (like hooking a delay load import)
+because the Vista tracing function is much better than XP ones.
+The choice was :
+- do not allow the driver to run on xp (set WINVER to 0x600)
+- don't use the great vista tracing functions (set WINVER to 0x500 and comment the function)
+- run on xp AND use this function (set WINVER to 0x600 and allow to run on xp)
+
+=> tried to have the best
+*/
+
 #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
@@ -37,18 +49,216 @@
 0x81cce5f, 0x5f9c, 0x4b43, 0x9a, 0x15, 0x1d, 0xcf, 0x5d, 0x2d, 0x45, 0xf5);
 
 REGHANDLE hPub = 0;
+BOOL          g_bTracingEnabled         = FALSE;
+TRACEHANDLE   g_SessionHandle = 0; // The handle to the session that enabled the provider.
+UCHAR g_EnableLevel = 0; // Determines the severity of events to log.
+extern BOOL fRunOnVistaAndLater;
+BOOL fDebugOutputIsEnabled = FALSE;
 
+typedef struct _event
+{
+    EVENT_TRACE_HEADER Header;
+    MOF_FIELD Data[MAX_MOF_FIELDS];  // Event-specific data
+} MY_EVENT, *PMY_EVENT;
+
+#define MY_EVENT_TYPE 1
+#define EVENT_DATA_FIELDS_CNT  1
+
+INT_PTR FAR WINAPI DoNothing()
+{
+	return 0;
+}
+
+// delayHookFunc - Delay load hooking function
+// don't fail to load our dll is the computer is xp
+FARPROC WINAPI delayHookFailureFunc (unsigned dliNotify, PDelayLoadInfo pdli)
+{
+	UNREFERENCED_PARAMETER(pdli);
+	if (_stricmp(pdli->szDll,"advapi32.dll") == 0 && dliNotify == dliFailGetProc)
+	{
+		return &DoNothing;
+	}
+
+	return NULL;
+}
+
+
+// __delayLoadHelper gets the hook function in here:
+PfnDliHook __pfnDliFailureHook2 = delayHookFailureFunc;
+
+
+
+// The callback function that receives enable/disable notifications
+// from one or more ETW sessions. Because more than one session
+// can enable the provider, this example ignores requests from other 
+// sessions if it is already enabled.
+
+ULONG WINAPI ControlCallback(
+    WMIDPREQUESTCODE RequestCode,
+    PVOID Context,
+    ULONG* Reserved, 
+    PVOID Header
+    )
+{
+    ULONG status = ERROR_SUCCESS;
+    TRACEHANDLE TempSessionHandle = 0; 
+
+    switch (RequestCode)
+    {
+        case WMI_ENABLE_EVENTS:  // Enable the provider.
+        {
+            SetLastError(0);
+
+            // If the provider is already enabled to a provider, ignore 
+            // the request. Get the session handle of the enabling session.
+            // You need the session handle to call the TraceEvent function.
+            // The session could be enabling the provider or it could be
+            // updating the level and enable flags.
+
+            TempSessionHandle = GetTraceLoggerHandle(Header);
+            if (INVALID_HANDLE_VALUE == (HANDLE)TempSessionHandle)
+            {
+                wprintf(L"GetTraceLoggerHandle failed. Error code is %lu.\n", status = GetLastError());
+                break;
+            }
+
+            if (0 == g_SessionHandle)
+            {
+                g_SessionHandle = TempSessionHandle;
+            }
+            else if (g_SessionHandle != TempSessionHandle)
+            {
+                break;
+            }
+
+            // Get the severity level of the events that the
+            // session wants you to log.
+
+            g_EnableLevel = GetTraceEnableLevel(g_SessionHandle); 
+            g_bTracingEnabled = TRUE;
+            break;
+        }
+ 
+        case WMI_DISABLE_EVENTS:  // Disable the provider.
+        {
+            // Disable the provider only if the request is coming from the
+            // session that enabled the provider.
+
+            TempSessionHandle = GetTraceLoggerHandle(Header);
+            if (INVALID_HANDLE_VALUE == (HANDLE)TempSessionHandle)
+            {
+                wprintf(L"GetTraceLoggerHandle failed. Error code is %lu.\n", status = GetLastError());
+                break;
+            }
+
+            if (g_SessionHandle == TempSessionHandle)
+            {
+                g_bTracingEnabled = FALSE;
+                g_SessionHandle = 0;
+            }
+            break;
+        }
+
+        default:
+        {
+            status = ERROR_INVALID_PARAMETER;
+            break;
+        }
+    }
+
+    return status;
+}
+
+// callback to know if the tracing is activated
+VOID NTAPI ControlCallbackVista (
+    __in LPCGUID SourceId,
+    __in ULONG IsEnabled,
+    __in UCHAR Level,
+    __in ULONGLONG MatchAnyKeyword,
+    __in ULONGLONG MatchAllKeyword,
+    __in_opt PEVENT_FILTER_DESCRIPTOR FilterData,
+    __in_opt PVOID CallbackContext
+    )
+{
+	g_bTracingEnabled = (IsEnabled?TRUE:FALSE);
+}
+
+// called to setup the tracing context
 void TracingRegister() 
 {
-	EventRegister(&TracingGuid,NULL,NULL,&hPub);
+	if (fRunOnVistaAndLater)
+	{
+		EventRegister(&TracingGuid,ControlCallbackVista,NULL,&hPub);
+	}
+	else
+	{
+		RegisterTraceGuids(
+			  ControlCallback,
+			  NULL,
+			  &TracingGuid, 
+			  0, NULL, NULL, 
+			  NULL,
+			  &hPub);
+	}
+#ifdef _DEBUG
+	fDebugOutputIsEnabled = TRUE;
+#endif
 }
-
+// called to clean up the tracing context
 void TracingUnRegister() 
 {
-	EventUnregister(hPub);
+	if (fRunOnVistaAndLater)
+	{
+		EventUnregister(hPub);
+	}
+	else
+	{
+		UnregisterTraceGuids(hPub );
+	}
 }
+// write a single line in the trace
+void WriteTrace(UCHAR dwLevel, PWSTR szTrace)
+{
+	if (fRunOnVistaAndLater)
+	{
+		EventWriteString(hPub,dwLevel,0,szTrace);
+	}
+	else
+	{
+		MY_EVENT MyEvent; 
+		NTSTATUS status;
+		
+		if (g_bTracingEnabled && (0 == g_EnableLevel || dwLevel <= g_EnableLevel))
+		{
+			// Initialize the event data structure.
 
+			ZeroMemory(&MyEvent, sizeof(MY_EVENT));
+			MyEvent.Header.Size = sizeof(EVENT_TRACE_HEADER) + (sizeof(MOF_FIELD) * EVENT_DATA_FIELDS_CNT);
+			MyEvent.Header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR;
+			MyEvent.Header.Guid = TracingGuid;
+			MyEvent.Header.Class.Type = MY_EVENT_TYPE;
+			MyEvent.Header.Class.Version = 1;
+			MyEvent.Header.Class.Level = dwLevel;
 
+			// Load the event data. You can also use the DEFINE_TRACE_MOF_FIELD
+			// macro defined in evntrace.h to set the MOF_FIELD members. For example,
+			// DEFINE_TRACE_MOF_FIELD(&EventData.Data[0], &EventData.Cost, sizeof(EventData.Cost), 0);
+
+			MyEvent.Data[0].DataPtr = (ULONG64) szTrace;
+			MyEvent.Data[0].Length = (ULONG) (sizeof(WCHAR) * (1 + wcslen(szTrace)));
+			MyEvent.Data[0].DataType = ETW_STRING_TYPE_VALUE;
+
+			// Write the event.
+
+			status = TraceEvent(g_SessionHandle, &(MyEvent.Header));
+			if (ERROR_SUCCESS != status)
+			{
+				g_bTracingEnabled = FALSE;
+			}
+		}
+	}
+}
+
 void TraceEx(LPCSTR szFile, DWORD dwLine, LPCSTR szFunction, UCHAR dwLevel, PCWSTR szFormat,...) 
 {
 	WCHAR Buffer[256];
@@ -60,22 +270,29 @@
 	UNREFERENCED_PARAMETER(szFile);
 #endif
 	if (!hPub) TracingRegister();
+	if ( g_bTracingEnabled || fDebugOutputIsEnabled) {
 
-	va_start (ap, szFormat);
-	ret = _vsnwprintf_s (Buffer, 256, _TRUNCATE, 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);
-
+		va_start (ap, szFormat);
+		ret = _vsnwprintf_s (Buffer, 256, _TRUNCATE, szFormat, ap);
+		va_end (ap);
+		if (ret <= 0) return;
+		if (ret > 256) ret = 255;
+		Buffer[255] = L'\0';
+		if (fDebugOutputIsEnabled)
+		{
+			swprintf_s(Buffer2,356,L"%S(%d) : %S - %s\r\n",szFile,dwLine,szFunction,Buffer);
+			OutputDebugString(Buffer2);
+		}
+		if (g_bTracingEnabled)
+		{
+			swprintf_s(Buffer2,356,L"%S(%d) : %s",szFunction,dwLine,Buffer);
+			WriteTrace(dwLevel, Buffer2);
+		}
+	}
 }
 
+
+
 void TraceDumpEx(LPCSTR szFile, DWORD dwLine, LPCSTR szFunction, UCHAR dwLevel,
 			  __in PBYTE pbCmd, __in DWORD dwCmdSize)
 {

Modified: trunk/OpenPGPminidriver/Tracing.h
===================================================================
--- trunk/OpenPGPminidriver/Tracing.h	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/Tracing.h	2010-03-31 08:58:46 UTC (rev 12)
@@ -25,6 +25,7 @@
 
 void TracingRegister();
 void TracingUnRegister();
+extern BOOL fRunOnVistaAndLater;
 
 #define Trace(dwLevel, ...) \
 	TraceEx(__FILE__,__LINE__,__FUNCTION__, dwLevel, __VA_ARGS__);

Modified: trunk/OpenPGPminidriver/openpgpmdrv.inf
===================================================================
--- trunk/OpenPGPminidriver/openpgpmdrv.inf	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/openpgpmdrv.inf	2010-03-31 08:58:46 UTC (rev 12)
@@ -7,7 +7,8 @@
 Class=SmartCard
 ClassGuid={990A2BD7-E738-46c7-B26F-1CF8FB9F1391}
 Provider=%OPENPGP%
-CatalogFile=delta.cat
+CatalogFile.ntx86=openpgpmdrv32.cat
+CatalogFile.ntamd64=openpgpmdrv64.cat
 DriverVer=03/18/2010,0.0.0.1
 
 [Manufacturer]

Modified: trunk/OpenPGPminidriver/tlv.c
===================================================================
--- trunk/OpenPGPminidriver/tlv.c	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriver/tlv.c	2010-03-31 08:58:46 UTC (rev 12)
@@ -1,5 +1,24 @@
+/*	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>
 
+
+
 DWORD getTlvSize(__in PBYTE pbPointer, __in PDWORD pdwOffset)
 {
 	DWORD dwSize;
@@ -21,6 +40,7 @@
 	return dwSize;
 }
 
+/** used to parse tlv data returned when reading the public certificate */
 BOOL find_tlv(__in PBYTE pbData, __in  DWORD dwTlvSearched, __in DWORD dwTotalSize, __out PBYTE *pbDataOut, __out_opt PDWORD pdwSize)
 {
 	DWORD dwOffset = 0, dwTlv ;

Modified: trunk/OpenPGPminidriverTest/BaseCSP.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/BaseCSP.cpp	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/BaseCSP.cpp	2010-03-31 08:58:46 UTC (rev 12)
@@ -464,4 +464,5 @@
 			CryptReleaseContext(hProv, 0);
 	}
 	return dwReturn;
-}
\ No newline at end of file
+}
+

Modified: trunk/OpenPGPminidriverTest/Dialog.h
===================================================================
--- trunk/OpenPGPminidriverTest/Dialog.h	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/Dialog.h	2010-03-31 08:58:46 UTC (rev 12)
@@ -9,6 +9,7 @@
 #define IDC_PINUSER 1201
 #define IDC_PINADMIN 1202
 #define IDC_PUK 1208
+#define IDC_SM 1212
 #define IDC_CHECKPIN 1203
 #define IDC_TXTPIN 1204
 #define IDC_TXTPIN2 1205
@@ -16,6 +17,7 @@
 #define IDC_UNBLOCKPIN 1207
 #define IDC_SETPUK 1209
 #define IDC_PERSONNALIZE 1210
+#define IDC_SETSM 1211
 #define IDD_CRYPTO 1300
 #define IDC_SAMEKEY 1301
 #define IDC_IMPORTKEY 1302
@@ -34,3 +36,5 @@
 #define IDC_STC1 1503
 #define IDC_CONTAINER 1504
 #define IDC_LSTCONTAINER 1505
+#define IDD_ENROLL 1600
+#define IDC_ENROLL 1601

Modified: trunk/OpenPGPminidriverTest/Dialog.rc
===================================================================
--- trunk/OpenPGPminidriverTest/Dialog.rc	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/Dialog.rc	2010-03-31 08:58:46 UTC (rev 12)
@@ -28,13 +28,15 @@
   CONTROL "User",IDC_PINUSER,"Button",WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP|BS_AUTORADIOBUTTON,6,15,33,13
   CONTROL "Admin",IDC_PINADMIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,51,15,36,12
   CONTROL "Puk",IDC_PUK,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,93,15,36,12
-  CONTROL "Check PIN",IDC_CHECKPIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,132,36,54,21
-  CONTROL "",IDC_TXTPIN,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP,9,36,93,21,WS_EX_CLIENTEDGE
-  CONTROL "",IDC_TXTPIN2,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP,9,66,93,21,WS_EX_CLIENTEDGE
-  CONTROL "Change Pin",IDC_CHANGEPIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,132,66,54,21
-  CONTROL "Unblock Pin",IDC_UNBLOCKPIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,201,66,54,22
-  CONTROL "Set Puk",IDC_SETPUK,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,267,66,54,21
+  CONTROL "Secure Messaging",IDC_SM,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_AUTORADIOBUTTON,138,15,87,12
+  CONTROL "Check PIN",IDC_CHECKPIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,162,36,54,21
+  CONTROL "",IDC_TXTPIN,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP,9,36,138,21,WS_EX_CLIENTEDGE
+  CONTROL "",IDC_TXTPIN2,"Edit",WS_CHILD|WS_VISIBLE|WS_TABSTOP,9,63,381,21,WS_EX_CLIENTEDGE
+  CONTROL "Change Pin",IDC_CHANGEPIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,165,87,54,21
+  CONTROL "Unblock Pin",IDC_UNBLOCKPIN,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,223,87,54,22
+  CONTROL "Set Puk",IDC_SETPUK,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,282,87,54,21
   CONTROL "Personnalize after the admin pin to succeed ms test for the driver",IDC_PERSONNALIZE,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,12,228,345,27
+  CONTROL "Set SM",IDC_SETSM,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,339,87,51,21
 END
 
 IDD_CRYPTO DIALOGEX 0,0,400,300
@@ -73,3 +75,11 @@
   CONTROL "",IDC_LSTCONTAINER,"ListBox",WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_NOINTEGRALHEIGHT|LBS_HASSTRINGS|LBS_NOTIFY,6,33,378,93,WS_EX_CLIENTEDGE
 END
 
+IDD_ENROLL DIALOGEX 0,0,400,300
+CAPTION "IDD_DLG"
+FONT 8,"MS Sans Serif",0,0,0
+STYLE NOT WS_VISIBLE|WS_CHILDWINDOW
+BEGIN
+  CONTROL "Enroll new certificate",IDC_ENROLL,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,48,27,111,24
+END
+

Added: trunk/OpenPGPminidriverTest/Enrollment.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/Enrollment.cpp	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/Enrollment.cpp	2010-03-31 08:58:46 UTC (rev 12)
@@ -0,0 +1,248 @@
+#include <windows.h>
+#include <tchar.h>
+#include <Cryptuiapi.h>
+#include <commctrl.h>
+#include <cardmod.h>
+#include <Xenroll.h>
+#include <CertEnroll.h>
+
+BOOL SchGetProviderNameFromCardName(__in LPCTSTR szCardName, __out LPTSTR szProviderName, __out PDWORD pdwProviderNameLen);
+
+BSTR GetAuthenticationContainer()
+{
+	BSTR szSignatureContainer = NULL;
+	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;
+	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;
+	LPWSTR szWideContainerName = NULL;
+	__try
+	{
+		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);
+			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
+				if (CryptGetUserKey(hProv,
+						AT_SIGNATURE,
+						&hKey) )
+				{
+					if (wcsncmp(szWideContainerName,L"OPENPGP_",8) == 0
+						&& wcsstr(szWideContainerName, L"_Authenticate") != NULL)
+					{
+						szSignatureContainer = SysAllocString(szWideContainerName);
+					}
+					CryptDestroyKey(hKey);
+					hKey = NULL;
+				}
+				CryptReleaseContext(hProv, 0);
+				hProv = NULL;
+			}
+			LocalFree(szWideContainerName);
+			szWideContainerName = NULL;
+			// prepare parameters for the next loop
+			dwContainerNameLen = sizeof(szContainerName);
+			dwFlags = 0;
+		}
+	}
+	__finally
+	{
+		if (szWideContainerName)
+			LocalFree(szWideContainerName);
+		if (hKey)
+			CryptDestroyKey(hKey);
+		if (hProv)
+			CryptReleaseContext(hProv, 0);
+		if (szMainContainerName)
+			LocalFree(szMainContainerName);
+		if (HMainCryptProv)
+			CryptReleaseContext(HMainCryptProv, 0);
+	}
+	return szSignatureContainer;
+}
+
+
+HRESULT Enroll()
+{
+	BSTR bstrDN = NULL;
+	BSTR bstrReq = NULL;
+	BSTR bstrOID = NULL;
+	ICEnroll4 * pEnroll = NULL;
+	HRESULT hr;
+
+	__try
+	{
+		// initialize COM
+		hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
+		if (FAILED(hr))
+		{
+			__leave;
+		}
+
+		hr = CoCreateInstance( __uuidof(CEnroll2),
+							   NULL,
+							   CLSCTX_INPROC_SERVER,
+							   __uuidof(IEnroll4),
+							   (void **)&pEnroll);
+		if (FAILED(hr))
+		{
+			__leave;
+		}
+		pEnroll->put_ContainerName(GetAuthenticationContainer());
+		pEnroll->put_KeySpec(AT_SIGNATURE);
+		pEnroll->put_UseExistingKeySet(TRUE);
+		pEnroll->put_WriteCertToCSP(FALSE);
+		// generate the DN for the cert request
+		bstrDN = SysAllocString( TEXT("CN=Your Name")   // common name
+								 TEXT(",OU=Your Unit")  // org unit
+								 TEXT(",O=Your Org")    // organization
+								 TEXT(",L=Your City")   // locality
+								 TEXT(",S=Your State")  // state
+								 TEXT(",C=Your Country") );  // country/region
+		if (NULL == bstrDN)
+		{
+			hr = GetLastError();
+			__leave;
+		}
+
+		// generate the OID, for example, "1.3.6.1.4.1.311.2.1.21".
+		bstrOID = SysAllocString(TEXT("1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.20.2.2"));
+		if (NULL == bstrOID)
+		{
+			__leave;
+		}
+
+		// create the PKCS10
+		hr = pEnroll->createPKCS10( bstrDN, bstrOID, &bstrReq );
+		if (FAILED(hr))
+		{
+			__leave;
+		}
+		// do something with the PKCS10 (bstrReq);
+
+	}
+	__finally
+	{
+
+		//clean up resources, etc.
+		if ( bstrDN )
+			SysFreeString( bstrDN );
+		if ( bstrOID )
+			SysFreeString( bstrOID );
+		if ( bstrReq )
+			SysFreeString( bstrReq );
+		if ( pEnroll )
+			pEnroll->Release();
+
+		CoUninitialize();
+	}
+	return hr;
+}
\ No newline at end of file

Modified: trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj
===================================================================
--- trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/OpenPGPminidriverTest.vcproj	2010-03-31 08:58:46 UTC (rev 12)
@@ -333,6 +333,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\Enrollment.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\InitializationAndDeconstruct.cpp"
 				>
 			</File>

Modified: trunk/OpenPGPminidriverTest/PINOperations.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/PINOperations.cpp	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/PINOperations.cpp	2010-03-31 08:58:46 UTC (rev 12)
@@ -107,6 +107,96 @@
     return dwReturn;
 }
 
+BYTE CharToByte(BYTE b)
+{
+	if (b >= 0x30 && b <= 0x39)
+	{
+		return b - 0x30;
+	}
+	if (b >= 0x41 && b <= 0x46)
+	{
+		return b - 0x37;
+	}
+	if (b >= 0x61 && b <= 0x66)
+	{
+		return b - 0x57;
+	}
+	return 0xFF;
+}
+
+DWORD SetSM(PSTR szPin, PSTR szPin2, PDWORD pcAttemptsRemaining)
+{
+	DWORD cbPin = (DWORD) strlen(szPin);
+	DWORD cbPin2 = (DWORD) strlen(szPin2);
+	DWORD dwReturn;
+	BYTE  bBuffer[24];
+	BYTE bTagBuffer[2 + 2 + 24 + 2 +24];
+	DWORD dwBufferSize, dwI;
+	BOOL fSet = FALSE;
+    __try
+    {
+        if (!pCardData)
+		{
+			dwReturn = SCARD_E_COMM_DATA_LOST;
+			__leave;
+		}
+		if (cbPin2 % 2 || cbPin2 / 2 > ARRAYSIZE(bBuffer))
+		{
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		dwBufferSize = cbPin2 / 2;
+		if (dwBufferSize != 24 && dwBufferSize != 16)
+		{
+			dwReturn = SCARD_E_INVALID_PARAMETER;
+			__leave;
+		}
+		for(dwI = 0; dwI < cbPin2 / 2; dwI++)
+		{
+			BYTE b1, b2;
+			b1 = szPin2[dwI * 2];
+			b2 = szPin2[dwI * 2 + 1];
+			b1 = CharToByte(b1);
+			b2 = CharToByte(b2);
+			if (b1 == 0xFF ||  b2 == 0xFF)
+			{
+				dwReturn = SCARD_E_INVALID_PARAMETER;
+				__leave;
+			}
+			bBuffer[dwI] = (BYTE)(b1) * 16 + (b2);
+		}
+		bTagBuffer[0] = 0x4d;
+		bTagBuffer[1] = (BYTE) dwBufferSize * 2 + 2 * 2;
+		bTagBuffer[2] = 0xD1;
+		bTagBuffer[3] = (BYTE) dwBufferSize;
+		memcpy(bTagBuffer + 4, bBuffer, dwBufferSize);
+		bTagBuffer[2 + 2 + dwBufferSize] = 0xD2;
+		bTagBuffer[3 + 2 + dwBufferSize] = (BYTE) dwBufferSize;
+		memcpy(bTagBuffer + 4 + 2 + dwBufferSize, bBuffer, dwBufferSize);
+        dwReturn = pCardData->pfnCardAuthenticateEx(
+            pCardData,
+            ROLE_ADMIN,0,
+            (PBYTE) szPin,
+            cbPin, NULL,NULL,
+            pcAttemptsRemaining);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = pCardData->pfnCardSetProperty(pCardData, CP_CARD_READ_ONLY, (PBYTE) &fSet, sizeof(BOOL),0);
+		if (dwReturn) __leave;
+		//dwReturn = pCardData->pfnCardWriteFile(pCardData, "openpgp", "smenc", 0, bBuffer, dwBufferSize);
+		dwReturn = pCardData->pfnCardWriteFile(pCardData, "openpgp", "sm", 0, bTagBuffer, 6 + 2*dwBufferSize);
+		if (dwReturn) __leave;
+		
+    }
+    __finally
+    {
+    }
+
+    return dwReturn;
+}
+
 DWORD ResetPin(PSTR szPin, PSTR szPin2, BOOL fIsPUK, PDWORD pcAttemptsRemaining)
 {
 	DWORD cbPin = (DWORD) strlen(szPin);

Added: trunk/OpenPGPminidriverTest/Personnalize.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/Personnalize.cpp	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/Personnalize.cpp	2010-03-31 08:58:46 UTC (rev 12)
@@ -0,0 +1,308 @@
+/*	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"
+
+
+
+LPBYTE AllocateAndEncodeObject(LPVOID pvStruct, LPCSTR lpszStructType, LPDWORD pdwSize )
+{
+   // Get Key Usage blob size   
+   LPBYTE pbEncodedObject = NULL;
+   BOOL bResult = TRUE;
+   DWORD dwError;
+	__try
+   {
+	   *pdwSize = 0;	
+	   bResult = CryptEncodeObject(X509_ASN_ENCODING,   
+								   lpszStructType,   
+								   pvStruct,   
+								   NULL, pdwSize);   
+	   if (!bResult)   
+	   {   
+		  dwError = GetLastError();
+		  __leave;   
+	   }   
+
+	   // Allocate Memory for Key Usage Blob   
+	   pbEncodedObject = (LPBYTE)LocalAlloc(0,*pdwSize);   
+	   if (!pbEncodedObject)   
+	   {   
+		  bResult = FALSE;
+		  dwError = GetLastError();   
+		  __leave;   
+	   }   
+
+	   // Get Key Usage Extension blob   
+	   bResult = CryptEncodeObject(X509_ASN_ENCODING,   
+								   lpszStructType,   
+								   pvStruct,   
+								   pbEncodedObject, pdwSize);   
+	   if (!bResult)   
+	   {   
+		  dwError = GetLastError();  
+		  __leave;   
+	   }   
+   }
+   __finally
+   {
+		if (pbEncodedObject && !bResult)
+		{
+			LocalFree(pbEncodedObject);
+		}
+   }
+   return pbEncodedObject;
+}
+
+DWORD Personnalize()
+{
+	DWORD dwReturn;
+	BOOL fSet;
+	HCRYPTPROV hProv = NULL;
+	HCRYPTKEY hKey = NULL;
+	TCHAR szContainerName[] = OPENPGP_TEST_CONTAINER;
+	BYTE pbData[4096];
+	DWORD dwDataSize = ARRAYSIZE(pbData);
+	BOOL bStatus;
+	BYTE One = 1;
+	CERT_NAME_BLOB SubjectIssuerBlob = {0};
+	CERT_INFO CertInfo = {0};
+	CertInfo.rgExtension = 0;
+	CRYPT_BIT_BLOB KeyUsage;  
+	BYTE ByteData; 
+	LPBYTE pbKeyUsage = NULL; 
+	DWORD dwSize;
+	CERT_BASIC_CONSTRAINTS2_INFO BasicConstraints;
+	LPBYTE pbBasicConstraints = NULL;
+	CERT_ENHKEY_USAGE CertEnhKeyUsage = { 0, NULL };  
+	LPBYTE pbEnhKeyUsage = NULL;
+	CERT_EXTENSIONS CertExtensions = {0} ;
+	PCCERT_CONTEXT pNewCertificateContext = NULL;
+	SYSTEMTIME StartTime;
+	SYSTEMTIME EndTime;
+	HCERTSTORE hCertStore = NULL;
+	BYTE pbCertificateBlob[4096];
+	CERT_BLOB dbStore = {ARRAYSIZE(pbCertificateBlob),pbCertificateBlob};
+	__try
+	{
+		 if (!pCardData)
+		{
+			dwReturn = SCARD_E_COMM_DATA_LOST;
+			__leave;
+		}
+		fSet = FALSE;
+		dwReturn = pCardData->pfnCardSetProperty(pCardData, CP_CARD_READ_ONLY, (PBYTE) &fSet, sizeof(BOOL),0);
+		if (dwReturn) __leave;
+		dwReturn = pCardData->pfnCardWriteFile(pCardData, "openpgp", "statusP1", 0, &One, 1);
+		if (dwReturn) __leave;
+		dwReturn = pCardData->pfnCardCreateContainerEx(pCardData, (BYTE) 0, 
+											CARD_CREATE_CONTAINER_KEY_GEN, 
+											AT_SIGNATURE, 1024, NULL, 1);
+		if (dwReturn) __leave;
+		bStatus = CryptAcquireContext(&hProv, szContainerName, MS_ENHANCED_PROV, PROV_RSA_FULL, 0);
+		if (!bStatus) 
+		{
+			dwReturn = GetLastError();
+			if (dwReturn == NTE_BAD_KEYSET)
+			{
+				bStatus = CryptAcquireContext(&hProv, szContainerName, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
+			}
+			if (!bStatus) 
+			{
+				dwReturn = GetLastError();
+				__leave;
+			}
+		}
+		// WARNING : AT_SIGNATURE is used implicitely when creating a new certificate
+		// if you use AT_KEYEXCHANGE, the public key of the container
+		// won't match the public key of the certificate
+		bStatus = CryptGenKey(hProv, AT_SIGNATURE, 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) 1, 
+											CARD_CREATE_CONTAINER_KEY_IMPORT, 
+											AT_KEYEXCHANGE, 1024, pbData, 3);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = pCardData->pfnCardCreateContainerEx(pCardData, (BYTE) 2, 
+											CARD_CREATE_CONTAINER_KEY_IMPORT, 
+											AT_SIGNATURE, 1024, pbData, 3);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		// create the cert data
+		if (!CertStrToName(X509_ASN_ENCODING,TEXT("CN=test"),CERT_X500_NAME_STR,NULL,NULL,&SubjectIssuerBlob.cbData,NULL))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		SubjectIssuerBlob.pbData = (PBYTE) LocalAlloc(0,SubjectIssuerBlob.cbData);
+		if (!SubjectIssuerBlob.pbData)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (!CertStrToName(X509_ASN_ENCODING,TEXT("CN=test"),CERT_X500_NAME_STR,NULL,(PBYTE)SubjectIssuerBlob.pbData,&SubjectIssuerBlob.cbData,NULL))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		// max 10 extensions => we don't count them
+		CertInfo.rgExtension = (PCERT_EXTENSION) LocalAlloc(0,sizeof(CERT_EXTENSION) * 10);
+		CertInfo.cExtension = 0;
+		if (!CertInfo.rgExtension) __leave;
+
+
+		       // Set Key Usage according to Public Key Type   
+		ZeroMemory(&KeyUsage, sizeof(KeyUsage));   
+		KeyUsage.cbData = 1;   
+		KeyUsage.pbData = &ByteData;   
+		ByteData = CERT_DIGITAL_SIGNATURE_KEY_USAGE |   
+                     CERT_DATA_ENCIPHERMENT_KEY_USAGE|   
+                     CERT_KEY_ENCIPHERMENT_KEY_USAGE |   
+                     CERT_KEY_AGREEMENT_KEY_USAGE;   
+		pbKeyUsage = AllocateAndEncodeObject(&KeyUsage,X509_KEY_USAGE,&dwSize);
+		if (!pbKeyUsage) __leave;
+
+		CertInfo.rgExtension[CertInfo.cExtension].pszObjId = szOID_KEY_USAGE;   
+		CertInfo.rgExtension[CertInfo.cExtension].fCritical = FALSE;   
+		CertInfo.rgExtension[CertInfo.cExtension].Value.cbData = dwSize;   
+		CertInfo.rgExtension[CertInfo.cExtension].Value.pbData = pbKeyUsage;   
+		// Increase extension count   
+		CertInfo.cExtension++; 
+		//////////////////////////////////////////////////
+
+		// Zero Basic Constraints structure   
+		ZeroMemory(&BasicConstraints, sizeof(BasicConstraints));   
+
+		BasicConstraints.fCA = TRUE;   
+		BasicConstraints.fPathLenConstraint = TRUE;   
+		BasicConstraints.dwPathLenConstraint = 1;   
+		pbBasicConstraints = AllocateAndEncodeObject(&BasicConstraints,X509_BASIC_CONSTRAINTS2,&dwSize);
+		if (!pbBasicConstraints) __leave;
+
+		// Set Basic Constraints extension   
+		CertInfo.rgExtension[CertInfo.cExtension].pszObjId = szOID_BASIC_CONSTRAINTS2;   
+		CertInfo.rgExtension[CertInfo.cExtension].fCritical = FALSE;   
+		CertInfo.rgExtension[CertInfo.cExtension].Value.cbData = dwSize;   
+		CertInfo.rgExtension[CertInfo.cExtension].Value.pbData = pbBasicConstraints;   
+		// Increase extension count   
+		CertInfo.cExtension++;  
+		//////////////////////////////////////////////////
+		CertEnhKeyUsage.cUsageIdentifier+=4;
+
+		CertEnhKeyUsage.rgpszUsageIdentifier = (LPSTR*) LocalAlloc(0,sizeof(LPSTR)*CertEnhKeyUsage.cUsageIdentifier);
+		if (!CertEnhKeyUsage.rgpszUsageIdentifier) __leave;
+		CertEnhKeyUsage.cUsageIdentifier = 0;
+		CertEnhKeyUsage.rgpszUsageIdentifier[CertEnhKeyUsage.cUsageIdentifier++] = szOID_PKIX_KP_CLIENT_AUTH;
+		CertEnhKeyUsage.rgpszUsageIdentifier[CertEnhKeyUsage.cUsageIdentifier++] = szOID_PKIX_KP_SERVER_AUTH;
+		CertEnhKeyUsage.rgpszUsageIdentifier[CertEnhKeyUsage.cUsageIdentifier++] = szOID_KP_SMARTCARD_LOGON;
+		CertEnhKeyUsage.rgpszUsageIdentifier[CertEnhKeyUsage.cUsageIdentifier++] = szOID_KP_EFS;
+		pbEnhKeyUsage = AllocateAndEncodeObject(&CertEnhKeyUsage,X509_ENHANCED_KEY_USAGE,&dwSize);
+		if (!pbEnhKeyUsage) __leave;
+
+		// Set Basic Constraints extension   
+		CertInfo.rgExtension[CertInfo.cExtension].pszObjId = szOID_ENHANCED_KEY_USAGE;   
+		CertInfo.rgExtension[CertInfo.cExtension].fCritical = FALSE;   
+		CertInfo.rgExtension[CertInfo.cExtension].Value.cbData = dwSize;   
+		CertInfo.rgExtension[CertInfo.cExtension].Value.pbData = pbEnhKeyUsage;   
+		// Increase extension count   
+		CertInfo.cExtension++; 
+ 
+		//////////////////////////////////////////////////
+
+		CertExtensions.cExtension = CertInfo.cExtension;
+		CertExtensions.rgExtension = CertInfo.rgExtension;
+
+		GetSystemTime(&StartTime);
+		GetSystemTime(&EndTime);
+		EndTime.wYear += 10;
+		pNewCertificateContext = CertCreateSelfSignCertificate(hProv,&SubjectIssuerBlob,
+			0,NULL,NULL,&StartTime,&EndTime,&CertExtensions);
+		if (!pNewCertificateContext)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		/*hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY,0,(HCRYPTPROV)NULL,0,NULL);
+		if (!hCertStore)
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if( !CertAddCertificateContextToStore(hCertStore,                // Store handle
+                                        pNewCertificateContext,                // Pointer to a certificate
+                                        CERT_STORE_ADD_REPLACE_EXISTING, NULL) )
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		if (!CertSaveStore(	hCertStore,
+				PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+				  CERT_STORE_SAVE_AS_PKCS7,
+				    CERT_STORE_SAVE_TO_MEMORY,
+				      &dbStore,
+				0))
+		{
+			dwReturn = GetLastError();
+			__leave;
+		}
+		dwReturn = pCardData->pfnCardWriteFile(pCardData, szBASE_CSP_DIR, "kxc01", 0,
+			dbStore.pbData,
+			dbStore.cbData);
+		if (dwReturn)
+		{
+			__leave;
+		}*/
+		dwReturn = pCardData->pfnCardWriteFile(pCardData, szBASE_CSP_DIR, "kxc01", 0,
+			pNewCertificateContext->pbCertEncoded,
+			pNewCertificateContext->cbCertEncoded);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		ViewCertificate(NULL, pNewCertificateContext);
+		fSet = TRUE;
+		dwReturn = pCardData->pfnCardSetProperty(pCardData, CP_CARD_READ_ONLY, (PBYTE) &fSet, sizeof(BOOL),0);
+		if (dwReturn) __leave;
+
+	}
+	__finally
+	{
+		if (hKey)
+			CryptDestroyKey(hKey);
+		//CryptAcquireContext(&hProv, szContainerName, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
+		if (hProv)
+			CryptReleaseContext(hProv,0);
+	}
+	return dwReturn;
+}
\ No newline at end of file

Modified: trunk/OpenPGPminidriverTest/global.h
===================================================================
--- trunk/OpenPGPminidriverTest/global.h	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/global.h	2010-03-31 08:58:46 UTC (rev 12)
@@ -22,6 +22,7 @@
 DWORD ResetPin(PSTR wszPin, PSTR wszPin2, BOOL fIsPUK, PDWORD pcAttemptsRemaining);
 DWORD ChangePin(PSTR szPin, PSTR szPin2, PWSTR wszUserId, PDWORD pcAttemptsRemaining);
 DWORD SetPuk(PSTR szPin, PSTR szPin2, PDWORD pcAttemptsRemaining);
+DWORD SetSM(PSTR szPin, PSTR szPin2, PDWORD pcAttemptsRemaining);
 DWORD ListFiles(HWND hWnd);
 DWORD ViewFile(HWND hWnd);
 DWORD ListContainer(HWND hWnd);
@@ -34,4 +35,5 @@
 DWORD SetReadOnly(BOOL fSet);
 void ViewCertificate(HWND hWnd, PCCERT_CONTEXT pCertContext);
 DWORD Personnalize();
+HRESULT Enroll();
 #define OPENPGP_TEST_CONTAINER TEXT("Test_OPENPGPG")
\ No newline at end of file

Modified: trunk/OpenPGPminidriverTest/main.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/main.cpp	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/OpenPGPminidriverTest/main.cpp	2010-03-31 08:58:46 UTC (rev 12)
@@ -45,6 +45,7 @@
 INT_PTR CALLBACK	WndProcFile(HWND, UINT, WPARAM, LPARAM);
 INT_PTR CALLBACK	WndProcCrypto(HWND, UINT, WPARAM, LPARAM);
 INT_PTR CALLBACK	WndProcCryptoApi(HWND, UINT, WPARAM, LPARAM);
+INT_PTR CALLBACK	WndProcEnroll(HWND, UINT, WPARAM, LPARAM);
 
 int APIENTRY _tWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
@@ -54,7 +55,7 @@
 	UNREFERENCED_PARAMETER(hPrevInstance);
 	UNREFERENCED_PARAMETER(lpCmdLine);
 	g_hinst = hInstance;
-    PROPSHEETPAGE psp[5];
+    PROPSHEETPAGE psp[6];
     PROPSHEETHEADER psh;
     psp[0].dwSize = sizeof(PROPSHEETPAGE);
     psp[0].dwFlags = PSP_USETITLE;
@@ -101,6 +102,15 @@
     psp[4].pszTitle = TEXT("CryptoApi");
     psp[4].lParam = 0;
     psp[4].pfnCallback = NULL;
+	psp[5].dwSize = sizeof(PROPSHEETPAGE);
+    psp[5].dwFlags = PSP_USETITLE;
+    psp[5].hInstance = g_hinst;
+    psp[5].pszTemplate = MAKEINTRESOURCE(IDD_ENROLL);
+    psp[5].pszIcon = NULL;
+    psp[5].pfnDlgProc = WndProcEnroll;
+    psp[5].pszTitle = TEXT("Enroll");
+    psp[5].lParam = 0;
+    psp[5].pfnCallback = NULL;
     psh.dwSize = sizeof(PROPSHEETHEADER);
     psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE;
     psh.hwndParent = NULL;
@@ -297,6 +307,12 @@
 				dwReturn = SetPuk(szPin, szPin2, &dwRemaining);
 				MessageBoxWin32(dwReturn);
 				break;
+			case IDC_SETSM:
+				GetDlgItemTextA(hWnd,IDC_TXTPIN,szPin,ARRAYSIZE(szPin));
+				GetDlgItemTextA(hWnd,IDC_TXTPIN2,szPin2,ARRAYSIZE(szPin2));
+				dwReturn = SetSM(szPin, szPin2, &dwRemaining);
+				MessageBoxWin32(dwReturn);
+				break;
 			case IDC_PERSONNALIZE:
 				dwReturn = Personnalize();
 				MessageBoxWin32(dwReturn);
@@ -448,3 +464,25 @@
 	return FALSE;
 }
 
+INT_PTR CALLBACK WndProcEnroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+	int wmId, wmEvent;
+	DWORD dwReturn;
+	switch (message)
+	{
+	case WM_INITDIALOG:
+		break;
+	case WM_COMMAND:
+		wmId    = LOWORD(wParam);
+		wmEvent = HIWORD(wParam);
+		
+		switch (wmId)
+		{
+			case IDC_ENROLL:
+				dwReturn = Enroll();
+				MessageBoxWin32(dwReturn);
+				break;
+		}
+	}
+	return FALSE;
+}
\ No newline at end of file

Added: trunk/makemsi/Resources/gnu-lgpl.rtf
===================================================================
--- trunk/makemsi/Resources/gnu-lgpl.rtf	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/makemsi/Resources/gnu-lgpl.rtf	2010-03-31 08:58:46 UTC (rev 12)
@@ -0,0 +1,50 @@
+{\rtf\ansi{     GNU Lesser General Public License - GNU Project - Free Software Foundation (FSF)      GNU LESSER GENERAL PUBLIC LICENSE \par
+\par
+Version 3, 29 June 2007 \par
+\par
+Copyright  2007 Free Software Foundation, Inc.  <http://fsf.org/>\par
+\par
+  Everyone is permitted to copy and distribute verbatim copies  of this license document, but changing it is not allowed. \par
+\par
+This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. \par
+\par
+As used herein, this License refers to version 3 of the GNU Lesser General Public License, and the GNU GPL refers to version 3 of the GNU General Public License. \par
+\par
+The Library refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. \par
+\par
+An Application is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. \par
+\par
+A Combined Work is a work produced by combining or linking an Application with the Library.  The particular version of the Library with which the Combined Work was made is also called the Linked Version. \par
+\par
+The Minimal Corresponding Source for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. \par
+\par
+The Corresponding Application Code for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. \par
+\par
+You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. \par
+\par
+If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:  *a) under this License, provided that you make a good faith effort to    ensure that, in the event an Application does not supply the    function or data, the facility still operates, and performs    whatever part of its purpose remains meaningful, or\par
+ *b) under the GNU GPL, with none of the additional permissions of    this License applicable to that copy.\par
+  3. Object Code Incorporating Material from Library Header Files. \par
+\par
+The object code form of an Application may incorporate material from a header file that is part of the Library.  You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:  *a) Give prominent notice with each copy of the object code that the    Library is used in it and that the Library and its use are    covered by this License.\par
+ *b) Accompany the object code with a copy of the GNU GPL and this license    document.\par
+  4. Combined Works. \par
+\par
+You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:  *a) Give prominent notice with each copy of the Combined Work that    the Library is used in it and that the Library and its use are    covered by this License.\par
+ *b) Accompany the Combined Work with a copy of the GNU GPL and this license    document.\par
+ *c) For a Combined Work that displays copyright notices during    execution, include the copyright notice for the Library among    these notices, as well as a reference directing the user to the    copies of the GNU GPL and this license document.\par
+ *d) Do one of the following:  *0) Convey the Minimal Corresponding Source under the terms of this        License, and the Corresponding Application Code in a form        suitable for, and under terms that permit, the user to        recombine or relink the Application with a modified version of        the Linked Version to produce a modified Combined Work, in the        manner specified by section 6 of the GNU GPL for conveying        Corresponding Source.\par
+ *1) Use a suitable shared library mechanism for linking with the        Library.  A suitable mechanism is one that (a) uses at run time        a copy of the Library already present on the user's computer        system, and (b) will operate properly with a modified version        of the Library that is interface-compatible with the Linked        Version.\par
+ \par
+ *e) Provide Installation Information, but only if you would otherwise    be required to provide such information under section 6 of the    GNU GPL, and only to the extent that such information is    necessary to install and execute a modified version of the    Combined Work produced by recombining or relinking the    Application with a modified version of the Linked Version. (If    you use option 4d0, the Installation Information must accompany    the Minimal Corresponding Source and Corresponding Application    Code. If you use option 4d1, you must provide the Installation    Information in the manner specified by section 6 of the GNU GPL    for conveying Corresponding Source.)\par
+  5. Combined Libraries. \par
+\par
+You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:  *a) Accompany the combined library with a copy of the same work based    on the Library, uncombined with any other library facilities,    conveyed under the terms of this License.\par
+ *b) Give prominent notice with the combined library that part of it    is a work based on the Library, and explaining where to find the    accompanying uncombined form of the same work.\par
+  6. Revised Versions of the GNU Lesser General Public License. \par
+\par
+The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. \par
+\par
+Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License or any later version applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. \par
+\par
+If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.  }}
\ No newline at end of file

Added: trunk/makemsi/makemsi.cmd
===================================================================
--- trunk/makemsi/makemsi.cmd	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/makemsi/makemsi.cmd	2010-03-31 08:58:46 UTC (rev 12)
@@ -0,0 +1,57 @@
+::@echo off
+set VERSION=0.0.0.1
+
+set WIX_PATH="C:\Program Files (x86)\Windows Installer XML v3\bin"
+:: Inf2cat and signtool are installed by Windows Driver Kit:
+set INF2CAT_PATH=C:\WinDDK\7600.16385.0\bin\selfsign
+set SIGNTOOL_PATH=C:\WinDDK\7600.16385.0\bin\x86
+
+:: Certificate name and store
+::set CERTIFICATENAME=Fedict eID(test)
+::set CERTIFICATESTORE=PrivateCertStore
+:: To create a test certificate: 
+::   %SIGNTOOL_PATH%\MakeCert.exe -r -pe -ss  %CERTIFICATESTORE% -n "CN=%CERTIFICATENAME%" fedicteidtest.cer
+
+:: Path to images
+set IMG_PATH=..\img
+
+set BUILDPATH=%~dp0
+
+cd %BUILDPATH%
+
+md %BUILDPATH%\Release
+md %BUILDPATH%\Build
+
+:: copy inf files
+copy %BUILDPATH%\..\OpenPGPminidriver\openpgpmdrv.inf %BUILDPATH%\Release
+
+:: copy dll files
+copy %BUILDPATH%\..\Release\openpgpmdrv32.dll %BUILDPATH%\Release
+copy %BUILDPATH%\..\Release\openpgpmdrv64.dll %BUILDPATH%\Release
+
+:: copy icon
+::copy %IMG_PATH%\beid.ico %BUILDPATH%\Release\
+
+:: Create catalog
+%INF2CAT_PATH%\inf2cat.exe /driver:%BUILDPATH%\Release\ /os:Vista_X86,Vista_X64,7_X86,7_X64,Server2008R2_X64,Server2008_X64,Server2008_X86,Server2003_X64,Server2003_X86,XP_X64,XP_X86
+
+:: Sign the catalog
+::%SIGNTOOL_PATH%\SignTool.exe sign /v /s %CERTIFICATESTORE% /n "%CERTIFICATENAME%"  /t http://timestamp.verisign.com/scripts/timestamp.dll %BUILDPATH%\Debug\openpgpmdrv.cat
+::%SIGNTOOL_PATH%\SignTool.exe sign /v /s %CERTIFICATESTORE% /n "%CERTIFICATENAME%"  /t http://timestamp.verisign.com/scripts/timestamp.dll %BUILDPATH%\Release\openpgpmdrv.cat
+
+:: Create MSI 64 bit Release
+%WIX_PATH%\candle -dVersion=%VERSION% -ext %WIX_PATH%\WixDifxAppExtension.dll openpgpmdrv64release.wxs 
+%WIX_PATH%\light -ext %WIX_PATH%\WixDifxAppExtension.dll -ext WixUIExtension openpgpmdrv64release.wixobj %WIX_PATH%\difxapp_x64.wixlib -o Build\OpenPGPmdrv-%VERSION%-x64.msi
+
+:: Create MSI 32 bit Release
+%WIX_PATH%\candle -dVersion=%VERSION% -ext %WIX_PATH%\WixDifxAppExtension.dll openpgpmdrv32release.wxs 
+%WIX_PATH%\light -ext %WIX_PATH%\WixDifxAppExtension.dll -ext WixUIExtension openpgpmdrv32release.wixobj %WIX_PATH%\difxapp_x86.wixlib -o Build\OpenPGPmdrv-%VERSION%-x86.msi
+
+:: Cleanup
+del openpgpmdrv32release.wixobj
+del Build\OpenPGPmdrv-%VERSION%-x86.wixpdb
+
+del openpgpmdrv64release.wixobj
+del Build\OpenPGPmdrv-%VERSION%-x64.wixpdb
+
+pause  
\ No newline at end of file

Added: trunk/makemsi/openpgpmdrv-include.wxs
===================================================================
--- trunk/makemsi/openpgpmdrv-include.wxs	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/makemsi/openpgpmdrv-include.wxs	2010-03-31 08:58:46 UTC (rev 12)
@@ -0,0 +1,3 @@
+<Include>
+<?define UpgradeCode=8B9CBE88-4B41-4141-A75E-296BD0E4A827 ?>
+</Include>

Added: trunk/makemsi/openpgpmdrv32release.wxs
===================================================================
--- trunk/makemsi/openpgpmdrv32release.wxs	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/makemsi/openpgpmdrv32release.wxs	2010-03-31 08:58:46 UTC (rev 12)
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?include $(sys.SOURCEFILEDIR)openpgpmdrv-include.wxs ?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
+     xmlns:difx='http://schemas.microsoft.com/wix/DifxAppExtension'>
+  <Product UpgradeCode="$(var.UpgradeCode)" Name="OpenPGP Smartcard minidriver (x86)" Id="*" Version="$(var.Version)" Manufacturer="OpenPGP" Language="1033">
+    <Package Id="*" Manufacturer="Fedict" InstallerVersion="200" Platform="x86" Languages="1033" Compressed="yes" SummaryCodepage="1252" />
+
+	<!-- do not edit the rtf file with word! The installer will be unable to read the license -->
+	<WixVariable Id="WixUILicenseRtf" Value="Resources\gnu-lgpl.rtf" />
+
+	<Upgrade Id='$(var.UpgradeCode)'>
+      <UpgradeVersion OnlyDetect='no' Property='OLDERFOUND'
+        Minimum='0.0.0.1' IncludeMinimum='yes'
+        Maximum='$(var.Version)' IncludeMaximum='no' />
+      <UpgradeVersion OnlyDetect='yes' Property='SELFFOUND'
+        Minimum='$(var.Version)' IncludeMinimum='yes'
+        Maximum='$(var.Version)' IncludeMaximum='yes' />
+      <UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
+        Minimum='$(var.Version)' IncludeMinimum='no' />
+    </Upgrade>
+    <CustomAction Id='NoDowngrade' Error='A later version of OpenPGP Smartcard minidriver is already installed.' />
+	<CustomAction Id='AlreadyUpdated' Error='The current version of OpenPGP Smartcard minidriver is already installed.' />
+    <InstallExecuteSequence>
+      <Custom Action='AlreadyUpdated' After='FindRelatedProducts'>SELFFOUND</Custom>
+      <Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND</Custom>
+	  <RemoveExistingProducts Before="InstallInitialize" /> 
+	</InstallExecuteSequence>
+	<UIRef Id="WixUI_Minimal" />
+	<UIRef Id="WixUI_ErrorProgressText" />
+	<Directory Id="TARGETDIR" Name="SourceDir">
+	  <Directory Id="ProgramFilesFolder">
+	    <Directory Id="APPLICATIONROOTDIRECTORY" Name="OpenPGP Smartcard Minidriver">
+          <Component Id="openpgpmdrv" Guid="CE7DCBB4-8FF3-49af-AC0B-39A16C4DC8F7" >
+            <File Id="openpgpmdrv.inf" Name="openpgpmdrv.inf" Source="$(sys.SOURCEFILEDIR)Release\openpgpmdrv.inf" KeyPath="yes" DiskId="1" />
+            <File Id="openpgpmdrv32.cat" Name="openpgpmdrv32.cat" Source="$(sys.SOURCEFILEDIR)Release\openpgpmdrv.cat" KeyPath="no" DiskId="1" />
+            <File Id="openpgpmdrv32.dll" Name="openpgpmdrv32.dll" Source="$(sys.SOURCEFILEDIR)Release\openpgpmdrv32.dll" KeyPath="no" DiskId="1" />
+	        <difx:Driver ForceInstall="no" PlugAndPlayPrompt="no" DeleteFiles="yes"  />
+          </Component>
+		</Directory>
+	  </Directory>
+	</Directory>
+    <Feature Id="DefaultFeature" Level="1">
+      <ComponentRef Id="openpgpmdrv" />
+    </Feature>
+    <Media Id="1" EmbedCab="yes" Cabinet="_6F571DCE799A4EBF99CB3F31745F03E2" />
+  </Product>
+</Wix>

Added: trunk/makemsi/openpgpmdrv64release.wxs
===================================================================
--- trunk/makemsi/openpgpmdrv64release.wxs	2010-03-18 16:03:39 UTC (rev 11)
+++ trunk/makemsi/openpgpmdrv64release.wxs	2010-03-31 08:58:46 UTC (rev 12)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?include $(sys.SOURCEFILEDIR)openpgpmdrv-include.wxs ?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
+     xmlns:difx='http://schemas.microsoft.com/wix/DifxAppExtension'>
+  <Product UpgradeCode="$(var.UpgradeCode)" Name="OpenPGP Smartcard minidriver (x64)" Id="*" Version="$(var.Version)" Manufacturer="OpenPGP" Language="1033">
+    <Package Id="*" Manufacturer="Fedict" InstallerVersion="200" Platform="x64" Languages="1033" Compressed="yes" SummaryCodepage="1252" />
+
+	<!-- do not edit the rtf file with word! The installer will be unable to read the license -->
+	<WixVariable Id="WixUILicenseRtf" Value="Resources\gnu-lgpl.rtf" />
+
+	<Upgrade Id='$(var.UpgradeCode)'>
+      <UpgradeVersion OnlyDetect='no' Property='OLDERFOUND'
+        Minimum='0.0.0.1' IncludeMinimum='yes'
+        Maximum='$(var.Version)' IncludeMaximum='no' />
+      <UpgradeVersion OnlyDetect='yes' Property='SELFFOUND'
+        Minimum='$(var.Version)' IncludeMinimum='yes'
+        Maximum='$(var.Version)' IncludeMaximum='yes' />
+      <UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
+        Minimum='$(var.Version)' IncludeMinimum='no' />
+    </Upgrade>
+    <CustomAction Id='NoDowngrade' Error='A later version of OpenPGP Smartcard minidriver is already installed.' />
+	<CustomAction Id='AlreadyUpdated' Error='The current version of OpenPGP Smartcard minidriver is already installed.' />
+    <InstallExecuteSequence>
+      <Custom Action='AlreadyUpdated' After='FindRelatedProducts'>SELFFOUND</Custom>
+      <Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND</Custom>
+	  <RemoveExistingProducts Before="InstallInitialize" /> 
+	</InstallExecuteSequence>
+	<UIRef Id="WixUI_Minimal" />
+	<UIRef Id="WixUI_ErrorProgressText" />
+	<Directory Id="TARGETDIR" Name="SourceDir">
+	  <Directory Id="ProgramFilesFolder">
+	    <Directory Id="APPLICATIONROOTDIRECTORY" Name="OpenPGP Smartcard Minidriver">
+          <Component Id="openpgpmdrv" Guid="CE7DCBB4-8FF3-49af-AC0B-39A16C4DC8F7" >
+            <File Id="openpgpmdrv.inf" Name="openpgpmdrv.inf" Source="$(sys.SOURCEFILEDIR)Release\openpgpmdrv.inf" KeyPath="yes" DiskId="1" />
+            <File Id="openpgpmdrv64.cat" Name="openpgpmdrv64.cat" Source="$(sys.SOURCEFILEDIR)Release\openpgpmdrv.cat" KeyPath="no" DiskId="1" />
+            <File Id="openpgpmdrv32.dll" Name="openpgpmdrv32.dll" Source="$(sys.SOURCEFILEDIR)Release\openpgpmdrv32.dll" KeyPath="no" DiskId="1" />
+            <File Id="openpgpmdrv64.dll" Name="openpgpmdrv64.dll" Source="$(sys.SOURCEFILEDIR)Release\openpgpmdrv64.dll" KeyPath="no" DiskId="1" />
+	        <difx:Driver ForceInstall="no" PlugAndPlayPrompt="no" DeleteFiles="yes"  />
+          </Component>
+		</Directory>
+	  </Directory>
+	</Directory>
+    <Feature Id="DefaultFeature" Level="1">
+      <ComponentRef Id="openpgpmdrv" />
+    </Feature>
+    <Media Id="1" EmbedCab="yes" Cabinet="_6F571DCE799A4EBF99CB3F31745F03E2" />
+  </Product>
+</Wix>



More information about the Openpgpmdrv-commits mailing list