channels/smartcard: migrate code to libwinpr-smartcard

This commit is contained in:
Marc-André Moreau 2014-04-03 15:27:55 -04:00
parent d5ca2162ad
commit 89ad7638e4
6 changed files with 239 additions and 121 deletions

View File

@ -28,6 +28,7 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/smartcard.h>
#include <freerdp/utils/list.h>
#include <freerdp/utils/debug.h>
@ -148,7 +149,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
smartcard->name = name;
}
smartcard->IrpQueue = MessageQueue_New();
smartcard->IrpQueue = MessageQueue_New(NULL);
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
smartcard, CREATE_SUSPENDED, NULL);

View File

@ -27,74 +27,13 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/smartcard.h>
#include <winpr/collections.h>
#define BOOL PCSC_BOOL
#include <PCSC/pcsclite.h>
#include <PCSC/reader.h>
#include <PCSC/winscard.h>
#undef BOOL
/*
* When using Windows Server 2008 R2 as the Terminal Services (TS)
* server, and with a smart card reader connected to the TS client machine
* and used to authenticate to an existing login session, the TS server
* will initiate the protocol initialization of MS-RDPEFS, Section 1.3.1,
* twice as it re-establishes a connection. The TS server starts both
* initializations with a "Server Announce Request" message.
* When the TS client receives this message, as per Section 3.2.5.1.2,
*
* The client SHOULD treat this packet as the beginning
* of a new sequence. The client SHOULD also cancel all
* outstanding requests and release previous references to
* all devices.
*
* As of this writing, the code does not cancel all outstanding requests.
* This leads to a problem where, after the first MS-RDPEFS initialization,
* the TS server sends an SCARD_IOCTL_GETSTATUSCHANGEx control in a message
* that uses an available "CompletionID". The
* TS client doesn't respond immediately because it is blocking while
* waiting for a change in the smart card's status in the reader.
* Then the TS server initiates a second MS-RDPEFS initialization sequence.
* As noted above, this should cancel the outstanding
* SCARD_IOCTL_GETSTATUSCHANGEx request, but it does not.
* At this point, the TS server is free to reuse the previously used
* "CompletionID", and it does reuse it for other SCARD_IOCTLs.
* Therefore, when the user removes (for example) the card from the reader,
* the TS client sends an "IOCompetion" message in response to the
* GETSTATUSCHANGEx using the original "CompletionID". The TS server does not
* expect this "CompletionID" and so, as per Section 3.1.5.2 of MS-RDPEFS,
* it treats that "IOCompletion" message as an error and terminates the
* virtual channel.
*
* The following structure is part of a work-around for this missing
* capability of canceling outstanding requests. This work-around
* allows the TS client to send an "IOCompletion" back to the
* TS server for the second (and subsequent) SCARD_IOCTLs that use
* the same "CompletionID" as the still outstanding
* SCARD_IOCTL_GETSTATUSCHANGEx. The work-around in the TS client
* prevents the client from sending the "IOCompletion" back (when
* the user removes the card) for the SCARD_IOCTL_GETSTATUSCHANGEx.
*
* This TS client expects the responses from the PCSC daemon for the second
* and subsequent SCARD_IOCTLs that use the same "CompletionID"
* to arrive at the TS client before the daemon's response to the
* SCARD_IOCTL_GETSTATUSCHANGEx. This is a race condition.
*
* The "CompletionIDs" are a global pool of IDs across all "DeviceIDs".
* However, this problem of duplicate "CompletionIDs" only affects smart cards.
*
* This structure tracks outstanding Terminal Services server "CompletionIDs"
* used by the redirected smart card device.
*/
struct _COMPLETIONIDINFO
{
UINT32 ID; /* CompletionID */
BOOL duplicate; /* Indicates whether or not this
* CompletionID is a duplicate of an
* earlier, outstanding, CompletionID.
*/
UINT32 ID;
BOOL duplicate;
};
typedef struct _COMPLETIONIDINFO COMPLETIONIDINFO;

View File

