|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#define PCSC_API
|
|
|
|
|
|
|
|
typedef unsigned char BYTE;
|
|
|
|
typedef BYTE *LPBYTE;
|
|
|
|
typedef unsigned int LONG;
|
|
|
|
typedef unsigned int DWORD;
|
|
|
|
typedef DWORD *LPDWORD;
|
|
|
|
typedef const void *LPCVOID;
|
|
|
|
typedef const char *LPCSTR;
|
|
|
|
typedef char *LPSTR;
|
|
|
|
typedef void *LPVOID;
|
|
|
|
typedef const BYTE *LPCBYTE;
|
|
|
|
|
|
|
|
typedef LONG SCARDCONTEXT;
|
|
|
|
typedef SCARDCONTEXT *LPSCARDCONTEXT;
|
|
|
|
|
|
|
|
typedef LONG SCARDHANDLE;
|
|
|
|
typedef SCARDHANDLE *LPSCARDHANDLE;
|
|
|
|
|
|
|
|
#define MAX_ATR_SIZE 33
|
|
|
|
|
|
|
|
typedef struct _SCARD_READERSTATE
|
|
|
|
{
|
|
|
|
const char *szReader;
|
|
|
|
void *pvUserData;
|
|
|
|
DWORD dwCurrentState;
|
|
|
|
DWORD dwEventState;
|
|
|
|
DWORD cbAtr;
|
|
|
|
unsigned char rgbAtr[MAX_ATR_SIZE];
|
|
|
|
} SCARD_READERSTATE, *LPSCARD_READERSTATE;
|
|
|
|
|
|
|
|
typedef struct _SCARD_IO_REQUEST
|
|
|
|
{
|
|
|
|
unsigned long dwProtocol;
|
|
|
|
unsigned long cbPciLength;
|
|
|
|
} SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
|
|
|
|
|
|
|
|
#define SCARD_PROTOCOL_T0 0x0001 /**< T=0 active protocol. */
|
|
|
|
#define SCARD_PROTOCOL_T1 0x0002 /**< T=1 active protocol. */
|
|
|
|
#define SCARD_PROTOCOL_RAW 0x0004 /**< Raw active protocol. */
|
|
|
|
|
|
|
|
PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_T0, 8 };
|
|
|
|
PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
|
|
|
|
PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_RAW, 8 };
|
|
|
|
|
|
|
|
#define LLOG_LEVEL 5
|
|
|
|
#define LLOGLN(_level, _args) \
|
|
|
|
do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
|
|
|
|
|
|
|
|
#define SCARD_ESTABLISH_CONTEXT 0x01
|
|
|
|
#define SCARD_RELEASE_CONTEXT 0x02
|
|
|
|
#define SCARD_LIST_READERS 0x03
|
|
|
|
#define SCARD_CONNECT 0x04
|
|
|
|
#define SCARD_RECONNECT 0x05
|
|
|
|
#define SCARD_DISCONNECT 0x06
|
|
|
|
#define SCARD_BEGIN_TRANSACTION 0x07
|
|
|
|
#define SCARD_END_TRANSACTION 0x08
|
|
|
|
#define SCARD_TRANSMIT 0x09
|
|
|
|
#define SCARD_CONTROL 0x0A
|
|
|
|
#define SCARD_STATUS 0x0B
|
|
|
|
#define SCARD_GET_STATUS_CHANGE 0x0C
|
|
|
|
#define SCARD_CANCEL 0x0D
|
|
|
|
#define SCARD_CANCEL_TRANSACTION 0x0E
|
|
|
|
#define SCARD_GET_ATTRIB 0x0F
|
|
|
|
#define SCARD_SET_ATTRIB 0x10
|
|
|
|
|
|
|
|
#define SCARD_S_SUCCESS 0x00000000
|
|
|
|
#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001)
|
|
|
|
|
|
|
|
#define SET_UINT32(_data, _offset, _val) do { \
|
|
|
|
(((BYTE*)(_data)) + (_offset))[0] = ((_val) >> 0) & 0xff; \
|
|
|
|
(((BYTE*)(_data)) + (_offset))[1] = ((_val) >> 8) & 0xff; \
|
|
|
|
(((BYTE*)(_data)) + (_offset))[2] = ((_val) >> 16) & 0xff; \
|
|
|
|
(((BYTE*)(_data)) + (_offset))[3] = ((_val) >> 24) & 0xff; } while (0)
|
|
|
|
|
|
|
|
#define GET_UINT32(_data, _offset) \
|
|
|
|
((((BYTE*)(_data)) + (_offset))[0] << 0) | \
|
|
|
|
((((BYTE*)(_data)) + (_offset))[1] << 8) | \
|
|
|
|
((((BYTE*)(_data)) + (_offset))[2] << 16) | \
|
|
|
|
((((BYTE*)(_data)) + (_offset))[3] << 24)
|
|
|
|
|
|
|
|
#define LMIN(_val1, _val2) (_val1) < (_val2) ? (_val1) : (_val2)
|
|
|
|
#define LMAX(_val1, _val2) (_val1) > (_val2) ? (_val1) : (_val2)
|
|
|
|
|
|
|
|
static int g_sck = -1; /* unix domain socket */
|
|
|
|
|
|
|
|
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
/* for pcsc_stringify_error */
|
|
|
|
static char g_error_str[512];
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
static int
|
|
|
|
get_display_num_from_display(const char *display_text)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int index;
|
|
|
|
int mode;
|
|
|
|
int host_index;
|
|
|
|
int disp_index;
|
|
|
|
int scre_index;
|
|
|
|
char host[256];
|
|
|
|
char disp[256];
|
|
|
|
char scre[256];
|
|
|
|
|
|
|
|
memset(host, 0, 256);
|
|
|
|
memset(disp, 0, 256);
|
|
|
|
memset(scre, 0, 256);
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
host_index = 0;
|
|
|
|
disp_index = 0;
|
|
|
|
scre_index = 0;
|
|
|
|
mode = 0;
|
|
|
|
|
|
|
|
while (display_text[index] != 0)
|
|
|
|
{
|
|
|
|
if (display_text[index] == ':')
|
|
|
|
{
|
|
|
|
mode = 1;
|
|
|
|
}
|
|
|
|
else if (display_text[index] == '.')
|
|
|
|
{
|
|
|
|
mode = 2;
|
|
|
|
}
|
|
|
|
else if (mode == 0)
|
|
|
|
{
|
|
|
|
host[host_index] = display_text[index];
|
|
|
|
host_index++;
|
|
|
|
}
|
|
|
|
else if (mode == 1)
|
|
|
|
{
|
|
|
|
disp[disp_index] = display_text[index];
|
|
|
|
disp_index++;
|
|
|
|
}
|
|
|
|
else if (mode == 2)
|
|
|
|
{
|
|
|
|
scre[scre_index] = display_text[index];
|
|
|
|
scre_index++;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
host[host_index] = 0;
|
|
|
|
disp[disp_index] = 0;
|
|
|
|
scre[scre_index] = 0;
|
|
|
|
LLOGLN(0, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]",
|
|
|
|
host, disp, scre));
|
|
|
|
rv = atoi(disp);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
static int
|
|
|
|
connect_to_chansrv(void)
|
|
|
|
{
|
|
|
|
int bytes;
|
|
|
|
int dis;
|
|
|
|
int error;
|
|
|
|
char *xrdp_session;
|
|
|
|
char *xrdp_display;
|
|
|
|
char *home_str;
|
|
|
|
struct sockaddr_un saddr;
|
|
|
|
struct sockaddr *psaddr;
|
|
|
|
|
|
|
|
if (g_sck != -1)
|
|
|
|
{
|
|
|
|
/* already connected */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
xrdp_session = getenv("XRDP_SESSION");
|
|
|
|
if (xrdp_session == NULL)
|
|
|
|
{
|
|
|
|
/* XRDP_SESSION must be set */
|
|
|
|
LLOGLN(0, ("connect_to_chansrv: error, not xrdp session"));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
xrdp_display = getenv("DISPLAY");
|
|
|
|
if (xrdp_display == NULL)
|
|
|
|
{
|
|
|
|
/* DISPLAY must be set */
|
|
|
|
LLOGLN(0, ("connect_to_chansrv: error, display not set"));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
home_str = getenv("HOME");
|
|
|
|
if (home_str == NULL)
|
|
|
|
{
|
|
|
|
/* HOME must be set */
|
|
|
|
LLOGLN(0, ("connect_to_chansrv: error, home not set"));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
dis = get_display_num_from_display(xrdp_display);
|
|
|
|
if (dis < 10)
|
|
|
|
{
|
|
|
|
/* DISPLAY must be > 9 */
|
|
|
|
LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
g_sck = socket(PF_LOCAL, SOCK_STREAM, 0);
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("connect_to_chansrv: error, socket failed"));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
memset(&saddr, 0, sizeof(struct sockaddr_un));
|
|
|
|
saddr.sun_family = AF_UNIX;
|
|
|
|
bytes = sizeof(saddr.sun_path);
|
|
|
|
snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis);
|
|
|
|
saddr.sun_path[bytes - 1] = 0;
|
|
|
|
LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path));
|
|
|
|
psaddr = (struct sockaddr *) &saddr;
|
|
|
|
bytes = sizeof(struct sockaddr_un);
|
|
|
|
error = connect(g_sck, psaddr, bytes);
|
|
|
|
if (error == 0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
perror("connect_to_chansrv");
|
|
|
|
close(g_sck);
|
|
|
|
g_sck = -1;
|
|
|
|
LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
static int
|
|
|
|
send_message(int code, char *data, int bytes)
|
|
|
|
{
|
|
|
|
char header[8];
|
|
|
|
|
|
|
|
SET_UINT32(header, 0, bytes);
|
|
|
|
SET_UINT32(header, 4, code);
|
|
|
|
if (send(g_sck, header, 8, 0) != 8)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (send(g_sck, data, bytes, 0) != bytes)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
static int
|
|
|
|
get_message(int *code, char *data, int *bytes)
|
|
|
|
{
|
|
|
|
char header[8];
|
|
|
|
int max_bytes;
|
|
|
|
|
|
|
|
if (recv(g_sck, header, 8, 0) != 8)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
max_bytes = *bytes;
|
|
|
|
*bytes = GET_UINT32(header, 0);
|
|
|
|
*code = GET_UINT32(header, 4);
|
|
|
|
if (*bytes > max_bytes)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (recv(g_sck, data, *bytes, 0) != *bytes)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2,
|
|
|
|
LPSCARDCONTEXT phContext)
|
|
|
|
{
|
|
|
|
char msg[256];
|
|
|
|
DWORD context;
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardEstablishContext:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
if (connect_to_chansrv() != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEstablishContext: error, can not connect "
|
|
|
|
"to chansrv"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
SET_UINT32(msg, 0, dwScope);
|
|
|
|
if (send_message(SCARD_ESTABLISH_CONTEXT, msg, 4) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEstablishContext: error, send_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 256;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEstablishContext: error, get_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if ((code != SCARD_ESTABLISH_CONTEXT) || (bytes != 8))
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEstablishContext: error, bad code"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
context = GET_UINT32(msg, 0);
|
|
|
|
status = GET_UINT32(msg, 4);
|
|
|
|
LLOGLN(10, ("SCardEstablishContext: got context 0x%8.8x", context));
|
|
|
|
*phContext = context;
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardReleaseContext(SCARDCONTEXT hContext)
|
|
|
|
{
|
|
|
|
char msg[256];
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardReleaseContext:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardReleaseContext: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
SET_UINT32(msg, 0, hContext);
|
|
|
|
if (send_message(SCARD_RELEASE_CONTEXT, msg, 4) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardReleaseContext: error, send_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 256;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardReleaseContext: error, get_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4))
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardReleaseContext: error, bad code"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
status = GET_UINT32(msg, 0);
|
|
|
|
LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status));
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardIsValidContext(SCARDCONTEXT hContext)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("SCardIsValidContext:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardIsValidContext: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
|
|
|
|
DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
|
|
|
|
LPDWORD pdwActiveProtocol)
|
|
|
|
{
|
|
|
|
char msg[256];
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int status;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardConnect:"));
|
|
|
|
LLOGLN(10, ("SCardConnect: hContext %p szReader %s dwShareMode %d "
|
|
|
|
"dwPreferredProtocols %d",
|
|
|
|
(void*)hContext, szReader, dwShareMode, dwPreferredProtocols));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardConnect: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
offset = 0;
|
|
|
|
SET_UINT32(msg, offset, hContext);
|
|
|
|
offset += 4;
|
|
|
|
bytes = strlen(szReader);
|
|
|
|
if (bytes > 99)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardConnect: error, name too long"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
memcpy(msg + offset, szReader, bytes);
|
|
|
|
memset(msg + offset + bytes, 0, 100 - bytes);
|
|
|
|
offset += 100;
|
|
|
|
SET_UINT32(msg, offset, dwShareMode);
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, dwPreferredProtocols);
|
|
|
|
offset += 4;
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
if (send_message(SCARD_CONNECT, msg, offset) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardConnect: error, send_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 256;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardConnect: error, get_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if (code != SCARD_CONNECT)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardConnect: error, bad code"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
*phCard = GET_UINT32(msg, 0);
|
|
|
|
*pdwActiveProtocol = GET_UINT32(msg, 4);
|
|
|
|
status = GET_UINT32(msg, 8);
|
|
|
|
LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status));
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
|
|
|
|
DWORD dwPreferredProtocols, DWORD dwInitialization,
|
|
|
|
LPDWORD pdwActiveProtocol)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardReconnect:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardReconnect: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
|
|
|
|
{
|
|
|
|
char msg[256];
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardDisconnect:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardDisconnect: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
SET_UINT32(msg, 0, hCard);
|
|
|
|
SET_UINT32(msg, 4, dwDisposition);
|
|
|
|
if (send_message(SCARD_DISCONNECT, msg, 8) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardDisconnect: error, send_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 256;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardDisconnect: error, get_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if ((code != SCARD_DISCONNECT) || (bytes != 4))
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardDisconnect: error, bad code"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
status = GET_UINT32(msg, 0);
|
|
|
|
LLOGLN(10, ("SCardDisconnect: got status 0x%8.8x", status));
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardBeginTransaction(SCARDHANDLE hCard)
|
|
|
|
{
|
|
|
|
char msg[256];
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardBeginTransaction:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardBeginTransaction: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
SET_UINT32(msg, 0, hCard);
|
|
|
|
if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardBeginTransaction: error, send_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 256;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardBeginTransaction: error, get_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4))
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardBeginTransaction: error, bad code"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
status = GET_UINT32(msg, 0);
|
|
|
|
LLOGLN(10, ("SCardBeginTransaction: got status 0x%8.8x", status));
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
|
|
|
|
{
|
|
|
|
char msg[256];
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardEndTransaction:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEndTransaction: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
SET_UINT32(msg, 0, hCard);
|
|
|
|
SET_UINT32(msg, 4, dwDisposition);
|
|
|
|
if (send_message(SCARD_END_TRANSACTION, msg, 8) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEndTransaction: error, send_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 256;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEndTransaction: error, get_message"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if ((code != SCARD_END_TRANSACTION) || (bytes != 4))
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardEndTransaction: error, bad code"));
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
status = GET_UINT32(msg, 0);
|
|
|
|
LLOGLN(10, ("SCardEndTransaction: got status 0x%8.8x", status));
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen,
|
|
|
|
LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr,
|
|
|
|
LPDWORD pcbAtrLen)
|
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int status;
|
|
|
|
int offset;
|
|
|
|
int cchReaderLen;
|
|
|
|
int to_copy;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardStatus:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardStatus: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
cchReaderLen = *pcchReaderLen;
|
|
|
|
msg = (char *) malloc(8192);
|
|
|
|
SET_UINT32(msg, 0, hCard);
|
|
|
|
SET_UINT32(msg, 4, cchReaderLen);
|
|
|
|
SET_UINT32(msg, 8, *pcbAtrLen);
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
if (send_message(SCARD_STATUS, msg, 12) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardStatus: error, send_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 8192;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardStatus: error, get_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if (code != SCARD_STATUS)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardStatus: error, bad code"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardStatus: cchReaderLen %d", *pcchReaderLen));
|
|
|
|
offset = 0;
|
|
|
|
*pcchReaderLen = GET_UINT32(msg, offset);
|
|
|
|
LLOGLN(10, ("SCardStatus: cchReaderLen %d", *pcchReaderLen));
|
|
|
|
offset += 4;
|
|
|
|
if (cchReaderLen > 0)
|
|
|
|
{
|
|
|
|
to_copy = cchReaderLen - 1;
|
|
|
|
if (*pcchReaderLen < to_copy)
|
|
|
|
{
|
|
|
|
to_copy = *pcchReaderLen;
|
|
|
|
}
|
|
|
|
memcpy(mszReaderName, msg + offset, to_copy);
|
|
|
|
mszReaderName[to_copy] = 0;
|
|
|
|
}
|
|
|
|
LLOGLN(10, ("SCardStatus: mszReaderName %s", mszReaderName));
|
|
|
|
offset += *pcchReaderLen;
|
|
|
|
*pdwState = GET_UINT32(msg, offset);
|
|
|
|
LLOGLN(10, ("SCardStatus: dwState %d", *pdwState));
|
|
|
|
offset += 4;
|
|
|
|
*pdwProtocol = GET_UINT32(msg, offset);
|
|
|
|
LLOGLN(10, ("SCardStatus: dwProtocol %d", *pdwProtocol));
|
|
|
|
offset += 4;
|
|
|
|
*pcbAtrLen = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, ("SCardStatus: cbAtrLen %d", *pcbAtrLen));
|
|
|
|
memcpy(pbAtr, msg + offset, *pcbAtrLen);
|
|
|
|
offset += *pcbAtrLen;
|
|
|
|
status = GET_UINT32(msg, offset);
|
|
|
|
LLOGLN(10, ("SCardStatus: status %d", status));
|
|
|
|
offset += 4;
|
|
|
|
free(msg);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
|
|
|
|
LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
|
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
int bytes;
|
|
|
|
int code;
|
|
|
|
int index;
|
|
|
|
int offset;
|
|
|
|
int str_len;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardGetStatusChange:"));
|
|
|
|
LLOGLN(10, (" dwTimeout %d cReaders %d", dwTimeout, cReaders));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardGetStatusChange: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
msg = (char *) malloc(8192);
|
|
|
|
SET_UINT32(msg, 0, hContext);
|
|
|
|
SET_UINT32(msg, 4, dwTimeout);
|
|
|
|
SET_UINT32(msg, 8, cReaders);
|
|
|
|
offset = 12;
|
|
|
|
for (index = 0; index < cReaders; index++)
|
|
|
|
{
|
|
|
|
str_len = strlen(rgReaderStates[index].szReader);
|
|
|
|
str_len = LMIN(str_len, 99);
|
|
|
|
memset(msg + offset, 0, 100);
|
|
|
|
memcpy(msg + offset, rgReaderStates[index].szReader, str_len);
|
|
|
|
offset += 100;
|
|
|
|
LLOGLN(10, (" in dwCurrentState %d", rgReaderStates[index].dwCurrentState));
|
|
|
|
SET_UINT32(msg, offset, rgReaderStates[index].dwCurrentState);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, (" in dwEventState %d", rgReaderStates[index].dwEventState));
|
|
|
|
SET_UINT32(msg, offset, rgReaderStates[index].dwEventState);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, (" in cbAtr %d", rgReaderStates[index].cbAtr));
|
|
|
|
SET_UINT32(msg, offset, rgReaderStates[index].cbAtr);
|
|
|
|
offset += 4;
|
|
|
|
memset(msg + offset, 0, 36);
|
|
|
|
memcpy(msg + offset, rgReaderStates[index].rgbAtr, 33);
|
|
|
|
offset += 36;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
if (send_message(SCARD_GET_STATUS_CHANGE, msg, offset) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardGetStatusChange: error, send_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 8192;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardGetStatusChange: error, get_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if (code != SCARD_GET_STATUS_CHANGE)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardGetStatusChange: error, bad code"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
cReaders = GET_UINT32(msg, 0);
|
|
|
|
offset = 4;
|
|
|
|
LLOGLN(10, ("SCardGetStatusChange: got back cReaders %d", cReaders));
|
|
|
|
for (index = 0; index < cReaders; index++)
|
|
|
|
{
|
|
|
|
rgReaderStates[index].dwCurrentState = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, (" out dwCurrentState %d", rgReaderStates[index].dwCurrentState));
|
|
|
|
rgReaderStates[index].dwEventState = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, (" out dwEventState %d", rgReaderStates[index].dwEventState));
|
|
|
|
rgReaderStates[index].cbAtr = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, (" out cbAtr %d", rgReaderStates[index].cbAtr));
|
|
|
|
memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33);
|
|
|
|
offset += 36;
|
|
|
|
}
|
|
|
|
status = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
free(msg);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
|
|
|
|
DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
|
|
|
|
LPDWORD lpBytesReturned)
|
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
int bytes;
|
|
|
|
int code;
|
|
|
|
int offset;
|
|
|
|
int status = 0;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardControl:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardControl: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
LLOGLN(10, ("SCardControl: dwControlCode 0x%8.8x", dwControlCode));
|
|
|
|
LLOGLN(10, ("SCardControl: cbSendLength %d", cbSendLength));
|
|
|
|
LLOGLN(10, ("SCardControl: cbRecvLength %d", cbRecvLength));
|
|
|
|
|
|
|
|
/* #define SCARD_CTL_CODE(code) (0x42000000 + (code))
|
|
|
|
control_code = (control_code & 0x3ffc) >> 2;
|
|
|
|
control_code = SCARD_CTL_CODE(control_code); */
|
|
|
|
|
|
|
|
/* PCSC to Windows control code conversion */
|
|
|
|
dwControlCode = dwControlCode - 0x42000000;
|
|
|
|
dwControlCode = dwControlCode << 2;
|
|
|
|
dwControlCode = dwControlCode | (49 << 16);
|
|
|
|
LLOGLN(10, ("SCardControl: dwControlCode 0x%8.8x", dwControlCode));
|
|
|
|
|
|
|
|
msg = (char *) malloc(8192);
|
|
|
|
offset = 0;
|
|
|
|
SET_UINT32(msg, offset, hCard);
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, dwControlCode);
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, cbSendLength);
|
|
|
|
offset += 4;
|
|
|
|
memcpy(msg + offset, pbSendBuffer, cbSendLength);
|
|
|
|
offset += cbSendLength;
|
|
|
|
SET_UINT32(msg, offset, cbRecvLength);
|
|
|
|
offset += 4;
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
if (send_message(SCARD_CONTROL, msg, offset) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardControl: error, send_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 8192;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardControl: error, get_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if (code != SCARD_CONTROL)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardControl: error, bad code"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
offset = 0;
|
|
|
|
*lpBytesReturned = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
memcpy(pbRecvBuffer, msg + offset, *lpBytesReturned);
|
|
|
|
offset += *lpBytesReturned;
|
|
|
|
status = GET_UINT32(msg, offset);
|
|
|
|
free(msg);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
|
|
|
|
LPCBYTE pbSendBuffer, DWORD cbSendLength,
|
|
|
|
SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
|
|
|
|
LPDWORD pcbRecvLength)
|
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
int bytes;
|
|
|
|
int code;
|
|
|
|
int offset;
|
|
|
|
int status;
|
|
|
|
int extra_len;
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardTransmit:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardTransmit: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
LLOGLN(10, ("SCardTransmit: cbSendLength %d", cbSendLength));
|
|
|
|
LLOGLN(10, ("SCardTransmit: pioRecvPci %p", pioRecvPci));
|
|
|
|
if (pioRecvPci != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("SCardTransmit: pioRecvPci->dwProtocol %d",
|
|
|
|
(int)pioRecvPci->dwProtocol));
|
|
|
|
LLOGLN(10, ("SCardTransmit: pioRecvPci->cbPciLength %d",
|
|
|
|
(int)pioRecvPci->cbPciLength));
|
|
|
|
}
|
|
|
|
msg = (char *) malloc(8192);
|
|
|
|
offset = 0;
|
|
|
|
SET_UINT32(msg, offset, hCard);
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, pioSendPci->dwProtocol);
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, pioSendPci->cbPciLength);
|
|
|
|
offset += 4;
|
|
|
|
extra_len = pioSendPci->cbPciLength - 8;
|
|
|
|
SET_UINT32(msg, offset, extra_len);
|
|
|
|
offset += 4;
|
|
|
|
memcpy(msg + offset, pioSendPci + 1, extra_len);
|
|
|
|
offset += extra_len;
|
|
|
|
SET_UINT32(msg, offset, cbSendLength);
|
|
|
|
offset += 4;
|
|
|
|
memcpy(msg + offset, pbSendBuffer, cbSendLength);
|
|
|
|
offset += cbSendLength;
|
|
|
|
if ((pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8))
|
|
|
|
{
|
|
|
|
SET_UINT32(msg, offset, 0); /* dwProtocol */
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, 0); /* cbPciLength */
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, 0); /* extra_len */
|
|
|
|
offset += 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SET_UINT32(msg, offset, pioRecvPci->dwProtocol);
|
|
|
|
offset += 4;
|
|
|
|
SET_UINT32(msg, offset, pioRecvPci->cbPciLength);
|
|
|
|
offset += 4;
|
|
|
|
extra_len = pioRecvPci->cbPciLength - 8;
|
|
|
|
SET_UINT32(msg, offset, extra_len);
|
|
|
|
offset += 4;
|
|
|
|
memcpy(msg + offset, pioRecvPci + 1, extra_len);
|
|
|
|
offset += extra_len;
|
|
|
|
}
|
|
|
|
SET_UINT32(msg, offset, *pcbRecvLength);
|
|
|
|
offset += 4;
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
if (send_message(SCARD_TRANSMIT, msg, offset) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardTransmit: error, send_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 8192;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardTransmit: error, get_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if (code != SCARD_TRANSMIT)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardTransmit: error, bad code"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
offset = 0;
|
|
|
|
if (pioRecvPci == 0)
|
|
|
|
{
|
|
|
|
offset += 8;
|
|
|
|
extra_len = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
offset += extra_len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pioRecvPci->dwProtocol = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
pioRecvPci->cbPciLength = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
extra_len = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
offset += extra_len;
|
|
|
|
}
|
|
|
|
*pcbRecvLength = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, ("SCardTransmit: cbRecvLength %d", *pcbRecvLength));
|
|
|
|
memcpy(pbRecvBuffer, msg + offset, *pcbRecvLength);
|
|
|
|
offset += *pcbRecvLength;
|
|
|
|
status = GET_UINT32(msg, offset);
|
|
|
|
free(msg);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
|
|
|
|
LPDWORD pcchGroups)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("SCardListReaderGroups:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardListReaderGroups: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
|
|
|
|
LPDWORD pcchReaders)
|
|
|
|
{
|
|
|
|
char* msg;
|
|
|
|
char* reader_names;
|
|
|
|
int reader_names_index;
|
|
|
|
int code;
|
|
|
|
int bytes;
|
|
|
|
int num_readers;
|
|
|
|
int status;
|
|
|
|
int offset;
|
|
|
|
int index;
|
|
|
|
char reader[100];
|
|
|
|
|
|
|
|
LLOGLN(10, ("SCardListReaders:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardListReaders: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
msg = (char *) malloc(8192);
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
SET_UINT32(msg, 0, hContext);
|
|
|
|
if (send_message(SCARD_LIST_READERS, msg, 4) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardListReaders: error, send_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
bytes = 8192;
|
|
|
|
if (get_message(&code, msg, &bytes) != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardListReaders: error, get_message"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
if (code != SCARD_LIST_READERS)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardListReaders: error, bad code"));
|
|
|
|
free(msg);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
offset = 0;
|
|
|
|
num_readers = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
LLOGLN(10, ("SCardListReaders: mszReaders %p pcchReaders %p num_readers %d",
|
|
|
|
mszReaders, pcchReaders, num_readers));
|
|
|
|
reader_names = (char *) malloc(8192);
|
|
|
|
reader_names_index = 0;
|
|
|
|
for (index = 0; index < num_readers; index++)
|
|
|
|
{
|
|
|
|
memcpy(reader, msg + offset, 100);
|
|
|
|
bytes = strlen(reader);
|
|
|
|
memcpy(reader_names + reader_names_index, reader, bytes);
|
|
|
|
reader_names_index += bytes;
|
|
|
|
reader_names[reader_names_index] = 0;
|
|
|
|
reader_names_index++;
|
|
|
|
offset += 100;
|
|
|
|
LLOGLN(10, ("SCardListReaders: readername %s", reader));
|
|
|
|
}
|
|
|
|
reader_names[reader_names_index] = 0;
|
|
|
|
reader_names_index++;
|
|
|
|
status = GET_UINT32(msg, offset);
|
|
|
|
offset += 4;
|
|
|
|
if (pcchReaders != 0)
|
|
|
|
{
|
|
|
|
*pcchReaders = reader_names_index;
|
|
|
|
}
|
|
|
|
if (mszReaders != 0)
|
|
|
|
{
|
|
|
|
memcpy(mszReaders, reader_names, reader_names_index);
|
|
|
|
}
|
|
|
|
free(msg);
|
|
|
|
free(reader_names);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardFreeMemory:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardFreeMemory: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardCancel(SCARDCONTEXT hContext)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardCancel:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardCancel: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
|
|
|
|
LPDWORD pcbAttrLen)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardGetAttrib:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardGetAttrib: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API LONG
|
|
|
|
SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
|
|
|
|
DWORD cbAttrLen)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardSetAttrib:"));
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
LLOGLN(0, ("SCardSetAttrib: error, not connected"));
|
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&g_mutex);
|
|
|
|
pthread_mutex_unlock(&g_mutex);
|
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
PCSC_API char *
|
|
|
|
pcsc_stringify_error(const long code)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("pcsc_stringify_error: 0x%8.8x", (int)code));
|
|
|
|
switch (code)
|
|
|
|
{
|
|
|
|
case SCARD_S_SUCCESS:
|
|
|
|
snprintf(g_error_str, 511, "Command successful.");
|
|
|
|
break;
|
|
|
|
case SCARD_F_INTERNAL_ERROR:
|
|
|
|
snprintf(g_error_str, 511, "Internal error.");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
snprintf(g_error_str, 511, "error 0x%8.8x", (int)code);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_error_str[511] = 0;
|
|
|
|
return g_error_str;
|
|
|
|
}
|