FreeRDP
test-scard.cpp
1 
27 #include <iostream>
28 #include <string>
29 #include <sstream>
30 #include <locale>
31 #include <codecvt>
32 
33 #include <comdef.h>
34 #include <winscard.h>
35 
36 static const WCHAR* listW[] = { nullptr, L"SCard$AllReaders\000", L"SCard$DefaultReaders\000",
37  L"SCard$LocalReaders\000", L"SCard$SystemReaders\000" };
38 static const char* listA[] = { nullptr, "SCard$AllReaders\000", "SCard$DefaultReaders\000",
39  "SCard$LocalReaders\000", "SCard$SystemReaders\000" };
40 
41 static std::string scope2str(DWORD scope)
42 {
43  switch (scope)
44  {
45  case SCARD_SCOPE_USER:
46  return "SCARD_SCOPE_USER";
47  case SCARD_SCOPE_TERMINAL:
48  return "SCARD_SCOPE_TERMINAL";
49  case SCARD_SCOPE_SYSTEM:
50  return "SCARD_SCOPE_SYSTEM";
51  default:
52  return "UNKNOWN";
53  }
54 }
55 
56 static std::string err2str(LONG code)
57 {
58  switch (code)
59  {
60  case ERROR_BROKEN_PIPE:
61  return "ERROR_BROKEN_PIPE";
62  case SCARD_E_BAD_SEEK:
63  return "SCARD_E_BAD_SEEK";
64  case SCARD_E_CANCELLED:
65  return "SCARD_E_CANCELLED";
66  case SCARD_E_CANT_DISPOSE:
67  return "SCARD_E_CANT_DISPOSE";
68  case SCARD_E_CARD_UNSUPPORTED:
69  return "SCARD_E_CARD_UNSUPPORTED";
70  case SCARD_E_CERTIFICATE_UNAVAILABLE:
71  return "SCARD_E_CERTIFICATE_UNAVAILABLE";
72  case SCARD_E_COMM_DATA_LOST:
73  return "SCARD_E_COMM_DATA_LOST";
74  case SCARD_E_DIR_NOT_FOUND:
75  return "SCARD_E_DIR_NOT_FOUND";
76  case SCARD_E_DUPLICATE_READER:
77  return "SCARD_E_DUPLICATE_READER";
78  case SCARD_E_FILE_NOT_FOUND:
79  return "SCARD_E_FILE_NOT_FOUND";
80  case SCARD_E_ICC_CREATEORDER:
81  return "SCARD_E_ICC_CREATEORDER";
82  case SCARD_E_ICC_INSTALLATION:
83  return "SCARD_E_ICC_INSTALLATION";
84  case SCARD_E_INSUFFICIENT_BUFFER:
85  return "SCARD_E_INSUFFICIENT_BUFFER";
86  case SCARD_E_INVALID_ATR:
87  return "SCARD_E_INVALID_ATR";
88  case SCARD_E_INVALID_CHV:
89  return "SCARD_E_INVALID_CHV";
90  case SCARD_E_INVALID_HANDLE:
91  return "SCARD_E_INVALID_HANDLE";
92  case SCARD_E_INVALID_PARAMETER:
93  return "SCARD_E_INVALID_PARAMETER";
94  case SCARD_E_INVALID_TARGET:
95  return "SCARD_E_INVALID_TARGET";
96  case SCARD_E_INVALID_VALUE:
97  return "SCARD_E_INVALID_VALUE";
98  case SCARD_E_NO_ACCESS:
99  return "SCARD_E_NO_ACCESS";
100  case SCARD_E_NO_DIR:
101  return "SCARD_E_NO_DIR";
102  case SCARD_E_NO_FILE:
103  return "SCARD_E_NO_FILE";
104  case SCARD_E_NO_KEY_CONTAINER:
105  return "SCARD_E_NO_KEY_CONTAINER";
106  case SCARD_E_NO_MEMORY:
107  return "SCARD_E_NO_MEMORY";
108  case SCARD_E_NO_PIN_CACHE:
109  return "SCARD_E_NO_PIN_CACHE";
110  case SCARD_E_NO_READERS_AVAILABLE:
111  return "SCARD_E_NO_READERS_AVAILABLE";
112  case SCARD_E_NO_SERVICE:
113  return "SCARD_E_NO_SERVICE";
114  case SCARD_E_NO_SMARTCARD:
115  return "SCARD_E_NO_SMARTCARD";
116  case SCARD_E_NO_SUCH_CERTIFICATE:
117  return "SCARD_E_NO_SUCH_CERTIFICATE";
118  case SCARD_E_NOT_READY:
119  return "SCARD_E_NOT_READY";
120  case SCARD_E_NOT_TRANSACTED:
121  return "SCARD_E_NOT_TRANSACTED";
122  case SCARD_E_PCI_TOO_SMALL:
123  return "SCARD_E_PCI_TOO_SMALL";
124  case SCARD_E_PIN_CACHE_EXPIRED:
125  return "SCARD_E_PIN_CACHE_EXPIRED";
126  case SCARD_E_PROTO_MISMATCH:
127  return "SCARD_E_PROTO_MISMATCH";
128  case SCARD_E_READ_ONLY_CARD:
129  return "SCARD_E_READ_ONLY_CARD";
130  case SCARD_E_READER_UNAVAILABLE:
131  return "SCARD_E_READER_UNAVAILABLE";
132  case SCARD_E_READER_UNSUPPORTED:
133  return "SCARD_E_READER_UNSUPPORTED";
134  case SCARD_E_SERVER_TOO_BUSY:
135  return "SCARD_E_SERVER_TOO_BUSY";
136  case SCARD_E_SERVICE_STOPPED:
137  return "SCARD_E_SERVICE_STOPPED";
138  case SCARD_E_SHARING_VIOLATION:
139  return "SCARD_E_SHARING_VIOLATION";
140  case SCARD_E_SYSTEM_CANCELLED:
141  return "SCARD_E_SYSTEM_CANCELLED";
142  case SCARD_E_TIMEOUT:
143  return "SCARD_E_TIMEOUT";
144  case SCARD_E_UNEXPECTED:
145  return "SCARD_E_UNEXPECTED";
146  case SCARD_E_UNKNOWN_CARD:
147  return "SCARD_E_UNKNOWN_CARD";
148  case SCARD_E_UNKNOWN_READER:
149  return "SCARD_E_UNKNOWN_READER";
150  case SCARD_E_UNKNOWN_RES_MNG:
151  return "SCARD_E_UNKNOWN_RES_MNG";
152  case SCARD_E_UNSUPPORTED_FEATURE:
153  return "SCARD_E_UNSUPPORTED_FEATURE";
154  case SCARD_E_WRITE_TOO_MANY:
155  return "SCARD_E_WRITE_TOO_MANY";
156  case SCARD_F_COMM_ERROR:
157  return "SCARD_F_COMM_ERROR";
158  case SCARD_F_INTERNAL_ERROR:
159  return "SCARD_F_INTERNAL_ERROR";
160  case SCARD_F_UNKNOWN_ERROR:
161  return "SCARD_F_UNKNOWN_ERROR";
162  case SCARD_F_WAITED_TOO_LONG:
163  return "SCARD_F_WAITED_TOO_LONG";
164  case SCARD_P_SHUTDOWN:
165  return "SCARD_P_SHUTDOWN";
166  case SCARD_S_SUCCESS:
167  return "SCARD_S_SUCCESS";
168  case SCARD_W_CANCELLED_BY_USER:
169  return "SCARD_W_CANCELLED_BY_USER";
170  case SCARD_W_CACHE_ITEM_NOT_FOUND:
171  return "SCARD_W_CACHE_ITEM_NOT_FOUND";
172  case SCARD_W_CACHE_ITEM_STALE:
173  return "SCARD_W_CACHE_ITEM_STALE";
174  case SCARD_W_CACHE_ITEM_TOO_BIG:
175  return "SCARD_W_CACHE_ITEM_TOO_BIG";
176  case SCARD_W_CARD_NOT_AUTHENTICATED:
177  return "SCARD_W_CARD_NOT_AUTHENTICATED";
178  case SCARD_W_CHV_BLOCKED:
179  return "SCARD_W_CHV_BLOCKED";
180  case SCARD_W_EOF:
181  return "SCARD_W_EOF";
182  case SCARD_W_REMOVED_CARD:
183  return "SCARD_W_REMOVED_CARD";
184  case SCARD_W_RESET_CARD:
185  return "SCARD_W_RESET_CARD";
186  case SCARD_W_SECURITY_VIOLATION:
187  return "SCARD_W_SECURITY_VIOLATION";
188  case SCARD_W_UNPOWERED_CARD:
189  return "SCARD_W_UNPOWERED_CARD";
190  case SCARD_W_UNRESPONSIVE_CARD:
191  return "SCARD_W_UNRESPONSIVE_CARD";
192  case SCARD_W_UNSUPPORTED_CARD:
193  return "SCARD_W_UNSUPPORTED_CARD";
194  case SCARD_W_WRONG_CHV:
195  return "SCARD_W_WRONG_CHV";
196  default:
197  return "UNKNOWN";
198  }
199 }
200 
201 static std::wstring err2wstr(LONG code)
202 {
203  auto str = err2str(code);
204  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
205  return converter.from_bytes(str);
206 }
207 
208 #if 0
209 static bool test_listreadergroups(SCARDCONTEXT hContext) {
210  auto rc = SCardListReaderGroupsA(hContext, &groups, &foobar);
211  rc = SCardListReaderGroupsW(hContext, &groups, &foobar);
212 }
213 #endif
214 
215 static bool test_valid(SCARDCONTEXT context)
216 {
217  auto rc = SCardIsValidContext(context);
218  if (rc)
219  std::cerr << "SCardIsValidContext failed with " << err2str(rc) << std::endl;
220  return true;
221 }
222 
223 static bool test_list_readers_a(SCARDCONTEXT context)
224 {
225  for (auto cur : listA)
226  {
227  LPSTR mszReaders = nullptr;
228  DWORD chReaders = SCARD_AUTOALLOCATE;
229  auto rc = SCardListReadersA(context, cur, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
230  if (!cur)
231  {
232  cur = "NULL";
233  }
234  if (rc != SCARD_S_SUCCESS)
235  {
236  std::cerr << "SCardListReadersA [" << cur << "] failed with " << err2str(rc)
237  << std::endl;
238  }
239  else
240  {
241  auto start = mszReaders;
242  auto end = &mszReaders[chReaders];
243 
244  std::cout << "SCardListReadersA [" << cur << "] " << chReaders << " [";
245  while (start < end)
246  {
247  std::cout << start << ", ";
248  start += strnlen(start, chReaders) + 2;
249  }
250  std::cout << "]" << std::endl;
251  }
252  SCardFreeMemory(context, mszReaders);
253  }
254 
255  return true;
256 }
257 
258 static bool test_list_readers_w(SCARDCONTEXT context)
259 {
260  for (auto cur : listW)
261  {
262  LPWSTR mszReaders = nullptr;
263  DWORD chReaders = SCARD_AUTOALLOCATE;
264  auto rc =
265  SCardListReadersW(context, cur, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
266  if (!cur)
267  {
268  cur = L"NULL";
269  }
270  if (rc != SCARD_S_SUCCESS)
271  {
272  std::wcerr << L"SCardListReadersW [" << cur << L"] failed with " << err2wstr(rc)
273  << std::endl;
274  }
275  else
276  {
277  auto start = mszReaders;
278  auto end = &mszReaders[chReaders];
279 
280  std::wcout << L"SCardListReadersW [" << cur << L"] " << chReaders << L" [";
281  while (start < end)
282  {
283  std::wcout << start << L", ";
284  start += wcsnlen(start, chReaders) + 2;
285  }
286  std::wcout << L"]" << std::endl;
287  }
288  SCardFreeMemory(context, mszReaders);
289  }
290 
291  return true;
292 }
293 
294 static bool test_list_reader_groups_a(SCARDCONTEXT context)
295 {
296  LPSTR mszReaders = nullptr;
297  DWORD chReaders = SCARD_AUTOALLOCATE;
298  auto rc = SCardListReaderGroupsA(context, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
299  if (rc != SCARD_S_SUCCESS)
300  {
301  std::cerr << "SCardListReaderGroupsA failed with " << err2str(rc) << std::endl;
302  }
303  else
304  {
305  auto start = mszReaders;
306  auto end = &mszReaders[chReaders];
307 
308  std::cout << "SCardListReaderGroupsA " << chReaders << " [";
309  while (start < end)
310  {
311  std::cout << start << ", ";
312  start += strnlen(start, chReaders) + 2;
313  }
314  std::cout << "]" << std::endl;
315  }
316  SCardFreeMemory(context, mszReaders);
317 
318  return true;
319 }
320 
321 static bool test_list_reader_groups_w(SCARDCONTEXT context)
322 {
323  LPWSTR mszReaders = nullptr;
324  DWORD chReaders = SCARD_AUTOALLOCATE;
325  auto rc = SCardListReaderGroupsW(context, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
326  if (rc != SCARD_S_SUCCESS)
327  {
328  std::wcerr << L"SCardListReaderGroupsW failed with " << err2wstr(rc) << std::endl;
329  }
330  else
331  {
332  auto start = mszReaders;
333  auto end = &mszReaders[chReaders];
334 
335  std::wcout << L"SCardListReaderGroupsW " << chReaders << L" [";
336  while (start < end)
337  {
338  std::wcout << start << L", ";
339  start += wcsnlen(start, chReaders) + 2;
340  }
341  std::wcout << L"]" << std::endl;
342  }
343  SCardFreeMemory(context, mszReaders);
344 
345  return true;
346 }
347 
348 static bool test_introduce_forget_reader_groups_a(SCARDCONTEXT context)
349 {
350  LPSTR group = "somefancygroup";
351 
352  auto rc = SCardIntroduceReaderGroupA(context, group);
353  if (rc != SCARD_S_SUCCESS)
354  {
355  std::cerr << "SCardIntroduceReaderGroupA failed with " << err2str(rc) << std::endl;
356  return false;
357  }
358  else
359  {
360  rc = SCardForgetReaderGroupA(context, group);
361  if (rc != SCARD_S_SUCCESS)
362  {
363  std::cerr << "SCardForgetReaderGroupA failed with " << err2str(rc) << std::endl;
364  return false;
365  }
366  return true;
367  }
368 }
369 
370 static bool test_introduce_forget_reader_groups_w(SCARDCONTEXT context)
371 {
372  LPWSTR group = L"somefancygroup";
373 
374  auto rc = SCardIntroduceReaderGroupW(context, group);
375  if (rc != SCARD_S_SUCCESS)
376  {
377  std::cerr << "SCardIntroduceReaderGroupW failed with " << err2str(rc) << std::endl;
378  return false;
379  }
380  else
381  {
382  rc = SCardForgetReaderGroupW(context, group);
383  if (rc != SCARD_S_SUCCESS)
384  {
385  std::cerr << "SCardForgetReaderGroupW failed with " << err2str(rc) << std::endl;
386  return false;
387  }
388  return true;
389  }
390 }
391 
392 static bool test_introduce_forget_reader_a(SCARDCONTEXT context)
393 {
394  LPSTR reader = "somefancygroup";
395  LPSTR device = "otherfancy";
396 
397  auto rc = SCardIntroduceReaderA(context, reader, device);
398  if (rc != SCARD_S_SUCCESS)
399  {
400  std::cerr << "SCardIntroduceReaderA failed with " << err2str(rc) << std::endl;
401  return false;
402  }
403  else
404  {
405  rc = SCardForgetReaderA(context, reader);
406  if (rc != SCARD_S_SUCCESS)
407  {
408  std::cerr << "SCardForgetReaderA failed with " << err2str(rc) << std::endl;
409  return false;
410  }
411  return true;
412  }
413 }
414 
415 static bool test_introduce_forget_reader_w(SCARDCONTEXT context)
416 {
417  LPWSTR reader = L"somefancygroup";
418  LPWSTR device = L"otherfancy";
419 
420  auto rc = SCardIntroduceReaderW(context, reader, device);
421  if (rc != SCARD_S_SUCCESS)
422  {
423  std::cerr << "SCardIntroduceReaderW failed with " << err2str(rc) << std::endl;
424  return false;
425  }
426  else
427  {
428  rc = SCardForgetReaderW(context, reader);
429  if (rc != SCARD_S_SUCCESS)
430  {
431  std::cerr << "SCardForgetReaderW failed with " << err2str(rc) << std::endl;
432  return false;
433  }
434  return true;
435  }
436 }
437 
438 static bool test_list_cards_a(SCARDCONTEXT context)
439 {
440  DWORD chCards = SCARD_AUTOALLOCATE;
441  LPSTR mszCards = nullptr;
442  auto rc =
443  SCardListCardsA(context, nullptr, nullptr, 0, reinterpret_cast<LPSTR>(&mszCards), &chCards);
444  if (rc != SCARD_S_SUCCESS)
445  {
446  std::cerr << "SCardListCardsA failed with " << err2str(rc) << std::endl;
447  }
448  else
449  {
450  auto start = mszCards;
451  auto end = &mszCards[chCards];
452  std::cout << "SCardListCardsA " << chCards << " [";
453  while (start < end)
454  {
455  std::cout << start << ", ";
456  start += strnlen(start, chCards) + 2;
457  }
458  std::cout << "]" << std::endl;
459  }
460  return true;
461 }
462 
463 static bool test_list_cards_w(SCARDCONTEXT context)
464 {
465  DWORD chCards = SCARD_AUTOALLOCATE;
466  LPWSTR mszCards = nullptr;
467  auto rc = SCardListCardsW(context, nullptr, nullptr, 0, reinterpret_cast<LPWSTR>(&mszCards),
468  &chCards);
469  if (rc != SCARD_S_SUCCESS)
470  {
471  std::cerr << "SCardListCardsW failed with " << err2str(rc) << std::endl;
472  }
473  else
474  {
475  auto start = mszCards;
476  auto end = &mszCards[chCards];
477  std::cout << "SCardListCardsW " << chCards << " [";
478  while (start < end)
479  {
480  std::wcout << start << L", ";
481  start += wcsnlen(start, chCards) + 2;
482  }
483  std::cout << "]" << std::endl;
484  }
485  return true;
486 }
487 
488 static bool test_cache_a(SCARDCONTEXT context)
489 {
490  BYTE wdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
491  const DWORD wdatalen = sizeof(wdata);
492  BYTE data[32] = {};
493  DWORD datalen = sizeof(data);
494  LPSTR name = "testdata";
495  UUID id = {};
496 
497  auto rc = SCardWriteCacheA(context, &id, 0, name, wdata, wdatalen);
498  if (rc != SCARD_S_SUCCESS)
499  {
500  std::cerr << "SCardWriteCacheA failed with " << err2str(rc) << std::endl;
501  return false;
502  }
503 
504  rc = SCardReadCacheA(context, &id, 0, name, data, &datalen);
505  if (rc != SCARD_S_SUCCESS)
506  {
507  std::cerr << "SCardReadCacheA failed with " << err2str(rc) << std::endl;
508  return false;
509  }
510 
511  if (wdatalen != datalen)
512  {
513  std::cerr << "SCardWriteCacheA wrote " << wdatalen << "bytes, SCardReadCacheA read "
514  << datalen << "bytes" << std::endl;
515  return false;
516  }
517 
518  if (memcmp(wdata, data, wdatalen) != 0)
519  {
520  std::cerr << "SCardWriteCacheA / SCardReadCacheA data corruption detected" << std::endl;
521  return false;
522  }
523 
524  return true;
525 }
526 
527 static bool test_cache_w(SCARDCONTEXT context)
528 {
529  BYTE wdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
530  const DWORD wdatalen = sizeof(wdata);
531  BYTE data[32] = {};
532  DWORD datalen = sizeof(data);
533  LPWSTR name = L"testdata";
534  UUID id = {};
535 
536  auto rc = SCardWriteCacheW(context, &id, 0, name, wdata, wdatalen);
537  if (rc != SCARD_S_SUCCESS)
538  {
539  std::cerr << "SCardWriteCacheW failed with " << err2str(rc) << std::endl;
540  return false;
541  }
542 
543  rc = SCardReadCacheW(context, &id, 0, name, data, &datalen);
544  if (rc != SCARD_S_SUCCESS)
545  {
546  std::cerr << "SCardReadCacheW failed with " << err2str(rc) << std::endl;
547  return false;
548  }
549 
550  if (wdatalen != datalen)
551  {
552  std::cerr << "SCardReadCacheW wrote " << wdatalen << "bytes, SCardReadCacheW read "
553  << datalen << "bytes" << std::endl;
554  return false;
555  }
556 
557  if (memcmp(wdata, data, wdatalen) != 0)
558  {
559  std::cerr << "SCardReadCacheW / SCardReadCacheW data corruption detected" << std::endl;
560  return false;
561  }
562 
563  return true;
564 }
565 
566 static bool test_reader_icon_a(SCARDCONTEXT context)
567 {
568  LPSTR name = "Gemalto PC Twin Reader 00 00\0\0";
569  LPBYTE pbIcon = nullptr;
570  DWORD cbIcon = SCARD_AUTOALLOCATE;
571 
572  auto rc = SCardGetReaderIconA(context, name, reinterpret_cast<LPBYTE>(&pbIcon), &cbIcon);
573  SCardFreeMemory(context, pbIcon);
574  if (rc != SCARD_S_SUCCESS)
575  {
576  std::cerr << "SCardGetReaderIconA failed with " << err2str(rc) << std::endl;
577  return false;
578  }
579 
580  return true;
581 }
582 
583 static bool test_reader_icon_w(SCARDCONTEXT context)
584 {
585  LPWSTR name = L"Gemalto PC Twin Reader 00 00\0\0";
586  LPBYTE pbIcon = nullptr;
587  DWORD cbIcon = SCARD_AUTOALLOCATE;
588 
589  auto rc = SCardGetReaderIconW(context, name, reinterpret_cast<LPBYTE>(&pbIcon), &cbIcon);
590  SCardFreeMemory(context, pbIcon);
591  if (rc != SCARD_S_SUCCESS)
592  {
593  std::cerr << "SCardGetReaderIconW failed with " << err2str(rc) << std::endl;
594  return false;
595  }
596 
597  return true;
598 }
599 
600 static bool test_locate_cards_a(SCARDCONTEXT context)
601 {
602  LPSTR name = "Gemalto PC Twin Reader 00 00\0\0";
603  SCARD_READERSTATEA rgReaderStates[16] = {};
604 
605  auto rc = SCardLocateCardsA(context, name, rgReaderStates, ARRAYSIZE(rgReaderStates));
606  if (rc != SCARD_S_SUCCESS)
607  {
608  std::cerr << "SCardLocateCardsA failed with " << err2str(rc) << std::endl;
609  return false;
610  }
611 
612  return true;
613 }
614 
615 static bool test_locate_cards_w(SCARDCONTEXT context)
616 {
617  LPWSTR name = L"Gemalto PC Twin Reader 00 00\0\0";
618  SCARD_READERSTATEW rgReaderStates[16] = {};
619 
620  auto rc = SCardLocateCardsW(context, name, rgReaderStates, ARRAYSIZE(rgReaderStates));
621  if (rc != SCARD_S_SUCCESS)
622  {
623  std::cerr << "SCardLocateCardsW failed with " << err2str(rc) << std::endl;
624  return false;
625  }
626 
627  return true;
628 }
629 
630 static bool test_locate_cards_by_atr_a(SCARDCONTEXT context)
631 {
632  SCARD_READERSTATEA rgReaderStates[16] = {};
633  SCARD_ATRMASK rgAtrMasks[16] = {};
634 
635  auto rc = SCardLocateCardsByATRA(context, rgAtrMasks, ARRAYSIZE(rgAtrMasks), rgReaderStates,
636  ARRAYSIZE(rgReaderStates));
637  if (rc != SCARD_S_SUCCESS)
638  {
639  std::cerr << "SCardLocateCardsByATRA failed with " << err2str(rc) << std::endl;
640  return false;
641  }
642 
643  return true;
644 }
645 
646 static bool test_locate_cards_by_atr_w(SCARDCONTEXT context)
647 {
648  SCARD_READERSTATEW rgReaderStates[16] = {};
649  SCARD_ATRMASK rgAtrMasks[16] = {};
650 
651  auto rc = SCardLocateCardsByATRW(context, rgAtrMasks, ARRAYSIZE(rgAtrMasks), rgReaderStates,
652  ARRAYSIZE(rgReaderStates));
653  if (rc != SCARD_S_SUCCESS)
654  {
655  std::cerr << "SCardLocateCardsByATRW failed with " << err2str(rc) << std::endl;
656  return false;
657  }
658 
659  return true;
660 }
661 
662 static bool test_devicetype_id_a(SCARDCONTEXT context)
663 {
664  BYTE data[32] = {};
665  LPSTR name = "testdata";
666  DWORD type;
667 
668  auto rc = SCardGetDeviceTypeIdA(context, name, &type);
669  if (rc != SCARD_S_SUCCESS)
670  {
671  std::cerr << "SCardGetDeviceTypeIdA failed with " << err2str(rc) << std::endl;
672  return false;
673  }
674 
675  return true;
676 }
677 
678 static bool test_devicetype_id_w(SCARDCONTEXT context)
679 {
680  BYTE data[32] = {};
681  LPWSTR name = L"testdata";
682  DWORD type;
683 
684  auto rc = SCardGetDeviceTypeIdW(context, name, &type);
685  if (rc != SCARD_S_SUCCESS)
686  {
687  std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
688  return false;
689  }
690 
691  return true;
692 }
693 
694 static bool test_transmitcount(SCARDHANDLE handle)
695 {
696  BYTE data[32] = {};
697  LPWSTR name = L"testdata";
698  DWORD count;
699 
700  auto rc = SCardGetTransmitCount(handle, &count);
701  if (rc != SCARD_S_SUCCESS)
702  {
703  std::cerr << "SCardGetTransmitCount failed with " << err2str(rc) << std::endl;
704  return false;
705  }
706  std::cout << "SCardGetTransmitCount() " << count << std::endl;
707  return true;
708 }
709 
710 static bool test_status_a(SCARDHANDLE handle)
711 {
712  BYTE data[32] = {};
713  LPWSTR name = L"testdata";
714  DWORD count;
715  /*
716  auto rc = SCardStatusA(handle, names, len, &state, &protocol, attr, &attrlen);
717  if (rc != SCARD_S_SUCCESS) {
718  std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
719  return false;
720  }
721  */
722  return true;
723 }
724 
725 static bool test_status_w(SCARDHANDLE handle)
726 {
727  BYTE data[32] = {};
728  LPWSTR name = L"testdata";
729  DWORD count;
730  /*
731  auto rc = SCardStatusA(handle, names, len, &state, &protocol, attr, &attrlen);
732  if (rc != SCARD_S_SUCCESS) {
733  std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
734  return false;
735  }
736 */
737  return true;
738 }
739 
740 static bool test_get_attrib(SCARDCONTEXT context, SCARDHANDLE handle)
741 {
742  DWORD attrlen = SCARD_AUTOALLOCATE;
743  LPBYTE attr = nullptr;
744 
745  auto rc =
746  SCardGetAttrib(handle, SCARD_ATTR_ATR_STRING, reinterpret_cast<LPBYTE>(&attr), &attrlen);
747  if (rc != SCARD_S_SUCCESS)
748  {
749  std::cerr << "SCardGetAttrib failed with " << err2str(rc) << std::endl;
750  return false;
751  }
752  std::cout << "SCardGetAttrib [" << attrlen << "]: " << (char*)attr << std::endl;
753  SCardFreeMemory(context, attr);
754 
755  return true;
756 }
757 
758 static bool test_set_attrib(SCARDCONTEXT context, SCARDHANDLE handle)
759 {
760  DWORD attrlen = SCARD_AUTOALLOCATE;
761  BYTE attr[] = "0123456789";
762 
763  auto rc = SCardSetAttrib(handle, SCARD_ATTR_SUPRESS_T1_IFS_REQUEST, attr, ARRAYSIZE(attr));
764  if (rc != SCARD_S_SUCCESS)
765  {
766  std::cerr << "SCardSetAttrib failed with " << err2str(rc) << std::endl;
767  return false;
768  }
769  std::cout << "SCardSetAttrib [" << attrlen << "]: " << (char*)attr << std::endl;
770  SCardFreeMemory(context, attr);
771 
772  return true;
773 }
774 
775 int main()
776 {
777  std::cout << "Hello World!" << std::endl;
778  try
779  {
780  auto scopes = { SCARD_SCOPE_USER, SCARD_SCOPE_SYSTEM };
781  for (auto scope : scopes)
782  {
783  SCARDCONTEXT context;
784  auto rc = SCardEstablishContext(scope, nullptr, nullptr, &context);
785  if (rc != SCARD_S_SUCCESS)
786  {
787  std::cerr << "SCardEstablishContext [" << scope2str(scope) << "] failed with "
788  << err2str(rc) << std::endl;
789  }
790  else
791  {
792  std::cerr << "SCardEstablishContext [" << scope2str(scope) << "] success"
793  << std::endl;
794 
795  test_valid(context);
796 
797  test_list_reader_groups_a(context);
798  test_list_reader_groups_w(context);
799 
800  test_list_readers_a(context);
801  test_list_readers_w(context);
802 
803  test_list_cards_a(context);
804  test_list_cards_w(context);
805 
806  test_introduce_forget_reader_groups_a(context);
807  test_introduce_forget_reader_groups_w(context);
808 
809  test_introduce_forget_reader_a(context);
810  test_introduce_forget_reader_w(context);
811 
812  // TODO: Introduce/Remove reader to group
813  test_locate_cards_a(context);
814  test_locate_cards_w(context);
815 
816  test_locate_cards_by_atr_a(context);
817  test_locate_cards_by_atr_w(context);
818 
819  test_cache_a(context);
820  test_cache_w(context);
821 
822  test_reader_icon_a(context);
823  test_reader_icon_w(context);
824 
825  test_devicetype_id_a(context);
826  test_devicetype_id_w(context);
827 
828  // TODO: statuschange
829  // TODO: begin/end transaction
830  // TODO: state
831  // TODO: transmit
832  // TODO: control
833 
834  {
835  DWORD protocol;
836  SCARDHANDLE handle = 0;
837  LPSTR mszReaders;
838  DWORD chReaders = SCARD_AUTOALLOCATE;
839 
840  LONG status = SCardListReadersA(
841  context, nullptr, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
842  if (status == SCARD_S_SUCCESS)
843  status = SCardConnectA(context, mszReaders, SCARD_SHARE_SHARED,
844  SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 |
845  SCARD_PROTOCOL_Tx | SCARD_PROTOCOL_RAW,
846  &handle, &protocol);
847  SCardFreeMemory(context, mszReaders);
848  if (status != SCARD_S_SUCCESS)
849  {
850  std::cerr << "SCardConnectA ["
851  << "] failed with " << err2str(status) << std::endl;
852  }
853  else
854  {
855  test_status_a(handle);
856  test_status_w(handle);
857  test_get_attrib(context, handle);
858  test_set_attrib(context, handle);
859  test_transmitcount(handle);
860 
861  status = SCardDisconnect(handle, 0);
862  if (status)
863  {
864  std::cerr << "SCardDisconnect ["
865  << "] failed with " << err2str(status) << std::endl;
866  }
867  }
868  }
869  {
870  DWORD protocol;
871  SCARDHANDLE handle = 0;
872  LPWSTR mszReaders;
873  DWORD chReaders = SCARD_AUTOALLOCATE;
874 
875  LONG status = SCardListReadersW(
876  context, nullptr, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
877  if (status == SCARD_S_SUCCESS)
878  status = SCardConnectW(context, mszReaders, SCARD_SHARE_SHARED,
879  SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 |
880  SCARD_PROTOCOL_Tx | SCARD_PROTOCOL_RAW,
881  &handle, &protocol);
882  SCardFreeMemory(context, mszReaders);
883 
884  if (status != SCARD_S_SUCCESS)
885  {
886  std::cerr << "SCardConnectW ["
887  << "] failed with " << err2str(status) << std::endl;
888  }
889  else
890  {
891  test_status_a(handle);
892  test_status_w(handle);
893  test_get_attrib(context, handle);
894  test_set_attrib(context, handle);
895  test_transmitcount(handle);
896 
897  status = SCardDisconnect(handle, 0);
898  if (status)
899  {
900  std::cerr << "SCardDisconnect ["
901  << "] failed with " << err2str(status) << std::endl;
902  }
903  }
904  }
905 
906  rc = SCardReleaseContext(context);
907  if (rc != SCARD_S_SUCCESS)
908  {
909  std::cerr << "SCardReleaseContext [" << scope2str(scope) << "] failed with "
910  << err2str(rc) << std::endl;
911  }
912  }
913  }
914  }
915  catch (...)
916  {
917  std::cerr << "exception!!!!" << std::endl;
918  }
919 
920  return 0;
921 }