From 0bf6afc5c01b9eb3024a8cfd04bfd743890db4f6 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 23 Mar 2012 16:00:24 +0000
Subject: Tidy up of assorted Schannel/CAPI stuffs.

Makes Swift disconnect if a smartcard used for auth is removed.
Fixes compilation.
Changes code style in a few places.

diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index b0a1778..28fdb2b 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -550,6 +550,8 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro
 			case ClientError::InvalidCertificateSignatureError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid certificate signature"); break;
 			case ClientError::InvalidCAError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Invalid Certificate Authority"); break;
 			case ClientError::InvalidServerIdentityError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate does not match the host identity"); break;
+			case ClientError::RevokedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has been revoked"); break;
+			case ClientError::RevocationCheckFailedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Unable to determine certificate revocation state"); break;
 		}
 		bool forceReconnectAfterCertificateTrust = false;
 		if (!certificateErrorMessage.empty()) {
diff --git a/Swift/QtUI/CAPICertificateSelector.cpp b/Swift/QtUI/CAPICertificateSelector.cpp
index 0d4768c..cc69956 100644
--- a/Swift/QtUI/CAPICertificateSelector.cpp
+++ b/Swift/QtUI/CAPICertificateSelector.cpp
@@ -6,94 +6,107 @@
 
 #include <string>
 
-#include "CAPICertificateSelector.h"
+#include <Swift/QtUI/CAPICertificateSelector.h>
 
 #define SECURITY_WIN32
 #include <Windows.h>
 #include <WinCrypt.h>
 #include <cryptuiapi.h>
 
+
 #include <Swiften/StringCodecs/Hexify.h>
 #include <boost/algorithm/string.hpp>
+#include <Swift/Controllers/Intl.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+#include <Swiften/Base/Log.h>
 
 namespace Swift {
 
-#define cert_dlg_title L"TLS Client Certificate Selection"
-#define cert_dlg_prompt L"Select a certificate to use for authentication"
 /////Hmm, maybe we should not exlude the "location" column
-#define exclude_columns	 CRYPTUI_SELECT_LOCATION_COLUMN \
-			|CRYPTUI_SELECT_INTENDEDUSE_COLUMN
+#define exclude_columns	 CRYPTUI_SELECT_LOCATION_COLUMN | CRYPTUI_SELECT_INTENDEDUSE_COLUMN
 
-// Size of the SHA1 hash
-#define SHA1_HASH_LEN                20
+#define SHA1_HASH_LENGTH 20
 
 static std::string getCertUri(PCCERT_CONTEXT cert, const char * cert_store_name) {
-	DWORD cbHash = SHA1_HASH_LEN;
-	BYTE aHash[SHA1_HASH_LEN];
-	std::string ret("certstore:");
+	DWORD cbHash = SHA1_HASH_LENGTH;
+	BYTE aHash[SHA1_HASH_LENGTH];
+	std::string result("certstore:");
 
-	ret += cert_store_name;
-	ret += ":sha1:";
+	result += cert_store_name;
+	result += ":sha1:";
 
-	if (CertGetCertificateContextProperty(cert,
-		 CERT_HASH_PROP_ID,
-		 aHash,
-		 &cbHash) == FALSE ) {
+	if (CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID, aHash, &cbHash) == FALSE ) {
 		return "";
 	}
 
 	ByteArray byteArray = createByteArray((char *)(&aHash[0]), cbHash);
-	ret += Hexify::hexify(byteArray);
+	result += Hexify::hexify(byteArray);
 
-	return ret;
+	return result;
 }
 
 std::string selectCAPICertificate() {
+	const char* certStoreName = "MY";
 
-	const char * cert_store_name = "MY";
-	PCCERT_CONTEXT cert;
-	DWORD store_flags;
-	HCERTSTORE hstore;
-	HWND hwnd;
-
-	store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
-		      CERT_STORE_READONLY_FLAG |
-		      CERT_SYSTEM_STORE_CURRENT_USER;
+	DWORD storeFlags = CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
 
-	hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, store_flags, cert_store_name);
+	HCERTSTORE hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, storeFlags, certStoreName);
 	if (!hstore) {
 		return "";
 	}
 
-
-////Does this handle need to be freed as well?
-	hwnd = GetForegroundWindow();
+	HWND hwnd = GetForegroundWindow();
 	if (!hwnd) {
 		hwnd = GetActiveWindow();
 	}
 
+	std::string certificateDialogTitle = QT_TRANSLATE_NOOP("", "TLS Client Certificate Selection");
+	std::string certificateDialogPrompt = QT_TRANSLATE_NOOP("", "Select a certificate to use for authentication");
+
+	int titleLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogTitle.c_str(), -1, NULL, 0);
+	int promptLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogPrompt.c_str(), -1, NULL, 0);
+
+	wchar_t* titleChars = new wchar_t[titleLength];
+	wchar_t* promptChars = new wchar_t[promptLength];
+
+	//titleChars[titleLength] = '\0';
+	//promptChars[promptLength] = '\0';
+
+	titleLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogTitle.c_str(), -1, titleChars, titleLength);
+	promptLength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, certificateDialogPrompt.c_str(), -1, promptChars, promptLength);
+
+	if (titleLength == 0 || promptLength == 0) {
+		int error = GetLastError();
+		switch (error) {
+			case ERROR_INSUFFICIENT_BUFFER: SWIFT_LOG("error") << "Insufficient buffer for rendering cert dialog" << std::endl;break;
+			case ERROR_INVALID_FLAGS: SWIFT_LOG("error") << "Invalid flags for rendering cert dialog" << std::endl;break;
+			case ERROR_INVALID_PARAMETER: SWIFT_LOG("error") << "Invalid parameter for rendering cert dialog" << std::endl;break;
+			case ERROR_NO_UNICODE_TRANSLATION: SWIFT_LOG("error") << "Invalid unicode for rendering cert dialog" << std::endl;break;
+			default: SWIFT_LOG("error") << "Unexpected multibyte conversion errorcode" << std::endl;
+
+		}
+	}
+
+	
+
 	/* Call Windows dialog to select a suitable certificate */
