#if defined (HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#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>
#include <poll.h>
#include "string_calls.h"
#define PCSC_API
typedef unsigned char BYTE;
typedef BYTE *LPBYTE;
#ifdef __APPLE__
typedef int LONG ;
typedef unsigned int DWORD;
#else
typedef long LONG ;
typedef unsigned long DWORD;
#endif
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 0 x0001 /**< T=0 active protocol. */
#define SCARD_PROTOCOL_T1 0 x0002 /**< T=1 active protocol. */
#define SCARD_PROTOCOL_RAW 0 x0004 /**< Raw active protocol. */
PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
#define LLOG_LEVEL 5
#define LLOGLN(_level, _args) \
do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n" ); } } while (0 )
#define LHEXDUMP(_level, _args) \
do { if (_level < LLOG_LEVEL) { lhexdump _args ; } } while (0 )
#define SCARD_ESTABLISH_CONTEXT 0 x01
#define SCARD_RELEASE_CONTEXT 0 x02
#define SCARD_LIST_READERS 0 x03
#define SCARD_CONNECT 0 x04
#define SCARD_RECONNECT 0 x05
#define SCARD_DISCONNECT 0 x06
#define SCARD_BEGIN_TRANSACTION 0 x07
#define SCARD_END_TRANSACTION 0 x08
#define SCARD_TRANSMIT 0 x09
#define SCARD_CONTROL 0 x0A
#define SCARD_STATUS 0 x0B
#define SCARD_GET_STATUS_CHANGE 0 x0C
#define SCARD_CANCEL 0 x0D
#define SCARD_CANCEL_TRANSACTION 0 x0E
#define SCARD_GET_ATTRIB 0 x0F
#define SCARD_SET_ATTRIB 0 x10
#define SCARD_S_SUCCESS 0 x00000000
#define SCARD_F_INTERNAL_ERROR ((LONG )0 x80100001)
#define SET_UINT32(_data, _offset, _val) do { \
(((BYTE*)(_data)) + (_offset))[0 ] = ((_val) >> 0 ) & 0 xff; \
(((BYTE*)(_data)) + (_offset))[1 ] = ((_val) >> 8 ) & 0 xff; \
(((BYTE*)(_data)) + (_offset))[2 ] = ((_val) >> 16 ) & 0 xff; \
(((BYTE*)(_data)) + (_offset))[3 ] = ((_val) >> 24 ) & 0 xff; } 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 ];
/*****************************************************************************/
/* produce a hex dump */
static void
lhexdump(void *p, int len)
{
unsigned char *line;
int i;
int thisline;
int offset;
line = (unsigned char *)p;
offset = 0 ;
while (offset < len)
{
printf("%04x " , offset);
thisline = len - offset;
if (thisline > 16 )
{
thisline = 16 ;
}
for (i = 0 ; i < thisline; i++)
{
printf("%02x " , line[i]);
}
for (; i < 16 ; i++)
{
printf(" " );
}
for (i = 0 ; i < thisline; i++)
{
printf("%c" , (line[i] >= 0 x20 && line[i] < 0 x7f) ? line[i] : '.' );
}
printf("\n" );
offset += thisline;
line += thisline;
}
}
/*****************************************************************************/
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 = g_get_display_num_from_display(xrdp_display);
if (dis < 0 )
{
LLOGLN(0 , ("connect_to_chansrv: error, don't understand DISPLAY='%s'" ,
xrdp_display));
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(10 , ("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 ];
pthread_mutex_lock(&g_mutex);
SET_UINT32(header, 0 , bytes);
SET_UINT32(header, 4 , code);
if (send(g_sck, header, 8 , 0 ) != 8 )
{
pthread_mutex_unlock(&g_mutex);
return 1 ;
}
if (send(g_sck, data, bytes, 0 ) != bytes)
{
pthread_mutex_unlock(&g_mutex);
return 1 ;
}
LLOGLN(10 , ("send_message:" ));
LHEXDUMP(10 , (data, bytes));
pthread_mutex_unlock(&g_mutex);
return 0 ;
}
/*****************************************************************************/
static int
get_message(int *code, char *data, int *bytes)
{
char header[8 ];
int max_bytes;
int error;
int recv_rv;
int lcode;
struct pollfd pollfd;
LLOGLN(10 , ("get_message:" ));
while (1 )
{
LLOGLN(10 , ("get_message: loop" ));
pollfd.fd = g_sck;
pollfd.events = POLLIN;
pollfd.revents = 0 ;
error = poll(&pollfd, 1 , 1000 );
if (error == 1 )
{
pthread_mutex_lock(&g_mutex);
pollfd.fd = g_sck;
pollfd.events = POLLIN;
pollfd.revents = 0 ;
error = poll(&pollfd, 1 , 0 );
if (error == 1 )
{
/* just take a look at the next message */
recv_rv = recv(g_sck, header, 8 , MSG_PEEK);
if (recv_rv == 8 )
{
lcode = GET_UINT32(header, 4 );
if (lcode == *code)
{
/* still have mutex lock */
break ;
}
else
{
LLOGLN(10 , ("get_message: lcode %d *code %d" ,
lcode, *code));
}
}
else if (recv_rv == 0 )
{
pthread_mutex_unlock(&g_mutex);
LLOGLN(0 , ("get_message: recv_rv 0, disconnect" ));
return 1 ;
}
else
{
LLOGLN(10 , ("get_message: recv_rv %d" , recv_rv));
}
}
else
{
LLOGLN(10 , ("get_message: select return %d" , error));
}
pthread_mutex_unlock(&g_mutex);
usleep(1000 );
}
}
if (recv(g_sck, header, 8 , 0 ) != 8 )
{
pthread_mutex_unlock(&g_mutex);
return 1 ;
}
max_bytes = *bytes;
*bytes = GET_UINT32(header, 0 );
*code = GET_UINT32(header, 4 );
if (*bytes > max_bytes)
{
pthread_mutex_unlock(&g_mutex);
return 1 ;
}
if (recv(g_sck, data, *bytes, 0 ) != *bytes)
{
pthread_mutex_unlock(&g_mutex);
return 1 ;
}
pthread_mutex_unlock(&g_mutex);
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;
}
}
SET_UINT32(msg, 0 , dwScope);
if (send_message(SCARD_ESTABLISH_CONTEXT, msg, 4 ) != 0 )
{
LLOGLN(0 , ("SCardEstablishContext: error, send_message" ));
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256 ;
code = SCARD_ESTABLISH_CONTEXT;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardEstablishContext: error, get_message" ));
return SCARD_F_INTERNAL_ERROR;
}
if ((code != SCARD_ESTABLISH_CONTEXT) || (bytes != 8 ))
{
LLOGLN(0 , ("SCardEstablishContext: error, bad code" ));
return SCARD_F_INTERNAL_ERROR;
}
context = GET_UINT32(msg, 0 );
status = GET_UINT32(msg, 4 );
LLOGLN(10 , ("SCardEstablishContext: got context 0x%8.8x" , (int )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;
}
SET_UINT32(msg, 0 , hContext);
if (send_message(SCARD_RELEASE_CONTEXT, msg, 4 ) != 0 )
{
LLOGLN(0 , ("SCardReleaseContext: error, send_message" ));
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256 ;
code = SCARD_RELEASE_CONTEXT;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardReleaseContext: error, get_message" ));
return SCARD_F_INTERNAL_ERROR;
}
if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4 ))
{
LLOGLN(0 , ("SCardReleaseContext: error, bad code" ));
return SCARD_F_INTERNAL_ERROR;
}
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;
}
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 0x%8.8x szReader %s dwShareMode %d "
"dwPreferredProtocols %d" ,
(int )hContext, szReader, (int )dwShareMode, (int )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 ;
if (send_message(SCARD_CONNECT, msg, offset) != 0 )
{
LLOGLN(0 , ("SCardConnect: error, send_message" ));
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256 ;
code = SCARD_CONNECT;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardConnect: error, get_message" ));
return SCARD_F_INTERNAL_ERROR;
}
if (code != SCARD_CONNECT)
{
LLOGLN(0 , ("SCardConnect: error, bad code" ));
return SCARD_F_INTERNAL_ERROR;
}
*phCard = GET_UINT32(msg, 0 );
*pdwActiveProtocol = GET_UINT32(msg, 4 );
status = GET_UINT32(msg, 8 );
LLOGLN(10 , ("SCardConnect: got status 0x%8.8x hCard 0x%8.8x "
"dwActiveProtocol %d" ,
status, (int )*phCard, (int )*pdwActiveProtocol));
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;
}
return SCARD_S_SUCCESS;
}
/*****************************************************************************/
PCSC_API LONG
SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
char msg[256 ];
int code;
int bytes;
int status;
LLOGLN(10 , ("SCardDisconnect: hCard 0x%8.8x dwDisposition %d" ,
(int )hCard, (int )dwDisposition));
if (g_sck == -1 )
{
LLOGLN(0 , ("SCardDisconnect: error, not connected" ));
return SCARD_F_INTERNAL_ERROR;
}
SET_UINT32(msg, 0 , hCard);
SET_UINT32(msg, 4 , dwDisposition);
if (send_message(SCARD_DISCONNECT, msg, 8 ) != 0 )
{
LLOGLN(0 , ("SCardDisconnect: error, send_message" ));
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256 ;
code = SCARD_DISCONNECT;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardDisconnect: error, get_message" ));
return SCARD_F_INTERNAL_ERROR;
}
if ((code != SCARD_DISCONNECT) || (bytes != 4 ))
{
LLOGLN(0 , ("SCardDisconnect: error, bad code" ));
return SCARD_F_INTERNAL_ERROR;
}
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: hCard 0x%8.8x" , (int )hCard));
if (hCard == 0 )
{
LLOGLN(0 , ("SCardBeginTransaction: error, bad hCard" ));
return SCARD_F_INTERNAL_ERROR;
}
if (g_sck == -1 )
{
LLOGLN(0 , ("SCardBeginTransaction: error, not connected" ));
return SCARD_F_INTERNAL_ERROR;
}
SET_UINT32(msg, 0 , hCard);
if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4 ) != 0 )
{
LLOGLN(0 , ("SCardBeginTransaction: error, send_message" ));
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256 ;
code = SCARD_BEGIN_TRANSACTION;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardBeginTransaction: error, get_message" ));
return SCARD_F_INTERNAL_ERROR;
}
if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4 ))
{
LLOGLN(0 , ("SCardBeginTransaction: error, bad code" ));
return SCARD_F_INTERNAL_ERROR;
}
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;
}
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" ));
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256 ;
code = SCARD_END_TRANSACTION;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardEndTransaction: error, get_message" ));
return SCARD_F_INTERNAL_ERROR;
}
if ((code != SCARD_END_TRANSACTION) || (bytes != 4 ))
{
LLOGLN(0 , ("SCardEndTransaction: error, bad code" ));
return SCARD_F_INTERNAL_ERROR;
}
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 (hCard == 0 )
{
LLOGLN(10 , ("SCardStatus: error, bad hCard" ));
return SCARD_F_INTERNAL_ERROR;
}
if (g_sck == -1 )
{
LLOGLN(0 , ("SCardStatus: error, not connected" ));
return SCARD_F_INTERNAL_ERROR;
}
LLOGLN(10 , (" hCard 0x%8.8x" , (int )hCard));
LLOGLN(10 , (" cchReaderLen %d" , (int )*pcchReaderLen));
LLOGLN(10 , (" cbAtrLen %d" , (int )*pcbAtrLen));
cchReaderLen = *pcchReaderLen;
msg = (char *) malloc(8192 );
SET_UINT32(msg, 0 , hCard);
SET_UINT32(msg, 4 , cchReaderLen);
SET_UINT32(msg, 8 , *pcbAtrLen);
if (send_message(SCARD_STATUS, msg, 12 ) != 0 )
{
LLOGLN(0 , ("SCardStatus: error, send_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
bytes = 8192 ;
code = SCARD_STATUS;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardStatus: error, get_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
if (code != SCARD_STATUS)
{
LLOGLN(0 , ("SCardStatus: error, bad code" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
LLOGLN(10 , ("SCardStatus: cchReaderLen in %d" , (int )*pcchReaderLen));
offset = 0 ;
*pcchReaderLen = GET_UINT32(msg, offset);
LLOGLN(10 , ("SCardStatus: cchReaderLen out %d" , (int )*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 out %s" , mszReaderName));
offset += *pcchReaderLen;
*pdwState = GET_UINT32(msg, offset);
if (*pdwState == 1 )
{
*pdwState = 0 x34;
}
LLOGLN(10 , ("SCardStatus: dwState %d" , (int )*pdwState));
offset += 4 ;
*pdwProtocol = GET_UINT32(msg, offset);
LLOGLN(10 , ("SCardStatus: dwProtocol %d" , (int )*pdwProtocol));
offset += 4 ;
*pcbAtrLen = GET_UINT32(msg, offset);
offset += 4 ;
LLOGLN(10 , ("SCardStatus: cbAtrLen %d" , (int )*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;
const char *rname;
int bytes;
int code;
int index;
int offset;
int str_len;
int status;
int dwCurrentState;
int dwEventState;
int cbAtr;
char atr[36 ];
LLOGLN(10 , ("SCardGetStatusChange:" ));
LLOGLN(10 , (" dwTimeout %d cReaders %d" , (int )dwTimeout, (int )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++)
{
rgReaderStates[index].dwCurrentState &= ~2 ;
rgReaderStates[index].dwEventState &= ~2 ;
rname = rgReaderStates[index].szReader;
if (strcmp(rname, "\\\\?PnP?\\Notification" ) == 0 )
{
LLOGLN(10 , (" \\\\?PnP?\\Notification present" ));
dwCurrentState = 0 ;
dwEventState = 0 ;
cbAtr = 0 ;
memset(atr, 0 , 36 );
}
else
{
dwCurrentState = rgReaderStates[index].dwCurrentState;
dwEventState = rgReaderStates[index].dwEventState;
cbAtr = rgReaderStates[index].cbAtr;
memset(atr, 0 , 36 );
memcpy(atr, rgReaderStates[index].rgbAtr, 33 );
}
str_len = strlen(rname);
str_len = LMIN(str_len, 99 );
memset(msg + offset, 0 , 100 );
memcpy(msg + offset, rname, str_len);
LLOGLN(10 , (" in szReader %s" , rname));
offset += 100 ;
LLOGLN(10 , (" in dwCurrentState 0x%8.8x" , dwCurrentState));
SET_UINT32(msg, offset, dwCurrentState);
offset += 4 ;
LLOGLN(10 , (" in dwEventState 0x%8.8x" , dwEventState));
SET_UINT32(msg, offset, dwEventState);
offset += 4 ;
LLOGLN(10 , (" in cbAtr %d" , cbAtr));
SET_UINT32(msg, offset, cbAtr);
offset += 4 ;
memcpy(msg + offset, atr, 36 );
offset += 36 ;
}
if (send_message(SCARD_GET_STATUS_CHANGE, msg, offset) != 0 )
{
LLOGLN(0 , ("SCardGetStatusChange: error, send_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
bytes = 8192 ;
code = SCARD_GET_STATUS_CHANGE;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardGetStatusChange: error, get_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
if (code != SCARD_GET_STATUS_CHANGE)
{
LLOGLN(0 , ("SCardGetStatusChange: error, bad code" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
cReaders = GET_UINT32(msg, 0 );
offset = 4 ;
LLOGLN(10 , ("SCardGetStatusChange: got back cReaders %d" , (int )cReaders));
for (index = 0 ; index < cReaders; index++)
{
rname = rgReaderStates[index].szReader;
#if 1
if (strcmp(rname, "\\\\?PnP?\\Notification" ) == 0 )
{
LLOGLN(10 , (" out szReader %s" , rgReaderStates[index].szReader));
dwCurrentState = GET_UINT32(msg, offset);
rgReaderStates[index].dwCurrentState = dwCurrentState;
offset += 4 ;
LLOGLN(10 , (" out dwCurrentState 0x%8.8x" , dwCurrentState));
// disable PnP for now
dwEventState = 4 ; // GET_UINT32(msg, offset);
rgReaderStates[index].dwEventState = dwEventState;
offset += 4 ;
LLOGLN(10 , (" out dwEventState 0x%8.8x" , dwEventState));
cbAtr = GET_UINT32(msg, offset);
rgReaderStates[index].cbAtr = cbAtr;
offset += 4 ;
LLOGLN(10 , (" out cbAtr %d" , cbAtr));
memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33 );
offset += 36 ;
}
else
#endif
{
LLOGLN(10 , (" out szReader %s" , rgReaderStates[index].szReader));
dwCurrentState = GET_UINT32(msg, offset);
rgReaderStates[index].dwCurrentState = dwCurrentState;
offset += 4 ;
LLOGLN(10 , (" out dwCurrentState 0x%8.8x" , dwCurrentState));
dwEventState = GET_UINT32(msg, offset);
rgReaderStates[index].dwEventState = dwEventState;
offset += 4 ;
LLOGLN(10 , (" out dwEventState 0x%8.8x" , dwEventState));
cbAtr = GET_UINT32(msg, offset);
rgReaderStates[index].cbAtr = cbAtr;
offset += 4 ;
LLOGLN(10 , (" out cbAtr %d" , 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 , (" hCard 0x%8.8x" , (int )hCard));
LLOGLN(10 , (" dwControlCode 0x%8.8x" , (int )dwControlCode));
LLOGLN(10 , (" cbSendLength %d" , (int )cbSendLength));
LLOGLN(10 , (" cbRecvLength %d" , (int )cbRecvLength));
/* #define SCARD_CTL_CODE(code) (0x42000000 + (code))
control_code = ( control_code & 0 x3ffc ) > > 2 ;
control_code = SCARD_CTL_CODE(control_code); */
/* PCSC to Windows control code conversion */
dwControlCode = dwControlCode - 0 x42000000;
dwControlCode = dwControlCode << 2 ;
dwControlCode = dwControlCode | (49 << 16 );
LLOGLN(10 , (" MS dwControlCode 0x%8.8d" , (int )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 ;
if (send_message(SCARD_CONTROL, msg, offset) != 0 )
{
LLOGLN(0 , ("SCardControl: error, send_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
bytes = 8192 ;
code = SCARD_CONTROL;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardControl: error, get_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
if (code != SCARD_CONTROL)
{
LLOGLN(0 , ("SCardControl: error, bad code" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
offset = 0 ;
*lpBytesReturned = GET_UINT32(msg, offset);
LLOGLN(10 , (" cbRecvLength %d" , (int )*lpBytesReturned));
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;
int got_recv_pci;
LLOGLN(10 , ("SCardTransmit:" ));
if (g_sck == -1 )
{
LLOGLN(0 , ("SCardTransmit: error, not connected" ));
return SCARD_F_INTERNAL_ERROR;
}
LLOGLN(10 , (" hCard 0x%8.8x" , (int )hCard));
LLOGLN(10 , (" cbSendLength %d" , (int )cbSendLength));
LLOGLN(10 , (" cbRecvLength %d" , (int )*pcbRecvLength));
LLOGLN(10 , (" pioSendPci->dwProtocol %d" , (int )(pioSendPci->dwProtocol)));
LLOGLN(10 , (" pioSendPci->cbPciLength %d" , (int )(pioSendPci->cbPciLength)));
LLOGLN(10 , (" pioRecvPci %p" , pioRecvPci));
if (pioRecvPci != 0 )
{
LLOGLN(10 , (" pioRecvPci->dwProtocol %d" , (int )(pioRecvPci->dwProtocol)));
LLOGLN(10 , (" 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); */
SET_UINT32(msg, offset, 8 );
offset += 4 ;
/* extra_len = pioSendPci->cbPciLength - 8; */
extra_len = 0 ;
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;
got_recv_pci = (pioRecvPci != NULL) && (pioRecvPci->cbPciLength >= 8 );
// TODO figure out why recv pci does not work
got_recv_pci = 0 ;
if (got_recv_pci == 0 )
{
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 ;
if (send_message(SCARD_TRANSMIT, msg, offset) != 0 )
{
LLOGLN(0 , ("SCardTransmit: error, send_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
bytes = 8192 ;
code = SCARD_TRANSMIT;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardTransmit: error, get_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
if (code != SCARD_TRANSMIT)
{
LLOGLN(0 , ("SCardTransmit: error, bad code" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
offset = 0 ;
if (got_recv_pci == 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 , (" cbRecvLength %d" , (int )*pcbRecvLength));
memcpy(pbRecvBuffer, msg + offset, *pcbRecvLength);
LHEXDUMP(10 , (pbRecvBuffer, *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;
}
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;
int val;
int llen;
char reader[100 ];
LLOGLN(10 , ("SCardListReaders:" ));
LLOGLN(10 , ("SCardListReaders: mszGroups %s" , mszGroups));
LLOGLN(10 , ("SCardListReaders: *pcchReaders %d" , (int )*pcchReaders));
if (g_sck == -1 )
{
LLOGLN(0 , ("SCardListReaders: error, not connected" ));
return SCARD_F_INTERNAL_ERROR;
}
if ((mszGroups == NULL) && (mszReaders == NULL))
{
*pcchReaders = 0 ;
}
msg = (char *) malloc(8192 );
offset = 0 ;
SET_UINT32(msg, offset, hContext);
offset += 4 ;
if (mszGroups != 0 )
{
unsigned int bytes_groups = strlen(mszGroups);
SET_UINT32(msg, offset, bytes_groups);
offset += 4 ;
memcpy(msg + offset, mszGroups, bytes_groups);
offset += bytes_groups;
}
else
{
SET_UINT32(msg, offset, 0 );
offset += 4 ;
}
val = *pcchReaders;
SET_UINT32(msg, offset, val);
offset += 4 ;
if (send_message(SCARD_LIST_READERS, msg, offset) != 0 )
{
LLOGLN(0 , ("SCardListReaders: error, send_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
bytes = 8192 ;
code = SCARD_LIST_READERS;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardListReaders: error, get_message" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
if (code != SCARD_LIST_READERS)
{
LLOGLN(0 , ("SCardListReaders: error, bad code" ));
free(msg);
return SCARD_F_INTERNAL_ERROR;
}
offset = 0 ;
llen = GET_UINT32(msg, offset);
offset += 4 ;
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);
LLOGLN(10 , ("SCardListReaders: status 0x%8.8x" , status));
offset += 4 ;
if (mszReaders == 0 )
{
reader_names_index = llen / 2 ;
}
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;
}
return SCARD_S_SUCCESS;
}
/*****************************************************************************/
PCSC_API LONG
SCardCancel(SCARDCONTEXT hContext)
{
char msg[256 ];
int code;
int bytes;
int status;
LLOGLN(10 , ("SCardCancel:" ));
if (g_sck == -1 )
{
LLOGLN(0 , ("SCardCancel: error, not connected" ));
return SCARD_F_INTERNAL_ERROR;
}
SET_UINT32(msg, 0 , hContext);
if (send_message(SCARD_CANCEL, msg, 4 ) != 0 )
{
LLOGLN(0 , ("SCardCancel: error, send_message" ));
return SCARD_F_INTERNAL_ERROR;
}
bytes = 256 ;
code = SCARD_CANCEL;
if (get_message(&code, msg, &bytes) != 0 )
{
LLOGLN(0 , ("SCardCancel: error, get_message" ));
return SCARD_F_INTERNAL_ERROR;
}
if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4 ))
{
LLOGLN(0 , ("SCardCancel: error, bad code" ));
return SCARD_F_INTERNAL_ERROR;
}
status = GET_UINT32(msg, 0 );
LLOGLN(10 , ("SCardCancel: got status 0x%8.8x" , status));
return status;
}
/*****************************************************************************/
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;
}
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;
}
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;
}
Messung V0.5 in Prozent C=97 H=94 G=95
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet am 2026-07-10)
¤
*© Formatika GbR, Deutschland