VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/SCardManager.cpp
blob: 40578d39ebf6714135d6be7d6a56716f1f17ab30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "SCardManager.h"
#include "PCSCException.h"

namespace VeraCrypt
{
	shared_ptr<SCardLoader> SCardManager::loader = make_shared<SCardLoader>();

	SCardManager::SCardManager()
	{
		loader->Initialize();
	}

	SCardManager::~SCardManager()
	{
		loader->Finalize();
	}

	vector<wstring> SCardManager::GetReaders()
	{
		vector<wstring> readers;
		LPTSTR mszReaders = NULL;
		LPTSTR ptr = NULL;
		DWORD dwReaders = 0;
		SCARDCONTEXT hScardContext = 0;
		LONG lRet = SCARD_S_SUCCESS;

		hScardContext = loader->GetSCardContext();
		lRet = loader->SCardIsValidContext(hScardContext);
		if (SCARD_S_SUCCESS != lRet)
		{
			loader->SCardReleaseContext(hScardContext);
			lRet = loader->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hScardContext);
			if (lRet != SCARD_S_SUCCESS)
				throw PCSCException(lRet);
		}

#ifdef SCARD_AUTOALLOCATE
		dwReaders = SCARD_AUTOALLOCATE;
		lRet = loader->SCardListReaders(hScardContext, NULL, (LPTSTR)&mszReaders, &dwReaders);
#else
		lRet = loader->SCardListReaders(hScardContext, NULL, NULL, &dwReaders);
		if (lRet == SCARD_S_SUCCESS)
		{
			mszReaders = (LPTSTR)calloc(dwReaders, sizeof(char));
			lRet = loader->SCardListReaders(hScardContext, NULL, mszReaders, &dwReaders);
		}
#endif

		if (lRet == SCARD_S_SUCCESS && !mszReaders)
		{
			lRet = SCARD_E_NO_READERS_AVAILABLE;
		}
		if (lRet == SCARD_E_NO_READERS_AVAILABLE)
		{
			readers.clear();
			lRet = SCARD_S_SUCCESS;
		}

		if (lRet == SCARD_S_SUCCESS && mszReaders)
		{
			ptr = mszReaders;
			while (*ptr)
			{
#ifdef TC_WINDOWS
				readers.push_back(ptr);
#else
				readers.push_back(StringConverter::ToWide(ptr));
#endif
				ptr += 
#ifdef TC_WINDOWS
				wcslen(ptr) + 1;
#else
				strlen(ptr) + 1;
#endif
			}

#ifdef SCARD_AUTOALLOCATE
			loader->SCardFreeMemory(hScardContext, mszReaders);
#else
			free(mszReaders);
#endif
		}

		if (lRet != SCARD_S_SUCCESS)
			throw PCSCException(lRet);

		return readers;
	}

	shared_ptr<SCardReader> SCardManager::GetReader(size_t readerNumber)
	{
		vector<wstring> readers;
		shared_ptr<SCardReader> smartCardReader;

		loader->Initialize();

		readers = GetReaders();
		if (readerNumber < readers.size())
		{
			smartCardReader = make_shared<SCardReader>(readers[readerNumber], loader);
			if (smartCardReader)
			{
				return smartCardReader;
			}
		}

		throw InvalidEMVPath();
	}
}