-	cert = CryptUIDlgSelectCertificateFromStore(hstore,
-						  hwnd,
-						  cert_dlg_title,
-						  cert_dlg_prompt,
-						  exclude_columns,
-						  0,
-						  NULL);
+	PCCERT_CONTEXT cert = CryptUIDlgSelectCertificateFromStore(hstore, hwnd, titleChars, promptChars, exclude_columns, 0, NULL);
+
+	delete[] titleChars;
+	delete[] promptChars;
 
 	if (hstore) {
 		CertCloseStore(hstore, 0);
 	}
 
-	if (cert) {
-		std::string ret = getCertUri(cert, cert_store_name);
+	std::string result;
 
+	if (cert) {
+		result = getCertUri(cert, certStoreName);
 		CertFreeCertificateContext(cert);
-
-		return ret;
-	} else {
-		return "";
 	}
+
+	return result;
 }
 
 bool isCAPIURI(std::string uri) {
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index 0622cc6..0971577 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -41,7 +41,6 @@ if myenv.get("HAVE_SNARL", False) :
 	myenv.Append(CPPDEFINES = ["HAVE_SNARL"])
 if env["PLATFORM"] == "win32" :
 	myenv.Append(LIBS = ["cryptui"])
-	myenv.Append(LIBS = ["Winscard"])
 myenv.UseFlags(myenv["PLATFORM_FLAGS"])
 
 myenv.Tool("qt4", toolpath = ["#/BuildTools/SCons/Tools"])
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 45d80aa..8a922ba 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -223,7 +223,7 @@ void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
 				case TLSError::CertificateCardRemoved:
 					clientError = ClientError(ClientError::CertificateCardRemoved);
 					break;
-				default:
+				case TLSError::UnknownError:
 					clientError = ClientError(ClientError::TLSError);
 					break;
 			}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 41ec947..6308a80 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -43,6 +43,10 @@ if env["SCONS_STAGE"] == "flags" :
 			dep_env.UseFlags(env.get(module + "_FLAGS", {}))
 	dep_env.UseFlags(dep_env["PLATFORM_FLAGS"])
 
+	if env.get("HAVE_SCHANNEL", 0) :
+		dep_env.Append(LIBS = ["Winscard"])
+
+
 	for var, e in [("SWIFTEN_FLAGS", swiften_env), ("SWIFTEN_DEP_FLAGS", dep_env)] : 
 		env[var] = {
 				"CPPDEFINES": e.get("CPPDEFINES", []),
diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp
index b33ebcf..0083b6f 100644
--- a/Swiften/TLS/CAPICertificate.cpp
+++ b/Swiften/TLS/CAPICertificate.cpp
@@ -3,31 +3,35 @@
  * Licensed under the simplified BSD license.
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
+
 #pragma once
 
 #include <Swiften/Network/TimerFactory.h>
 #include <Swiften/TLS/CAPICertificate.h>
 #include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Base/Log.h>
 
 #include <boost/bind.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 
 // Size of the SHA1 hash
-#define SHA1_HASH_LEN                20
+#define SHA1_HASH_LEN 20
 
 
 namespace Swift {
 
-CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory)
-	: valid_(false),
-	uri_(capiUri),
-	certStoreHandle_(0),
-	scardContext_(0),
-	cardHandle_(0),
-	certStore_(),
-	certName_(),
-	smartCardReaderName_(),
-	timerFactory_(timerFactory) {
+CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory) : 
+		valid_(false), 
+		uri_(capiUri),
+		certStoreHandle_(0),
+		scardContext_(0),
+		cardHandle_(0),
+		certStore_(),
+		certName_(),
+		smartCardReaderName_(),
+		timerFactory_(timerFactory),
+		lastPollingResult_(true) {
+	assert(timerFactory_);
 
 	setUri(capiUri);
 }
@@ -69,19 +73,11 @@ const std::string& CAPICertificate::getSmartCardReaderName() const {
 }
 
 PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName) {
-	PCCERT_CONTEXT pCertContext = NULL;
-
 	if (!boost::iequals(certName.substr(0, 5), "sha1:")) {
 
 		// Find client certificate. Note that this sample just searches for a
 		// certificate that contains the user name somewhere in the subject name.
-		pCertContext = CertFindCertificateInStore(certStoreHandle,
-				X509_ASN_ENCODING,
-				0,				// dwFindFlags
-				CERT_FIND_SUBJECT_STR_A,
-				certName.c_str(),		// *pvFindPara
-				NULL );				// pPrevCertContext
-		return pCertContext;
+		return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /*dwFindFlags*/ 0, CERT_FIND_SUBJECT_STR_A, /* *pvFindPara*/certName.c_str(), /*pPrevCertContext*/ NULL);
 	}
 
 
@@ -97,19 +93,12 @@ PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::st
 
 	// Find client certificate. Note that this sample just searches for a
 	// certificate that contains the user name somewhere in the subject name.