@ -28,36 +28,10 @@
#include <string.h>
#include <assert.h>
#ifdef _WIN32
#include <winscard.h>
#else
#include <strings.h>
#define BOOL PCSC_BOOL
#include <PCSC/pcsclite.h>
#include <PCSC/winscard.h>
#if !defined(__APPLE__)
#include <PCSC/reader.h>
#else
/* On OS X reader.h isn't available so define it here */
#endif
#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
#define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003)
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005)
#ifdef UNICODE
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W /**< Reader's display name. */
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W /**< Reader's system name. */
#else
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A /**< Reader's display name. */
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A /**< Reader's system name. */
#define SCARD_CTL_CODE(code) (0x42000000 + (code))
#endif
#undef BOOL
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/smartcard.h>
#include <freerdp/freerdp.h>
#include <freerdp/channels/rdpdr.h>
@ -489,9 +463,9 @@ static BOOL check_handle_is_forwarded(SMARTCARD_DEVICE *scard,
LONG status;
DWORD state = 0, protocol = 0;
DWORD readerLen;
DWORD atrLen = MAX_ATR_SIZE;
DWORD atrLen = SCARD_ATR_LENGTH;
char* readerName = NULL;
BYTE pbAtr[MAX_ATR_SIZE];
BYTE pbAtr[SCARD_ATR_LENGTH];
assert(scard);
assert(hCard);
@ -777,7 +751,7 @@ static UINT32 handle_ReleaseContext(SMARTCARD_DEVICE* scard, IRP* irp)
ZeroMemory(&scard->hContext, sizeof(scard->hContext));
if (status)
DEBUG_SCARD("%s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("%s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("success 0x%08lx", hContext);
@ -815,7 +789,7 @@ static UINT32 handle_IsValidContext(SMARTCARD_DEVICE* scard, IRP* irp)
status = SCardIsValidContext(hContext);
if (status)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success context: 0x%08x", (unsigned) hContext);
@ -914,7 +888,7 @@ static UINT32 handle_ListReaders(SMARTCARD_DEVICE* scard, IRP* irp, BOOL wide)
#endif
if (status != SCARD_S_SUCCESS)
{
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
goto finish;
}
@ -1014,7 +988,7 @@ static UINT32 handle_GetStatusChange(SMARTCARD_DEVICE* scard, IRP* irp, BOOL wid
{
DEBUG_WARN("length violation %d [%d]", 12,
Stream_GetRemainingLength(irp->input));
status =SCARD_F_INTERNAL_ERROR;
status = SCARD_F_INTERNAL_ERROR;
goto finish;
}
@ -1127,7 +1101,7 @@ static UINT32 handle_GetStatusChange(SMARTCARD_DEVICE* scard, IRP* irp, BOOL wid
status = SCardGetStatusChange(hContext, (DWORD) dwTimeout, readerStates, (DWORD) readerCount);
if (status != SCARD_S_SUCCESS)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success");
@ -1163,7 +1137,7 @@ finish:
cur = &readerStates[i];
if (cur->szReader)
free(cur->szReader);
free((void*) cur->szReader);
cur->szReader = NULL;
}
free(readerStates);
@ -1172,7 +1146,7 @@ finish:
return status;
}
static UINT32 handle_Cancel(SMARTCARD_DEVICE *scard, IRP* irp)
static UINT32 handle_Cancel(SMARTCARD_DEVICE* scard, IRP* irp)
{
int redirect = 0;
LONG status;
@ -1201,9 +1175,9 @@ static UINT32 handle_Cancel(SMARTCARD_DEVICE *scard, IRP* irp)
status = SCardCancel(hContext);
if (status != SCARD_S_SUCCESS)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success context: 0x%08x %s", (unsigned) hContext, pcsc_stringify_error(status));
DEBUG_SCARD("Success context: 0x%08x %s", (unsigned) hContext, SCardGetErrorString(status));
smartcard_output_alignment(irp, 8);
@ -1283,7 +1257,7 @@ static UINT32 handle_Connect(SMARTCARD_DEVICE* scard, IRP* irp, BOOL wide)
(DWORD) dwPreferredProtocol, &hCard, (DWORD *) &dwActiveProtocol);
if (status != SCARD_S_SUCCESS)
DEBUG_WARN("Failure: %s 0x%08x", pcsc_stringify_error(status), (unsigned) status);
DEBUG_WARN("Failure: %s 0x%08x", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success 0x%08x", (unsigned) hCard);
@ -1361,7 +1335,7 @@ static UINT32 handle_Reconnect(SMARTCARD_DEVICE* scard, IRP* irp)
(DWORD) dwInitialization, (LPDWORD) &dwActiveProtocol);
if (status != SCARD_S_SUCCESS)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success (proto: 0x%08x)", (unsigned) dwActiveProtocol);
@ -1420,7 +1394,7 @@ static UINT32 handle_Disconnect(SMARTCARD_DEVICE* scard, IRP* irp)
status = SCardDisconnect(hCard, (DWORD) dwDisposition);
if (status != SCARD_S_SUCCESS)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success");
@ -1475,7 +1449,7 @@ static UINT32 handle_BeginTransaction(SMARTCARD_DEVICE* scard, IRP* irp)
status = SCardBeginTransaction(hCard);
if (status != SCARD_S_SUCCESS)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard);
@ -1529,7 +1503,7 @@ static UINT32 handle_EndTransaction(SMARTCARD_DEVICE* scard, IRP* irp)
status = SCardEndTransaction(hCard, dwDisposition);
if (status != SCARD_S_SUCCESS)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard);
@ -1546,9 +1520,9 @@ static UINT32 handle_State(SMARTCARD_DEVICE* scard, IRP* irp)
SCARDCONTEXT hContext;
DWORD state = 0, protocol = 0;
DWORD readerLen;
DWORD atrLen = MAX_ATR_SIZE;
DWORD atrLen = SCARD_ATR_LENGTH;
char* readerName = NULL;
BYTE pbAtr[MAX_ATR_SIZE];
BYTE pbAtr[SCARD_ATR_LENGTH];
#ifdef WITH_DEBUG_SCARD
int i;
@ -1605,7 +1579,7 @@ static UINT32 handle_State(SMARTCARD_DEVICE* scard, IRP* irp)
if (status != SCARD_S_SUCCESS)
{
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
status = smartcard_output_return(irp, status);
goto finish;
}
@ -1653,7 +1627,7 @@ static DWORD handle_Status(SMARTCARD_DEVICE *scard, IRP* irp, BOOL wide)
SCARDCONTEXT hContext;
DWORD state, protocol;
DWORD readerLen = 0;
DWORD atrLen = MAX_ATR_SIZE;
DWORD atrLen = SCARD_ATR_LENGTH;
char* readerName = NULL;
BYTE *pbAtr = NULL;
UINT32 dataLength = 0;
@ -1716,7 +1690,7 @@ static DWORD handle_Status(SMARTCARD_DEVICE *scard, IRP* irp, BOOL wide)
if (status != SCARD_S_SUCCESS)
{
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
status = smartcard_output_return(irp, status);
goto finish;
}
@ -1999,7 +1973,7 @@ static UINT32 handle_Transmit(SMARTCARD_DEVICE* scard, IRP* irp)
if (status != SCARD_S_SUCCESS)
{
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
}
else
{
@ -2126,7 +2100,7 @@ static UINT32 handle_Control(SMARTCARD_DEVICE* scard, IRP* irp)
sendBuffer, (DWORD) outBufferSize, &nBytesReturned);
if (status != SCARD_S_SUCCESS)
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned) status);
else
DEBUG_SCARD("Success (out: %u bytes)", (unsigned) nBytesReturned);
@ -2263,7 +2237,7 @@ static UINT32 handle_GetAttrib(SMARTCARD_DEVICE* scard, IRP* irp)
if (status != SCARD_S_SUCCESS)
{
DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned int) status);
DEBUG_SCARD("Failure: %s (0x%08x)", SCardGetErrorString(status), (unsigned int) status);
status = smartcard_output_return(irp, status);
goto finish;
}
@ -2447,7 +2421,7 @@ static UINT32 handle_LocateCardsByATR(SMARTCARD_DEVICE* scard, IRP* irp, BOOL wi
if (status != SCARD_S_SUCCESS)
{
DEBUG_SCARD("Failure: %s (0x%08x)",
pcsc_stringify_error(status), (unsigned) status);
SCardGetErrorString(status), (unsigned) status);
status = smartcard_output_return(irp, status);
goto finish;
}