-	pCertContext = CertFindCertificateInStore(certStoreHandle,
-			X509_ASN_ENCODING,
-			0,				// dwFindFlags
-			CERT_FIND_HASH,
-			&HashBlob,
-			NULL );				// pPrevCertContext
-
-	return pCertContext;
+	return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /* dwFindFlags */ 0, CERT_FIND_HASH, &HashBlob, /* pPrevCertContext */ NULL);
+
 }
 
 
 void CAPICertificate::setUri (const std::string& capiUri) {
-
 	valid_ = false;
 
 	/* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */
@@ -119,41 +108,39 @@ void CAPICertificate::setUri (const std::string& capiUri) {
 	}
 
 	/* Substring of subject: uses "storename" */
-	std::string capi_identity = capiUri.substr(10);
-	std::string new_certStore_name;
-	size_t pos = capi_identity.find_first_of (':');
+	std::string capiIdentity = capiUri.substr(10);
+	std::string newCertStoreName;
+	size_t pos = capiIdentity.find_first_of (':');
 
 	if (pos == std::string::npos) {
 		/* Using the default certificate store */
-		new_certStore_name = "MY";
-		certName_ = capi_identity;
+		newCertStoreName = "MY";
+		certName_ = capiIdentity;
 	}
 	else {
-		new_certStore_name = capi_identity.substr(0, pos);
-		certName_ = capi_identity.substr(pos + 1);
+		newCertStoreName = capiIdentity.substr(0, pos);
+		certName_ = capiIdentity.substr(pos + 1);
 	}
 
-	PCCERT_CONTEXT pCertContext = NULL;
-
 	if (certStoreHandle_ != NULL) {
-		if (new_certStore_name != certStore_) {
+		if (newCertStoreName != certStore_) {
 			CertCloseStore(certStoreHandle_, 0);
 			certStoreHandle_ = NULL;
 		}
 	}
 
 	if (certStoreHandle_ == NULL) {
-		certStoreHandle_ = CertOpenSystemStore(0, new_certStore_name.c_str());
+		certStoreHandle_ = CertOpenSystemStore(0, newCertStoreName.c_str());
 		if (!certStoreHandle_) {
 			return;
 		}
 	}
 
-	certStore_ = new_certStore_name;
+	certStore_ = newCertStoreName;
 
-	pCertContext = findCertificateInStore (certStoreHandle_, certName_);
+	PCCERT_CONTEXT certContext = findCertificateInStore (certStoreHandle_, certName_);
 
-	if (!pCertContext) {
+	if (!certContext) {
 		return;
 	}
 
@@ -165,61 +152,50 @@ void CAPICertificate::setUri (const std::string& capiUri) {
 	HCRYPTPROV hprov;
 	HCRYPTKEY key;
 
-	if (!CertGetCertificateContextProperty(pCertContext,
+	if (!CertGetCertificateContextProperty(certContext,
 			CERT_KEY_PROV_INFO_PROP_ID,
 			NULL,
 			&len)) {
-		CertFreeCertificateContext(pCertContext);
+		CertFreeCertificateContext(certContext);
 		return;
 	}
 
 	pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len));
 	if (!pinfo) {
-		CertFreeCertificateContext(pCertContext);
+		CertFreeCertificateContext(certContext);
 		return;
 	}
 
-	if (!CertGetCertificateContextProperty(pCertContext,
-			CERT_KEY_PROV_INFO_PROP_ID,
-			pinfo,
-			&len)) {
-		CertFreeCertificateContext(pCertContext);
+	if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) {
+		CertFreeCertificateContext(certContext);
 		free(pinfo);
 		return;
 	}
 
-	CertFreeCertificateContext(pCertContext);
+	CertFreeCertificateContext(certContext);
 
 	// Now verify if we have access to the private key
-	if (!CryptAcquireContextW(&hprov,
-			pinfo->pwszContainerName,
-			pinfo->pwszProvName,
-			pinfo->dwProvType,
-			0)) {
+	if (!CryptAcquireContextW(&hprov, pinfo->pwszContainerName, pinfo->pwszProvName, pinfo->dwProvType, 0)) {
 		free(pinfo);
 		return;
 	}
 
 
-	char smartcard_reader[1024];
-	DWORD buflen;
-
-	buflen = sizeof(smartcard_reader);
-	if (!CryptGetProvParam(hprov, PP_SMARTCARD_READER, (BYTE *)&smartcard_reader, &buflen, 0)) {
-		DWORD error;
-
-		error = GetLastError();
+	char smartCardReader[1024];
+	DWORD bufferLength = sizeof(smartCardReader);
+	if (!CryptGetProvParam(hprov, PP_SMARTCARD_READER, (BYTE *)&smartCardReader, &bufferLength, 0)) {
+		DWORD error = GetLastError();
 		smartCardReaderName_ = "";
-	} else {
-		LONG       lRet;
-
-		smartCardReaderName_ = smartcard_reader;
+	}
+	else {
+		smartCardReaderName_ = smartCardReader;
 
-		lRet = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scardContext_);
-		if (SCARD_S_SUCCESS == lRet) {
+		LONG result = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scardContext_);
+		if (SCARD_S_SUCCESS == result) {
 			// Initiate monitoring for smartcard ejection
-			smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQ);
-		} else {
+			smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS);
+		}
+		else {
 			///Need to handle an error here
 		}
 	}
@@ -242,125 +218,115 @@ void CAPICertificate::setUri (const std::string& capiUri) {
 	valid_ = true;
 }
 
-static void smartcard_check_status (SCARDCONTEXT  hContext,
-				    const char * pReader,
-				    SCARDHANDLE hCardHandle,     // Can be 0 on the first call
-				    SCARDHANDLE * newCardHandle, // The handle returned
-				    DWORD * pdwState) {
-	LONG            lReturn;
-	DWORD           dwAP;
-	char            szReader[200];
-	DWORD           cch = sizeof(szReader);
-	BYTE            bAttr[32];
-	DWORD           cByte = 32;
-
+static void smartcard_check_status (SCARDCONTEXT hContext,
+		const char* pReader,
+		SCARDHANDLE hCardHandle, /* Can be 0 on the first call */
+		SCARDHANDLE* newCardHandle, /* The handle returned */
+		DWORD* pdwState) {
 	if (hCardHandle == 0) {
-		lReturn = SCardConnect(hContext,
-					pReader,
-					SCARD_SHARE_SHARED,
-					SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
-					&hCardHandle,
-					&dwAP);
-		if ( SCARD_S_SUCCESS != lReturn ) {
+		DWORD dwAP;
+		LONG result = SCardConnect(hContext, pReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCardHandle, &dwAP);
+		if (SCARD_S_SUCCESS != result) {
 			hCardHandle = 0;
-			if (SCARD_E_NO_SMARTCARD == lReturn || SCARD_W_REMOVED_CARD == lReturn) {
+			if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) {
 				*pdwState = SCARD_ABSENT;
-			} else {
+			}
+			else {
 				*pdwState = SCARD_UNKNOWN;
 			}
-			goto done;
+
+			if (newCardHandle == NULL) {
+				(void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD);
+				hCardHandle = 0;
+			}
+			else {
+				*newCardHandle = hCardHandle;
+			}
 		}
 	}
 
-	lReturn = SCardStatus(hCardHandle,
-				szReader,	// Unfortunately we can't use NULL here
-				&cch,
-				pdwState,
-				NULL,
-				(LPBYTE)&bAttr,
-				&cByte);
+	char szReader[200];
+	DWORD cch = sizeof(szReader);
+	BYTE bAttr[32];
+	DWORD cByte = 32;
+	LONG result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte);
 
-	if ( SCARD_S_SUCCESS != lReturn ) {
-		if (SCARD_E_NO_SMARTCARD == lReturn || SCARD_W_REMOVED_CARD == lReturn) {
+	if (SCARD_S_SUCCESS != result) {
+		if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) {
 			*pdwState = SCARD_ABSENT;
-		} else {
+		}
+		else {
 			*pdwState = SCARD_UNKNOWN;
 		}
 	}
 
-done:
 	if (newCardHandle == NULL) {
 		(void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD);
 		hCardHandle = 0;
-	} else {
+	}
+	else {
 		*newCardHandle = hCardHandle;
 	}
 }
 
 bool CAPICertificate::checkIfSmartCardPresent () {
-
-	DWORD dwState;
-
 	if (!smartCardReaderName_.empty()) {
-		smartcard_check_status (scardContext_,
-					smartCardReaderName_.c_str(),
-					cardHandle_,
-					&cardHandle_,
-					&dwState);
-////DEBUG
-		switch ( dwState ) {
-		case SCARD_ABSENT:
-		    printf("Card absent.\n");
-		    break;
-		case SCARD_PRESENT:
-		    printf("Card present.\n");
-		    break;
-		case SCARD_SWALLOWED:
-		    printf("Card swallowed.\n");
-		    break;
-		case SCARD_POWERED:
-		    printf("Card has power.\n");
-		    break;
-		case SCARD_NEGOTIABLE:
-		    printf("Card reset and waiting PTS negotiation.\n");
-		    break;
-		case SCARD_SPECIFIC:
-		    printf("Card has specific communication protocols set.\n");
-		    break;
-		default:
-		    printf("Unknown or unexpected card state.\n");
-		    break;
+		DWORD dwState;
+		smartcard_check_status(scardContext_, smartCardReaderName_.c_str(), cardHandle_, &cardHandle_, &dwState);
+
+		switch (dwState) {
+			case SCARD_ABSENT:
+				SWIFT_LOG("DEBUG") << "Card absent." << std::endl;
+				break;
+			case SCARD_PRESENT:
+				SWIFT_LOG("DEBUG") << "Card present." << std::endl;
+				break;
+			case SCARD_SWALLOWED:
+				SWIFT_LOG("DEBUG") << "Card swallowed." << std::endl;
+				break;
+			case SCARD_POWERED:
+				SWIFT_LOG("DEBUG") << "Card has power." << std::endl;
+				break;
+			case SCARD_NEGOTIABLE:
+				SWIFT_LOG("DEBUG") << "Card reset and waiting PTS negotiation." << std::endl;
+				break;
+			case SCARD_SPECIFIC:
+				SWIFT_LOG("DEBUG") << "Card has specific communication protocols set." << std::endl;
+				break;
+			default:
+				SWIFT_LOG("DEBUG") << "Unknown or unexpected card state." << std::endl;
+				break;
 		}
 
 
 
-		switch ( dwState ) {
-		case SCARD_ABSENT:
-		    return false;
+		switch (dwState) {
+			case SCARD_ABSENT:
+				return false;
 
-		case SCARD_PRESENT:
-		case SCARD_SWALLOWED:
-		case SCARD_POWERED:
-		case SCARD_NEGOTIABLE:
-		case SCARD_SPECIFIC:
-		    return true;
+			case SCARD_PRESENT:
+			case SCARD_SWALLOWED:
+			case SCARD_POWERED:
+			case SCARD_NEGOTIABLE:
+			case SCARD_SPECIFIC:
+				return true;
 
-		default:
-		    return false;
+			default:
+				return false;
 		}
-	} else {
+	}
+	else {
 		return false;
 	}
 }
 
 void CAPICertificate::handleSmartCardTimerTick() {
-
-	if (checkIfSmartCardPresent() == false) {
-		smartCardTimer_->stop();
+	bool poll = checkIfSmartCardPresent();
+	if (lastPollingResult_ && !poll) {
 		onCertificateCardRemoved();
-	} else {
-		smartCardTimer_->start();
-	}
+	} 
+	lastPollingResult_ = poll;
+	smartCardTimer_->start();
 }
 
 }
diff --git a/Swiften/TLS/CAPICertificate.h b/Swiften/TLS/CAPICertificate.h
index c8c00fe..5f24b7e 100644
--- a/Swiften/TLS/CAPICertificate.h
+++ b/Swiften/TLS/CAPICertificate.h
@@ -16,15 +16,13 @@
 #include <WinCrypt.h>
 #include <Winscard.h>
 
-/* In ms */
-#define SMARTCARD_EJECTION_CHECK_FREQ	1000
+#define SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS	1000
 
 namespace Swift {
 	class TimerFactory;
 
 	class CAPICertificate : public Swift::CertificateWithKey {
 		public:
-////Allow timerFactory to be NULL?
 			CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory);
 
 			virtual ~CAPICertificate();
@@ -61,6 +59,8 @@ namespace Swift {
 			std::string smartCardReaderName_;
 			boost::shared_ptr<Timer> smartCardTimer_;
 			TimerFactory* timerFactory_;
+
+			bool lastPollingResult_;
 	};
 
 PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName);
diff --git a/Swiften/TLS/SConscript b/Swiften/TLS/SConscript
index 0e95b8b..fb327b9 100644
--- a/Swiften/TLS/SConscript
+++ b/Swiften/TLS/SConscript
@@ -19,6 +19,7 @@ if myenv.get("HAVE_OPENSSL", 0) :
 		])
 	myenv.Append(CPPDEFINES = "HAVE_OPENSSL")
 elif myenv.get("HAVE_SCHANNEL", 0) :
+	swiften_env.Append(LIBS = ["Winscard"])
 	objects += myenv.StaticObject([
 			"CAPICertificate.cpp",
 			"Schannel/SchannelContext.cpp",
diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp
index 8e952ea..6169ad7 100644
--- a/Swiften/TLS/Schannel/SchannelContext.cpp
+++ b/Swiften/TLS/Schannel/SchannelContext.cpp
@@ -4,79 +4,69 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
 #include <boost/bind.hpp>
 
 #include <Swiften/TLS/Schannel/SchannelContext.h>
 #include <Swiften/TLS/Schannel/SchannelCertificate.h>
 #include <Swiften/TLS/CAPICertificate.h>
-#include <WinHTTP.h> // For SECURITY_FLAG_IGNORE_CERT_CN_INVALID
+#include <WinHTTP.h> /* For SECURITY_FLAG_IGNORE_CERT_CN_INVALID */
 
 namespace Swift {
 
 //------------------------------------------------------------------------
 
-SchannelContext::SchannelContext() 
-: m_state(Start)
-, m_secContext(0)
-, m_my_cert_store(NULL)
-, m_cert_store_name("MY")
-, m_cert_name()
-, m_smartcard_reader()
-{
-	m_ctxtFlags = ISC_REQ_ALLOCATE_MEMORY | 
-				  ISC_REQ_CONFIDENTIALITY |
-				  ISC_REQ_EXTENDED_ERROR  |
-				  ISC_REQ_INTEGRITY		  |
-				  ISC_REQ_REPLAY_DETECT   |	
-				  ISC_REQ_SEQUENCE_DETECT |
-				  ISC_REQ_USE_SUPPLIED_CREDS |
-				  ISC_REQ_STREAM;
+SchannelContext::SchannelContext() : m_state(Start), m_secContext(0), m_my_cert_store(NULL), m_cert_store_name("MY"), m_cert_name(), m_smartcard_reader() {
+	m_ctxtFlags = ISC_REQ_ALLOCATE_MEMORY |
+				ISC_REQ_CONFIDENTIALITY |
+				ISC_REQ_EXTENDED_ERROR |
+				ISC_REQ_INTEGRITY |
+				ISC_REQ_REPLAY_DETECT |
+				ISC_REQ_SEQUENCE_DETECT |
+				ISC_REQ_USE_SUPPLIED_CREDS |
+				ISC_REQ_STREAM;
 
 	ZeroMemory(&m_streamSizes, sizeof(m_streamSizes));
 }
 
 //------------------------------------------------------------------------
 
-SchannelContext::~SchannelContext()
-{
+SchannelContext::~SchannelContext() {
 	if (m_my_cert_store) CertCloseStore(m_my_cert_store, 0);
 }
 
 //------------------------------------------------------------------------
 
-void SchannelContext::determineStreamSizes()
-{
+void SchannelContext::determineStreamSizes() {
 	QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_STREAM_SIZES, &m_streamSizes);
 }
 
 //------------------------------------------------------------------------
 
-void SchannelContext::connect() 
-{
+void SchannelContext::connect() {
 	ScopedCertContext pCertContext;
 
 	m_state = Connecting;
 
 	// If a user name is specified, then attempt to find a client
 	// certificate. Otherwise, just create a NULL credential.
-	if (!m_cert_name.empty())
-	{
-		if (m_my_cert_store == NULL)
-		{
+	if (!m_cert_name.empty()) {
+		if (m_my_cert_store == NULL) {
 			m_my_cert_store = CertOpenSystemStore(0, m_cert_store_name.c_str());
-			if (!m_my_cert_store)
-			{
-/////			printf( "**** Error 0x%x returned by CertOpenSystemStore\n", GetLastError() );
-				indicateError();
+			if (!m_my_cert_store) {
+				indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 				return;
 			}
 		}
 
 		pCertContext = findCertificateInStore( m_my_cert_store, m_cert_name );
-		if (pCertContext == NULL)
-		{
-/////		printf("**** Error 0x%x returned by CertFindCertificateInStore\n", GetLastError());
-			indicateError();
+		if (pCertContext == NULL) {
+			indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 			return;
 		}
 	}
@@ -91,17 +81,15 @@ void SchannelContext::connect()
 	sc.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
 	sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
 
-	if (pCertContext)
-	{
+	if (pCertContext) {
 		sc.cCreds = 1;
 		sc.paCred = pCertContext.GetPointer();
 		sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
 	}
-	else
-	{
-		sc.cCreds = 0; // Let Crypto API find the appropriate certificate for us
+	else {
+		sc.cCreds = 0;
 		sc.paCred = clientCerts;
-		sc.dwFlags |= SCH_CRED_USE_DEFAULT_CREDS;
+		sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
 	}
 
 	// Swiften performs the server name check for us
@@ -118,10 +106,9 @@ void SchannelContext::connect()
 		m_credHandle.Reset(),
 		NULL);
 	
-	if (status != SEC_E_OK) 
-	{
+	if (status != SEC_E_OK) {
 		// We failed to obtain the credentials handle
-		indicateError();
+		indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 		return;
 	}
 
@@ -161,22 +148,21 @@ void SchannelContext::connect()
 		&m_secContext,
 		NULL);
 
-	if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) 
-	{
+	if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
 		// We failed to initialize the security context
 		handleCertError(status);
-		indicateError();
+		indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 		return;
 	}
 
 	// Start the handshake
 	sendDataOnNetwork(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer);
 
-	if (status == SEC_E_OK) 
-	{
+	if (status == SEC_E_OK) {
 		status = validateServerCertificate();
-		if (status != SEC_E_OK)
+		if (status != SEC_E_OK) {
 			handleCertError(status);
+		}
 
 		m_state = Connected;
 		determineStreamSizes();
@@ -187,11 +173,11 @@ void SchannelContext::connect()
 
 //------------------------------------------------------------------------
 
-SECURITY_STATUS SchannelContext::validateServerCertificate()
-{
+SECURITY_STATUS SchannelContext::validateServerCertificate() {
 	SchannelCertificate::ref pServerCert = boost::dynamic_pointer_cast<SchannelCertificate>( getPeerCertificate() );
-	if (!pServerCert)
+	if (!pServerCert) {
 		return SEC_E_WRONG_PRINCIPAL;
+	}
 
 	const LPSTR usage[] = 
 	{
@@ -220,8 +206,9 @@ SECURITY_STATUS SchannelContext::validateServerCertificate()
 		NULL,
 		pChainContext.Reset());
 
-	if (!success)
+	if (!success) {
 		return GetLastError();
+	}
 
 	SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslChainPolicy = {0};
 	sslChainPolicy.cbSize = sizeof(sslChainPolicy);
@@ -242,34 +229,31 @@ SECURITY_STATUS SchannelContext::validateServerCertificate()
 		CERT_CHAIN_POLICY_SSL,
 		pChainContext,
 		&certChainPolicy,
-		&certChainPolicyStatus))
-	{
+		&certChainPolicyStatus)) {
 		return GetLastError();
 	}
 
-	if (certChainPolicyStatus.dwError != S_OK)
+	if (certChainPolicyStatus.dwError != S_OK) {
 		return certChainPolicyStatus.dwError;
+	}
 
 	return S_OK;
 }
 
 //------------------------------------------------------------------------
 
-void SchannelContext::appendNewData(const SafeByteArray& data)
-{
+void SchannelContext::appendNewData(const SafeByteArray& data) {
 	size_t originalSize = m_receivedData.size();
-	m_receivedData.resize( originalSize + data.size() );
-	memcpy( &m_receivedData[0] + originalSize, &data[0], data.size() );
+	m_receivedData.resize(originalSize + data.size());
+	memcpy(&m_receivedData[0] + originalSize, &data[0], data.size());
 }
 
 //------------------------------------------------------------------------
 
-void SchannelContext::continueHandshake(const SafeByteArray& data) 
-{
+void SchannelContext::continueHandshake(const SafeByteArray& data) {
 	appendNewData(data);
 
-	while (!m_receivedData.empty())
-	{
+	while (!m_receivedData.empty()) {
 		SecBuffer inBuffers[2];
 
 		// Provide Schannel with the remote host's handshake data
@@ -321,49 +305,51 @@ void SchannelContext::continueHandshake(const SafeByteArray& data)
 			&m_secContext,
 			NULL);
 
-		if (status == SEC_E_INCOMPLETE_MESSAGE)	
-		{
+		if (status == SEC_E_INCOMPLETE_MESSAGE)	{
 			// Wait for more data to arrive
 			break;
 		}
-		else if (status == SEC_I_CONTINUE_NEEDED) 
-		{
+		else if (status == SEC_I_CONTINUE_NEEDED) {
 			SecBuffer* pDataBuffer = &outBuffers[0];
 			SecBuffer* pExtraBuffer = &inBuffers[1];
 			
-			if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL)
+			if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) {
 				sendDataOnNetwork(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
+			}
 
-			if (pExtraBuffer->BufferType == SECBUFFER_EXTRA)
+			if (pExtraBuffer->BufferType == SECBUFFER_EXTRA) {
 				m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
-			else
+			}
+			else {
 				m_receivedData.clear();
+			}
 
 			break;
 		}
-		else if (status == SEC_E_OK) 
-		{
+		else if (status == SEC_E_OK)  {
 			status = validateServerCertificate();
-			if (status != SEC_E_OK)
+			if (status != SEC_E_OK) {
 				handleCertError(status);
+			}
 
 			SecBuffer* pExtraBuffer = &inBuffers[1];
 			
-			if (pExtraBuffer && pExtraBuffer->cbBuffer > 0)
+			if (pExtraBuffer && pExtraBuffer->cbBuffer > 0) {
 				m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
-			else
+			}
+			else {
 				m_receivedData.clear();
+			}
 
 			m_state = Connected;
 			determineStreamSizes();
 
 			onConnected();
 		} 
-		else 
-		{
+		else {
 			// We failed to initialize the security context
 			handleCertError(status);
-			indicateError();
+			indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 			return;
 		}
 	}
@@ -377,45 +363,36 @@ void SchannelContext::handleCertError(SECURITY_STATUS status)
 		status == CERT_E_UNTRUSTEDROOT			||
 		status == CRYPT_E_ISSUER_SERIALNUMBER	|| 
 		status == CRYPT_E_SIGNER_NOT_FOUND		||
-		status == CRYPT_E_NO_TRUSTED_SIGNER)
-	{
+		status == CRYPT_E_NO_TRUSTED_SIGNER) {
 		m_verificationError = CertificateVerificationError::Untrusted;
 	}
 	else if (status == SEC_E_CERT_EXPIRED || 
-			 status == CERT_E_EXPIRED)
-	{
+			 status == CERT_E_EXPIRED) {
 		m_verificationError = CertificateVerificationError::Expired;
 	}
-	else if (status == CRYPT_E_SELF_SIGNED)
-	{
+	else if (status == CRYPT_E_SELF_SIGNED) {
 		m_verificationError = CertificateVerificationError::SelfSigned;
 	}
 	else if (status == CRYPT_E_HASH_VALUE	||
-			 status == TRUST_E_CERT_SIGNATURE)
-	{
+			 status == TRUST_E_CERT_SIGNATURE) {
 		m_verificationError = CertificateVerificationError::InvalidSignature;
 	}
-	else if (status == CRYPT_E_REVOKED)
-	{
+	else if (status == CRYPT_E_REVOKED) {
 		m_verificationError = CertificateVerificationError::Revoked;
 	}
 	else if (status == CRYPT_E_NO_REVOCATION_CHECK ||
-			 status == CRYPT_E_REVOCATION_OFFLINE)
-	{
+			 status == CRYPT_E_REVOCATION_OFFLINE) {
 		m_verificationError = CertificateVerificationError::RevocationCheckFailed;
 	}
-	else
-	{
+	else {
 		m_verificationError = CertificateVerificationError::UnknownError;
 	}
 }
 
 //------------------------------------------------------------------------
 
-void SchannelContext::sendDataOnNetwork(const void* pData, size_t dataSize) 
-{
-	if (dataSize > 0 && pData) 
-	{
+void SchannelContext::sendDataOnNetwork(const void* pData, size_t dataSize) {
+	if (dataSize > 0 && pData) {
 		SafeByteArray byteArray(dataSize);
 		memcpy(&byteArray[0], pData, dataSize);
 
@@ -425,8 +402,7 @@ void SchannelContext::sendDataOnNetwork(const void* pData, size_t dataSize)
 
 //------------------------------------------------------------------------
 
-void SchannelContext::forwardDataToApplication(const void* pData, size_t dataSize) 
-{
+void SchannelContext::forwardDataToApplication(const void* pData, size_t dataSize) {
 	SafeByteArray byteArray(dataSize);
 	memcpy(&byteArray[0], pData, dataSize);
 
@@ -435,11 +411,11 @@ void SchannelContext::forwardDataToApplication(const void* pData, size_t dataSiz
 
 //------------------------------------------------------------------------
 
-void SchannelContext::handleDataFromApplication(const SafeByteArray& data) 
-{
+void SchannelContext::handleDataFromApplication(const SafeByteArray& data) {
 	// Don't attempt to send data until we're fully connected
-	if (m_state == Connecting)
+	if (m_state == Connecting) {
 		return;
+	}
 
 	// Encrypt the data
 	encryptAndSendData(data);
@@ -447,10 +423,8 @@ void SchannelContext::handleDataFromApplication(const SafeByteArray& data)
 
 //------------------------------------------------------------------------
 
-void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) 
-{
-	switch (m_state)
-	{
+void SchannelContext::handleDataFromNetwork(const SafeByteArray& data) {
+	switch (m_state) {
 	case Connecting:
 		{
 			// We're still establishing the connection, so continue the handshake
@@ -472,23 +446,20 @@ void SchannelContext::handleDataFromNetwork(const SafeByteArray& data)
 
 //------------------------------------------------------------------------
 
-void SchannelContext::indicateError() 
-{
+void SchannelContext::indicateError(boost::shared_ptr<TLSError> error) {
 	m_state = Error;
 	m_receivedData.clear();
-	onError(boost::make_shared<TLSError>());
+	onError(error);
 }
 
 //------------------------------------------------------------------------
 
-void SchannelContext::decryptAndProcessData(const SafeByteArray& data) 
-{
+void SchannelContext::decryptAndProcessData(const SafeByteArray& data) {
 	SecBuffer inBuffers[4]	= {0};
 
 	appendNewData(data);
 	
-	while (!m_receivedData.empty())
-	{
+	while (!m_receivedData.empty()) {
 		//
 		// MSDN: 
 		//   When using the Schannel SSP with contexts that are not connection oriented, on input, 
@@ -515,49 +486,44 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data)
 		size_t inData = m_receivedData.size();
 		SECURITY_STATUS status = DecryptMessage(m_ctxtHandle, &inBufferDesc, 0, NULL);
 
-		if (status == SEC_E_INCOMPLETE_MESSAGE) 
-		{
+		if (status == SEC_E_INCOMPLETE_MESSAGE) {
 			// Wait for more data to arrive
 			break;
 		} 
-		else if (status == SEC_I_RENEGOTIATE) 
-		{
+		else if (status == SEC_I_RENEGOTIATE) {
 			// TODO: Handle renegotiation scenarios
-			indicateError();
+			indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 			break;
 		} 
-		else if (status == SEC_I_CONTEXT_EXPIRED) 
-		{
-			indicateError();
+		else if (status == SEC_I_CONTEXT_EXPIRED) {
+			indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 			break;
 		} 
-		else if (status != SEC_E_OK) 
-		{
-			indicateError();
+		else if (status != SEC_E_OK) {
+			indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 			break;
 		}
 
 		SecBuffer* pDataBuffer = NULL;
 		SecBuffer* pExtraBuffer = NULL;
-		for (int i = 0; i < 4; ++i) 
-		{
-			if (inBuffers[i].BufferType == SECBUFFER_DATA)
+		for (int i = 0; i < 4; ++i) {
+			if (inBuffers[i].BufferType == SECBUFFER_DATA) {
 				pDataBuffer = &inBuffers[i];
-
-			else if (inBuffers[i].BufferType == SECBUFFER_EXTRA)
+			}
+			else if (inBuffers[i].BufferType == SECBUFFER_EXTRA) {
 				pExtraBuffer = &inBuffers[i];
+			}
 		}
 
-		if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL)
+		if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL) {
 			forwardDataToApplication(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
+		}
 
 		// If there is extra data left over from the decryption operation, we call DecryptMessage() again
-		if (pExtraBuffer) 
-		{
+		if (pExtraBuffer) {
 			m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
 		} 
-		else 
-		{
+		else {
 			// We're done
 			m_receivedData.erase(m_receivedData.begin(), m_receivedData.begin() + inData);
 		}
@@ -566,10 +532,10 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data)
 
 //------------------------------------------------------------------------
 
-void SchannelContext::encryptAndSendData(const SafeByteArray& data) 
-{	
-	if (m_streamSizes.cbMaximumMessage == 0)
+void SchannelContext::encryptAndSendData(const SafeByteArray& data) {
+	if (m_streamSizes.cbMaximumMessage == 0) {
 		return;
+	}
 
 	SecBuffer outBuffers[4]	= {0};
 
@@ -583,8 +549,7 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data)
 	sendBuffer.resize(m_streamSizes.cbHeader + messageBufferSize + m_streamSizes.cbTrailer);
 
 	size_t bytesSent = 0;
-	do 
-	{
+	do {
 		size_t bytesLeftToSend = data.size() - bytesSent;
 
 		// Calculate how much of the send buffer we'll be using for this chunk
@@ -617,9 +582,8 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data)
 		outBufferDesc.ulVersion  = SECBUFFER_VERSION;
 
 		SECURITY_STATUS status = EncryptMessage(m_ctxtHandle, 0, &outBufferDesc, 0);
-		if (status != SEC_E_OK) 
-		{
-			indicateError();
+		if (status != SEC_E_OK) {
+			indicateError(boost::make_shared<TLSError>(TLSError::UnknownError));
 			return;
 		}
 
@@ -631,13 +595,14 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data)
 
 //------------------------------------------------------------------------
 
-bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate)
-{
+bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate) {
 	boost::shared_ptr<CAPICertificate> capiCertificate = boost::dynamic_pointer_cast<CAPICertificate>(certificate);
 	if (!capiCertificate || capiCertificate->isNull()) {
 		return false;
 	}
 
+	userCertificate = capiCertificate;
+
 	// We assume that the Certificate Store Name/Certificate Name
 	// are valid at this point
 	m_cert_store_name = capiCertificate->getCertStoreName();
@@ -652,41 +617,26 @@ bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate)
 
 //------------------------------------------------------------------------
 void SchannelContext::handleCertificateCardRemoved() {
-	//ToDo: Might want to log the reason ("certificate card ejected")
-	indicateError();
+	indicateError(boost::make_shared<TLSError>(TLSError::CertificateCardRemoved));
 }
 
 //------------------------------------------------------------------------
 
-Certificate::ref SchannelContext::getPeerCertificate() const 
-{
-	SchannelCertificate::ref pCertificate;
-
+Certificate::ref SchannelContext::getPeerCertificate() const {
 	ScopedCertContext pServerCert;
 	SECURITY_STATUS status = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset());
-	if (status != SEC_E_OK)
-		return pCertificate;
-
-	pCertificate.reset( new SchannelCertificate(pServerCert) );
-	return pCertificate;
+	return status == SEC_E_OK ? boost::make_shared<SchannelCertificate>(pServerCert) : SchannelCertificate::ref();
 }
 
 //------------------------------------------------------------------------
 
-CertificateVerificationError::ref SchannelContext::getPeerCertificateVerificationError() const 
-{
-	boost::shared_ptr<CertificateVerificationError> pCertError;
-
-	if (m_verificationError)
-		pCertError.reset( new CertificateVerificationError(*m_verificationError) );
-	
-	return pCertError;
+CertificateVerificationError::ref SchannelContext::getPeerCertificateVerificationError() const {
+	return m_verificationError ? boost::make_shared<CertificateVerificationError>(*m_verificationError) : CertificateVerificationError::ref();
 }
 
 //------------------------------------------------------------------------
 
-ByteArray SchannelContext::getFinishMessage() const
-{
+ByteArray SchannelContext::getFinishMessage() const {
 	// TODO: Implement
 
 	ByteArray emptyArray;
diff --git a/Swiften/TLS/Schannel/SchannelContext.h b/Swiften/TLS/Schannel/SchannelContext.h
index bce7415..7c2601b 100644
--- a/Swiften/TLS/Schannel/SchannelContext.h
+++ b/Swiften/TLS/Schannel/SchannelContext.h
@@ -4,14 +4,21 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
 #pragma once
 
-#include "Swiften/Base/boost_bsignals.h"
+#include <Swiften/Base/boost_bsignals.h>
 
-#include "Swiften/TLS/TLSContext.h"
-#include "Swiften/TLS/Schannel/SchannelUtil.h"
-#include "Swiften/TLS/CertificateWithKey.h"
-#include "Swiften/Base/ByteArray.h"
+#include <Swiften/TLS/TLSContext.h>
+#include <Swiften/TLS/Schannel/SchannelUtil.h>
+#include <Swiften/TLS/CertificateWithKey.h>
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/TLS/TLSError.h>
 
 #define SECURITY_WIN32
 #include <Windows.h>
@@ -23,6 +30,7 @@
 
 namespace Swift 
 {	
+	class CAPICertificate;
 	class SchannelContext : public TLSContext, boost::noncopyable 
 	{
 	public:
@@ -50,7 +58,9 @@ namespace Swift
 	private:
 		void			determineStreamSizes();
 		void			continueHandshake(const SafeByteArray& data);
-		void			indicateError();
+		void			indicateError(boost::shared_ptr<TLSError> error);
+		//FIXME: Remove
+		void indicateError() {indicateError(boost::make_shared<TLSError>());}
 		void			handleCertError(SECURITY_STATUS status) ;
 
 		void			sendDataOnNetwork(const void* pData, size_t dataSize);
@@ -90,5 +100,6 @@ namespace Swift
 		std::string		m_cert_name;
 ////Not needed, most likely
 		std::string		m_smartcard_reader;	//Can be empty string for non SmartCard certificates
+		boost::shared_ptr<CAPICertificate> userCertificate;
 	};
 }
-- 
cgit v0.10.2-6-g49f6