View File

@ -82,10 +82,6 @@ WINPR_API BOOL CancelSynchronousIo(HANDLE hThread);
}
#endif
/*
* WinPR I/O Manager Custom API
*/
#define DEVICE_TYPE ULONG
#define FILE_DEVICE_BEEP 0x00000001
@ -156,6 +152,27 @@ WINPR_API BOOL CancelSynchronousIo(HANDLE hThread);
#define FILE_DEVICE_BIOMETRIC 0x00000044
#define FILE_DEVICE_PMI 0x00000045
#define CTL_CODE(DeviceType, Function, Method, Access) \
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((DWORD)(ctrlCode & 0xFFFF0000)) >> 16)
#define METHOD_FROM_CTL_CODE(ctrlCode) ((DWORD)(ctrlCode & 3))
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER 3
#define FILE_ANY_ACCESS 0
#define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS)
#define FILE_READ_ACCESS (0x0001)
#define FILE_WRITE_ACCESS (0x0002)
/*
* WinPR I/O Manager Custom API
*/
typedef HANDLE PDRIVER_OBJECT_EX;
typedef HANDLE PDEVICE_OBJECT_EX;

View File

@ -23,6 +23,7 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/io.h>
#include <winpr/error.h>
#ifdef _WIN32
@ -87,6 +88,7 @@
#define SCARD_E_PIN_CACHE_EXPIRED ((DWORD)0x80100032L)
#define SCARD_E_NO_PIN_CACHE ((DWORD)0x80100033L)
#define SCARD_E_READ_ONLY_CARD ((DWORD)0x80100034L)
#define SCARD_W_UNSUPPORTED_CARD ((DWORD)0x80100065L)
#define SCARD_W_UNRESPONSIVE_CARD ((DWORD)0x80100066L)
#define SCARD_W_UNPOWERED_CARD ((DWORD)0x80100067L)
@ -335,6 +337,14 @@ typedef void (WINAPI *LPOCNDSCPROC)(SCARDCONTEXT hSCardContext, SCARDHANDLE hCar
#define SCARD_AUDIT_CHV_FAILURE 0x0
#define SCARD_AUDIT_CHV_SUCCESS 0x1
#define SCardListCardTypes SCardListCards
#define PCSCardIntroduceCardType(hContext, szCardName, pbAtr, pbAtrMask, cbAtrLen, pguidPrimaryProvider, rgguidInterfaces, dwInterfaceCount) \
SCardIntroduceCardType(hContext, szCardName, pguidPrimaryProvider, rgguidInterfaces, dwInterfaceCount, pbAtr, pbAtrMask, cbAtrLen)
#define SCardGetReaderCapabilities SCardGetAttrib
#define SCardSetReaderCapabilities SCardSetAttrib
typedef struct
{
LPCSTR szReader;
@ -673,6 +683,8 @@ WINSCARDAPI LONG WINAPI SCardGetStatusChangeA(SCARDCONTEXT hContext,
WINSCARDAPI LONG WINAPI SCardGetStatusChangeW(SCARDCONTEXT hContext,
DWORD dwTimeout, LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders);
WINSCARDAPI LONG WINAPI SCardCancel(SCARDCONTEXT hContext);
WINSCARDAPI LONG WINAPI SCardConnectA(SCARDCONTEXT hContext,
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol);
@ -819,5 +831,19 @@ WINSCARDAPI LONG WINAPI SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent);
#endif
/**
* Extended API
*/
#ifdef __cplusplus
extern "C" {
#endif
WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode);
#ifdef __cplusplus
}
#endif
#endif /* WINPR_SMARTCARD_H */

View File

@ -424,6 +424,18 @@ WINSCARDAPI LONG WINAPI SCardGetStatusChangeW(SCARDCONTEXT hContext,
return 0;
}
WINSCARDAPI LONG WINAPI SCardCancel(SCARDCONTEXT hContext)
{
InitializeSCardStubs();
if (g_PCSCLite && g_PCSCLite->pfnSCardCancel)
{
return g_PCSCLite->pfnSCardCancel(hContext);
}
return 0;
}
WINSCARDAPI LONG WINAPI SCardConnectA(SCARDCONTEXT hContext,
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
@ -688,3 +700,152 @@ WINSCARDAPI LONG WINAPI SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
}
#endif
/**
* Extended API
*/
WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode)
{
switch (errorCode)
{
case SCARD_S_SUCCESS:
return "SCARD_S_SUCCESS";
case SCARD_F_INTERNAL_ERROR:
return "SCARD_F_INTERNAL_ERROR";
case SCARD_E_CANCELLED:
return "SCARD_E_CANCELLED";
case SCARD_E_INVALID_HANDLE:
return "SCARD_E_INVALID_HANDLE";
case SCARD_E_INVALID_PARAMETER:
return "SCARD_E_INVALID_PARAMETER";
case SCARD_E_INVALID_TARGET:
return "SCARD_E_INVALID_TARGET";
case SCARD_E_NO_MEMORY:
return "SCARD_E_NO_MEMORY";
case SCARD_F_WAITED_TOO_LONG:
return "SCARD_F_WAITED_TOO_LONG";
case SCARD_E_INSUFFICIENT_BUFFER:
return "SCARD_E_INSUFFICIENT_BUFFER";
case SCARD_E_UNKNOWN_READER:
return "SCARD_E_UNKNOWN_READER";
case SCARD_E_TIMEOUT:
return "SCARD_E_TIMEOUT";
case SCARD_E_SHARING_VIOLATION:
return "SCARD_E_SHARING_VIOLATION";
case SCARD_E_NO_SMARTCARD:
return "SCARD_E_NO_SMARTCARD";
case SCARD_E_UNKNOWN_CARD:
return "SCARD_E_UNKNOWN_CARD";
case SCARD_E_CANT_DISPOSE:
return "SCARD_E_CANT_DISPOSE";
case SCARD_E_PROTO_MISMATCH:
return "SCARD_E_PROTO_MISMATCH";
case SCARD_E_NOT_READY:
return "SCARD_E_NOT_READY";
case SCARD_E_INVALID_VALUE:
return "SCARD_E_INVALID_VALUE";
case SCARD_E_SYSTEM_CANCELLED:
return "SCARD_E_SYSTEM_CANCELLED";
case SCARD_F_COMM_ERROR:
return "SCARD_F_COMM_ERROR";
case SCARD_F_UNKNOWN_ERROR:
return "SCARD_F_UNKNOWN_ERROR";
case SCARD_E_INVALID_ATR:
return "SCARD_E_INVALID_ATR";
case SCARD_E_NOT_TRANSACTED:
return "SCARD_E_NOT_TRANSACTED";
case SCARD_E_READER_UNAVAILABLE:
return "SCARD_E_READER_UNAVAILABLE";
case SCARD_P_SHUTDOWN:
return "SCARD_P_SHUTDOWN";
case SCARD_E_PCI_TOO_SMALL:
return "SCARD_E_PCI_TOO_SMALL";
case SCARD_E_READER_UNSUPPORTED:
return "SCARD_E_READER_UNSUPPORTED";
case SCARD_E_DUPLICATE_READER:
return "SCARD_E_DUPLICATE_READER";
case SCARD_E_CARD_UNSUPPORTED:
return "SCARD_E_CARD_UNSUPPORTED";
case SCARD_E_NO_SERVICE:
return "SCARD_E_NO_SERVICE";
case SCARD_E_SERVICE_STOPPED:
return "SCARD_E_SERVICE_STOPPED";
case SCARD_E_UNEXPECTED:
return "SCARD_E_UNEXPECTED";
case SCARD_E_ICC_INSTALLATION:
return "SCARD_E_ICC_INSTALLATION";
case SCARD_E_ICC_CREATEORDER:
return "SCARD_E_ICC_CREATEORDER";
case SCARD_E_UNSUPPORTED_FEATURE:
return "SCARD_E_UNSUPPORTED_FEATURE";
case SCARD_E_DIR_NOT_FOUND:
return "SCARD_E_DIR_NOT_FOUND";
case SCARD_E_FILE_NOT_FOUND:
return "SCARD_E_FILE_NOT_FOUND";
case SCARD_E_NO_DIR:
return "SCARD_E_NO_DIR";
case SCARD_E_NO_FILE:
return "SCARD_E_NO_FILE";
case SCARD_E_NO_ACCESS:
return "SCARD_E_NO_ACCESS";
case SCARD_E_WRITE_TOO_MANY:
return "SCARD_E_WRITE_TOO_MANY";
case SCARD_E_BAD_SEEK:
return "SCARD_E_BAD_SEEK";
case SCARD_E_INVALID_CHV:
return "SCARD_E_INVALID_CHV";
case SCARD_E_UNKNOWN_RES_MNG:
return "SCARD_E_UNKNOWN_RES_MNG";
case SCARD_E_NO_SUCH_CERTIFICATE:
return "SCARD_E_NO_SUCH_CERTIFICATE";
case SCARD_E_CERTIFICATE_UNAVAILABLE:
return "SCARD_E_CERTIFICATE_UNAVAILABLE";
case SCARD_E_NO_READERS_AVAILABLE:
return "SCARD_E_NO_READERS_AVAILABLE";
case SCARD_E_COMM_DATA_LOST:
return "SCARD_E_COMM_DATA_LOST";
case SCARD_E_NO_KEY_CONTAINER:
return "SCARD_E_NO_KEY_CONTAINER";
case SCARD_E_SERVER_TOO_BUSY:
return "SCARD_E_SERVER_TOO_BUSY";
case SCARD_E_PIN_CACHE_EXPIRED:
return "SCARD_E_PIN_CACHE_EXPIRED";
case SCARD_E_NO_PIN_CACHE:
return "SCARD_E_NO_PIN_CACHE";
case SCARD_E_READ_ONLY_CARD:
return "SCARD_E_READ_ONLY_CARD";
case SCARD_W_UNSUPPORTED_CARD:
return "SCARD_W_UNSUPPORTED_CARD";
case SCARD_W_UNRESPONSIVE_CARD:
return "SCARD_W_UNRESPONSIVE_CARD";
case SCARD_W_UNPOWERED_CARD:
return "SCARD_W_UNPOWERED_CARD";
case SCARD_W_RESET_CARD:
return "SCARD_W_RESET_CARD";
case SCARD_W_REMOVED_CARD:
return "SCARD_W_REMOVED_CARD";
case SCARD_W_SECURITY_VIOLATION:
return "SCARD_W_SECURITY_VIOLATION";
case SCARD_W_WRONG_CHV:
return "SCARD_W_WRONG_CHV";
case SCARD_W_CHV_BLOCKED:
return "SCARD_W_CHV_BLOCKED";
case SCARD_W_EOF:
return "SCARD_W_EOF";
case SCARD_W_CANCELLED_BY_USER:
return "SCARD_W_CANCELLED_BY_USER";
case SCARD_W_CARD_NOT_AUTHENTICATED:
return "SCARD_W_CARD_NOT_AUTHENTICATED";
case SCARD_W_CACHE_ITEM_NOT_FOUND:
return "SCARD_W_CACHE_ITEM_NOT_FOUND";
case SCARD_W_CACHE_ITEM_STALE:
return "SCARD_W_CACHE_ITEM_STALE";
case SCARD_W_CACHE_ITEM_TOO_BIG:
return "SCARD_W_CACHE_ITEM_TOO_BIG";
default:
return "SCARD_E_UNKNOWN";
}
return "SCARD_E_UNKNOWN";
}