scard.c revision 6e9aa255e3376b2da5824c09c4c62bc233463bfe
/*
rdesktop: A Remote Desktop Protocol client.
Smart Card support
Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
Copyright 2010-2013 Pierre Ossman <ossman@cendio.se> for Cendio AB
Copyright 2011-2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
* other than GPL or LGPL is available it will apply instead, Oracle elects to use only
* the General Public License version 2 (GPLv2) at this time for any software where
* a choice of GPL license versions is made available with the language indicating
* that GPLv2 or any later version may be used, or where a choice of which version
* of the GPL is applied is otherwise unspecified.
*/
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <strings.h>
#include <time.h>
#ifndef MAKE_PROTO
#ifdef __APPLE__
#include <PCSC/wintypes.h>
#include <PCSC/pcsclite.h>
#include <PCSC/winscard.h>
#else
#include <wintypes.h>
#include <pcsclite.h>
#include <winscard.h>
#ifdef PCSCLITE_VERSION_NUMBER
#include <reader.h>
#endif
#endif /* PCSC_OSX */
#include "rdesktop.h"
#include "scard.h"
/* variable segment */
#define SCARD_MAX_MEM 102400
#ifndef SCARD_AUTOALLOCATE
#define SCARD_AUTOALLOCATE -1
#endif
#define OUT_STREAM_SIZE 4096
#ifdef B_ENDIAN
(((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
#else
#define swap32(x) (x)
#define swap16(x) (x)
#endif
static int nameMapCount = 0;
static pthread_t queueHandler;
static pthread_mutex_t queueAccess;
static pthread_cond_t queueEmpty;
static pthread_mutex_t hcardAccess;
static int threadCount = 0;
static void *queue_handler_function(void *data);
/* code segment */
#endif /* MAKE_PROTO */
void
{
}
#ifndef MAKE_PROTO
static RD_NTSTATUS
{
return RD_STATUS_SUCCESS;
}
static RD_NTSTATUS
{
return RD_STATUS_SUCCESS;
}
static RD_NTSTATUS
{
return RD_STATUS_SUCCESS;
}
static RD_NTSTATUS
{
return RD_STATUS_SUCCESS;
}
#endif /* MAKE_PROTO */
/* Enumeration of devices from rdesktop.c */
/* returns numer of units found and initialized. */
/* optarg looks like ':"ReaderName=ReaderAlias"' */
/* when it arrives to this function. */
int
{
char *alias;
int count = 0;
/* code segment */
if (rv != SCARD_S_SUCCESS)
{
error("scard_enum_devices: PCSC service not available\n");
return 0;
}
else
count = 0;
{
error("scard_enum_devices: Can't initialize queue access mutex\n");
return 0;
}
{
error("scard_enum_devices: Can't initialize queue control cv\n");
return 0;
}
{
error("scard_enum_devices: Can't initialize hcard list access mutex\n");
return 0;
}
if (0 !=
{
error("scard_enum_devices: Can't create queue handling Thread\n");
return 0;
}
count++;
(*id)++;
if (*optarg == ':')
{
{
int len;
{
{
vendor = "\0";
}
nameMapCount++;
if (nameMapList == NULL)
else
nameMapCount * sizeof(TSCNameMapRec));
if (vendor)
{
if (len > 0)
{
}
else
}
else
}
}
}
return count;
}
#ifndef MAKE_PROTO
typedef struct _scard_handle_list_t
{
struct _scard_handle_list_t *next;
/* pcsc handles is datatype long which
is arch sizedependent */
long handle;
/* rdp server handles are always 32bit */
static uint32_t g_scard_handle_counter = 0;
static void _scard_handle_list_add(long handle);
static void _scard_handle_list_remove(long handle);
void
_scard_handle_list_add(long handle)
{
/* we dont care of order of list so to simplify the add
we add new items to front of list */
/* lookup first unused handle id */
int overlap = 0;
if (g_scard_handle_counter == 0)
{
if (g_scard_handle_counter == 0 && overlap)
assert(!"broken smartcard client software, handles are not freed and there is no more handles left to allocate.");
if (g_scard_handle_counter == 0)
}
}
void
{
while (item)
{
{
/* unlink from list */
if (prev_item)
else
break;
}
/* store previous item for relinking */
}
}
{
while (item)
{
}
return 0;
}
long
{
while (item)
{
}
return 0;
}
static void *
{
{
if (handle)
{
if (*memHandle)
{
}
return handle + 1;
}
else
return NULL;
}
else
return NULL;
}
static void
{
{
{
if (lcHandle->nextHandle)
if (lcHandle->prevHandle)
{
if (lcHandle->prevHandle)
else
}
}
}
}
static void
{
{
if ((*handle)->prevHandle)
{
}
if ((*handle)->nextHandle)
{
}
}
}
/* ---------------------------------- */
static char *
{
int i;
{
}
return alias;
}
static char *
{
int i;
{
}
return NULL;
}
static char *
{
int i;
{
}
return name;
}
static int
{
int i;
{
return 1;
}
return 0;
}
static void
{
{
}
}
static void
{
if (add > 0)
{
}
}
static void
{
}
static void
{
}
static void
{
if (length <= 0)
{
}
else
{
}
}
static void
{
}
static void
{
if (add > 0)
}
static unsigned int
inString(PMEM_HANDLE * handle, STREAM in, char **destination, SERVER_DWORD dataLength, RD_BOOL wide)
{
char *reader;
/* code segment */
if (wide)
{
int i;
for (i = 0; i < dataLength; i++)
buffer[i] = '?';
else
}
else
{
}
return Result;
}
static unsigned int
{
/* code segment */
if (wide)
{
int i;
for (i = 0; i < dataLength; i++)
{
if (source[i] < 0)
else
}
}
else
{
}
return Result;
}
static void
{
in->p += 0x08;
}
static void
{
if (len > 0)
{
}
}
/* ---------------------------------- */
/* Smart Card processing functions: */
/* ---------------------------------- */
static MYPCSC_DWORD
{
return rc;
}
static MYPCSC_DWORD
{
}
static MYPCSC_DWORD
{
/* code segment */
DEBUG_SCARD(("SCARD: SCardEstablishContext()\n"));
hContext = 0;
if (myHContext)
{
}
if (rv)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
myHContext));
}
out_uint32_le(out, hContext); /* must not be 0 (Seems to be pointer), don't know what is this (I use hContext as value) */
/* i hope it's not a pointer because i just downcasted it - jlj */
return rv;
}
static MYPCSC_DWORD
{
in->p += 0x1C;
myHContext));
if (rv)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
return rv;
}
static MYPCSC_DWORD
{
char *readers;
in->p += 0x1C;
DEBUG_SCARD(("SCARD: SCardIsValidContext(context: 0x%08x [0x%lx])\n",
(unsigned) hContext, myHContext));
if (!readers)
if (rv)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
return rv;
}
static MYPCSC_DWORD
{
#define readerArraySize 1024
in->p += 0x2C;
DEBUG_SCARD(("SCARD: SCardListReaders(context: 0x%08x [0x%lx])\n",
(unsigned) hContext, myHContext));
dataLength = 0;
if (!readers)
readers[0] = '\0';
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
int i;
DEBUG_SCARD(("SCARD: -> Success\n"));
{
}
if (lenSC == 0)
else
while (lenSC > 0)
{
{
}
}
}
return rv;
}
static MYPCSC_DWORD
{
char *szReader;
in->p += 0x1C;
in->p += 0x04;
DEBUG_SCARD(("SCARD: SCardConnect(context: 0x%08x [0x%lx], share: 0x%08x, proto: 0x%08x, reader: \"%s\")\n", (unsigned) hContext, myHContext, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, szReader ? szReader : "NULL"));
hCard = 0;
if (myHCard)
{
}
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success (hcard: 0x%08x [0x%lx])\n",
{
DEBUG_SCARD(("SCARD: Set Attribute ATTR_VENDOR_NAME\n"));
if (hcard)
{
if (hcardFirst)
{
}
hcardFirst = hcard;
}
}
}
/* if the active protocol > 4 billion, this is trouble. odds are low */
return rv;
}
static MYPCSC_DWORD
{
in->p += 0x20;
in->p += 0x04;
in->p += 0x04;
DEBUG_SCARD(("SCARD: SCardReconnect(context: 0x%08x, hcard: 0x%08x [%lx], share: 0x%08x, proto: 0x%08x, init: 0x%08x)\n", (unsigned) hContext, (unsigned) hCard, myHCard, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, (unsigned) dwInitialization));
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
}
return rv;
}
static MYPCSC_DWORD
{
in->p += 0x20;
in->p += 0x04;
in->p += 0x04;
DEBUG_SCARD(("SCARD: SCardDisconnect(context: 0x%08x [0x%lx], hcard: 0x%08x [0x%lx], disposition: 0x%08x)\n", (unsigned) hContext, myHContext, (unsigned) hCard, myHCard, (unsigned) dwDisposition));
while (hcard)
{
{
if (hcardFirst == hcard)
break;
}
}
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
return rv;
}
/* Currently unused */
#if 0
static int
{
int i, recall = 0;
if (rv == SCARD_S_SUCCESS)
{
{
{
recall++;
}
}
}
return recall;
}
static RD_BOOL
{
code >>= 16;
code &= 0x0000FFFF;
return (code % 2);
}
#endif
static void
{
MYPCSC_DWORD i;
{
}
}
static void
{
SERVER_DWORD i;
{
}
}
static MYPCSC_DWORD
{
long i;
in->p += 0x18;
in->p += 0x08;
in->p += 0x04;
DEBUG_SCARD(("SCARD: SCardGetStatusChange(context: 0x%08x [0x%lx], timeout: 0x%08x, count: %d)\n", (unsigned) hContext, myHContext, (unsigned) dwTimeout, (int) dwCount));
if (dwCount > 0)
{
if (!rsArray)
{
}
{
{
in->p += 0x08;
dataLength, wide));
}
DEBUG_SCARD(("SCARD: user: %p, state: 0x%08x, event: 0x%08x\n",
(unsigned) cur->dwEventState));
}
}
else
{
}
if (!myRsArray)
/* Workaround for a bug in pcsclite, timeout value of 0 is handled as INFINIT
but is by Windows PCSC spec. used for polling current state.
*/
if (dwTimeout == 0)
dwTimeout = 1;
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
{
DEBUG_SCARD(("SCARD: user: %p, state: 0x%08x, event: 0x%08x\n",
(unsigned) cur->dwEventState));
/* Do endian swaps... */
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
}
return rv;
}
static MYPCSC_DWORD
{
in->p += 0x1C;
(unsigned long) myHContext));
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
return rv;
}
static MYPCSC_DWORD
{
int i, j, k;
/* The SCARD_ATRMASK_L struct doesn't contain any longs or DWORDs -
no need to split into SERVER_ and MYPCSC_ */
SERVER_DWORD atrMaskCount = 0;
SERVER_DWORD readerCount = 0;
in->p += 0x2C;
if (!pAtrMasks)
if (!rsArray)
DEBUG_SCARD(("SCARD: SCardLocateCardsByATR(context: 0x%08x [0x%08lx], atrs: %d, readers: %d)\n", (unsigned) hContext, (unsigned long) myHContext, (int) atrMaskCount, (int) readerCount));
{
DEBUG_SCARD(("SCARD: ATR: "));
{
DEBUG_SCARD(("%02x%c",
DEBUG_SCARD(("\n"));
DEBUG_SCARD(("SCARD: "));
{
DEBUG_SCARD(("%02x%c",
DEBUG_SCARD(("\n"));
}
i < readerCount; i++, rsCur++)
{
}
if (!ResArray)
{
/* Do endian swaps... */
DEBUG_SCARD(("SCARD: user: %p, state: 0x%08x, event: 0x%08x\n",
(unsigned) rsCur->dwEventState));
}
/* FIXME segfault here. */
if (!myRsArray)
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
{
{
{
{
equal = 0;
break;
}
}
if (equal)
{
DEBUG_SCARD(("SCARD: \"%s\"\n",
DEBUG_SCARD(("SCARD: user: %p, state: 0x%08x, event: 0x%08x\n", rsCur->pvUserData, (unsigned) rsCur->dwCurrentState, (unsigned) rsCur->dwEventState));
}
}
}
}
{
/* Do endian swaps... */
sizeof(SCARD_READERSTATE) - 2 * sizeof(unsigned char *));
}
return rv;
}
static DWORD
{
in->p += 0x30;
DEBUG_SCARD(("SCARD: SCardBeginTransaction(hcard: 0x%08x [0x%lx])\n",
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
return rv;
}
static DWORD
{
in->p += 0x20;
in->p += 0x0C;
DEBUG_SCARD(("SCARD: SCardEndTransaction(hcard: 0x%08x [0x%lx], disposition: 0x%08x)\n",
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
return rv;
}
static void
{
- sizeof(MYPCSC_SCARD_IO_REQUEST) +
sizeof(SERVER_SCARD_IO_REQUEST));
}
static void
{
- sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
}
static DWORD
{
void *tmp;
in->p += 0x14;
in->p += 0x04;
if (!pioSendPci)
if (map[0] & INPUT_LINKED)
in->p += 0x04;
{
if (!tmp)
pioSendPci = tmp;
}
else
{
if (!sendBuf)
}
else
if (cbRecvLength)
{
if (!recvBuf)
}
{
if (!pioRecvPci)
{
if (!tmp)
(void *) ((unsigned char *) tmp +
sizeof(SERVER_SCARD_IO_REQUEST)), linkedLen);
pioRecvPci = tmp;
}
else
}
else
pioRecvPci = NULL;
DEBUG_SCARD(("SCARD: SCardTransmit(hcard: 0x%08x [0x%08lx], send: %d bytes, recv: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) cbSendLength, (int) cbRecvLength));
sizeof(MYPCSC_SCARD_IO_REQUEST)
if (!myPioSendPci)
/* always a send, not always a recv */
if (pioRecvPci)
{
sizeof(MYPCSC_SCARD_IO_REQUEST)
- sizeof(SERVER_SCARD_IO_REQUEST));
if (!myPioRecvPci)
}
else
{
myPioRecvPci = NULL;
}
/* FIXME: handle responses with length > 448 bytes */
if (cbRecvLength > 448)
{
cbRecvLength = 448;
}
if (pioRecvPci)
{
/*
* pscs-lite mishandles this structure in some cases.
* make sure we only copy it if it is valid.
*/
}
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
#if 0
{
out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */
}
else
#endif
#if 0
{
len, 12);
}
#endif
}
return rv;
}
static MYPCSC_DWORD
{
char *readerName;
unsigned char *atr;
in->p += 0x24;
in->p += 0x0C;
in->p += 0x04;
DEBUG_SCARD(("SCARD: SCardStatus(hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) dwReaderLen, (int) dwAtrLen));
#if 1
/*
* Active client sometimes sends a readerlen *just* big enough
* SCardStatus doesn't seem to like this. This is a workaround,
* aka hack!
*/
dwReaderLen = 200;
#endif
if (!readerName)
if (!atr)
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
int i;
DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
(unsigned) dwState, (unsigned) dwProtocol));
DEBUG_SCARD(("SCARD: ATR: "));
for (i = 0; i < dwAtrLen; i++)
{
}
DEBUG_SCARD(("\n"));
dwState = 0x00000006;
else
#if 0
if (dwState & SCARD_SPECIFIC)
dwState = 0x00000006;
else if (dwState & SCARD_NEGOTIABLE)
dwState = 0x00000005;
else
#endif
if (dwState & SCARD_POWERED)
dwState = 0x00000004;
else if (dwState & SCARD_SWALLOWED)
dwState = 0x00000003;
else if (dwState & SCARD_PRESENT)
dwState = 0x00000002;
else if (dwState & SCARD_ABSENT)
dwState = 0x00000001;
else
dwState = 0x00000000;
if (dwAtrLen < 32)
{
}
}
return rv;
}
static MYPCSC_DWORD
{
char *readerName;
unsigned char *atr;
in->p += 0x24;
in->p += 0x0C;
in->p += 0x04;
DEBUG_SCARD(("SCARD: SCardState(hcard: 0x%08x [0x%08lx], atr len: %d bytes)\n",
if (!readerName)
if (!atr)
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
int i;
DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
(unsigned) dwState, (unsigned) dwProtocol));
DEBUG_SCARD(("SCARD: ATR: "));
for (i = 0; i < dwAtrLen; i++)
{
}
DEBUG_SCARD(("\n"));
dwState = 0x00000006;
else
#if 0
if (dwState & SCARD_SPECIFIC)
dwState = 0x00000006;
else if (dwState & SCARD_NEGOTIABLE)
dwState = 0x00000005;
else
#endif
if (dwState & SCARD_POWERED)
dwState = 0x00000004;
else if (dwState & SCARD_SWALLOWED)
dwState = 0x00000003;
else if (dwState & SCARD_PRESENT)
dwState = 0x00000002;
else if (dwState & SCARD_ABSENT)
dwState = 0x00000001;
else
dwState = 0x00000000;
}
return rv;
}
#ifndef WITH_PCSC120
/* Currently unused */
#if 0
static MYPCSC_DWORD
{
char *szGroups;
in->p += 0x20;
in->p += 0x04;
DEBUG_SCARD(("SCARD: SCardListReaderGroups(context: 0x%08x [0x%08lx], groups: %d)\n",
if (!szGroups)
if (rv)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
int i;
char *cur;
DEBUG_SCARD(("SCARD: -> Success\n"));
{
}
}
return rv;
}
#endif
static MYPCSC_DWORD
{
unsigned char *pbAttr;
in->p += 0x20;
in->p += 0x04;
in->p += 0x0C;
DEBUG_SCARD(("SCARD: SCardGetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
if (dwAttrLen > MAX_BUFFER_SIZE)
if (dwAttrLen > SCARD_AUTOALLOCATE)
{
}
else
{
if (!pbAttr)
}
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
if (!pbAttr)
{
}
else
{
}
}
return rv;
}
/* Currently unused */
#if 0
static MYPCSC_DWORD
{
unsigned char *pbAttr;
in->p += 0x20;
in->p += 0x04;
in->p += 0x0C;
DEBUG_SCARD(("SCARD: SCardSetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
if (dwAttrLen > MAX_BUFFER_SIZE)
if (!pbAttr)
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
DEBUG_SCARD(("SCARD: -> Success\n"));
}
return rv;
}
#endif
#endif
static MYPCSC_DWORD
{
unsigned char *pInBuffer, *pOutBuffer;
pOutBuffer = NULL;
in->p += 0x14;
in->p += 0x04;
in->p += 0x04;
in->p += 0x04;
in->p += 0x04;
{
/* read real input size */
if (nInBufferSize > 0)
{
if (!pInBuffer)
}
}
DEBUG_SCARD(("SCARD: SCardControl(context: 0x%08x [0x%08lx], hcard: 0x%08x [0x%08lx], code: 0x%08x, in: %d bytes, out: %d bytes)\n", (unsigned) hContext, (unsigned long) myHContext, (unsigned) hCard, (unsigned long) myHCard, (unsigned) dwControlCode, (int) nInBufferSize, (int) nOutBufferSize));
/* Is this a proper Windows smart card ioctl? */
{
/* Translate to local encoding */
}
else
{
}
#if 0
if (nOutBufferSize > 0)
{
}
else
#endif
nOutBufferRealSize = 1024;
if (!pOutBuffer)
#ifdef WITH_PCSC120
#else
#endif
if (rv != SCARD_S_SUCCESS)
{
DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
}
else
{
}
#ifdef PCSCLITE_VERSION_NUMBER
{
int i;
for (i = 0; i < nBytesReturned / 6; i++)
{
}
}
#endif
if (nBytesReturned > 0)
{
}
return rv;
}
static MYPCSC_DWORD
{
DEBUG_SCARD(("SCARD: SCardAccessStartedEvent()\n"));
return SCARD_S_SUCCESS;
}
static RD_NTSTATUS
{
SERVER_DWORD addToEnd = 0;
/* Processing request */
pStatusCode = out->p;
switch (request)
{
/* SCardEstablishContext */
case SC_ESTABLISH_CONTEXT:
{
break;
}
/* SCardReleaseContext */
case SC_RELEASE_CONTEXT:
{
break;
}
/* SCardIsValidContext */
case SC_IS_VALID_CONTEXT:
{
break;
}
/* SCardListReaders */
case SC_LIST_READERS: /* SCardListReadersA */
{
break;
}
/* ScardConnect */
case SC_CONNECT: /* ScardConnectA */
{
break;
}
/* ScardReconnect */
case SC_RECONNECT:
{
break;
}
/* ScardDisconnect */
case SC_DISCONNECT:
{
break;
}
/* ScardGetStatusChange */
case SC_GET_STATUS_CHANGE: /* SCardGetStatusChangeA */
{
break;
}
/* SCardCancel */
case SC_CANCEL:
{
break;
}
/* SCardLocateCardsByATR */
case SC_LOCATE_CARDS_BY_ATR: /* SCardLocateCardsByATRA */
{
break;
}
/* SCardBeginTransaction */
case SC_BEGIN_TRANSACTION:
{
break;
}
/* SCardBeginTransaction */
case SC_END_TRANSACTION:
{
break;
}
/* ScardTransmit */
case SC_TRANSMIT:
{
break;
}
/* SCardControl */
case SC_CONTROL:
{
break;
}
/* SCardGetAttrib */
#ifndef WITH_PCSC120
case SC_GETATTRIB:
{
break;
}
#endif
case SC_ACCESS_STARTED_EVENT:
{
break;
}
case SC_STATUS: /* SCardStatusA */
{
break;
}
case SC_STATE: /* SCardState */
{
break;
}
default:
{
Result = 0x80100014;
break;
}
}
#if 0
#endif
/* Setting modified variables */
/* setting data size */
/* setting status code */
out->p = pStatusCode;
/* finish */
{
}
return RD_STATUS_SUCCESS;
}
/* Thread functions */
static STREAM
{
if (d != NULL)
{
if (isInputStream)
else if (buffer_size < s->size)
else
d->size = buffer_size;
d->iso_hdr =
d->mcs_hdr =
d->sec_hdr =
d->sec_hdr =
d->rdp_hdr =
d->channel_hdr =
if (isInputStream)
else
}
return d;
}
/* Currently unused */
#if 0
static void
{
if (s != NULL)
{
}
}
#endif
static PSCThreadData
{
if (!data)
return NULL;
else
{
{
return NULL;
}
SC_FALSE);
{
return NULL;
}
if (queueLast)
if (!queueFirst)
queueFirst = data;
}
return data;
}
static void
{
if (data)
{
}
}
static PSCThreadData
{
while (queueFirst == NULL)
Result = queueFirst;
if (!queueFirst)
{
}
return Result;
}
static void
{
size_t buffer_len = 0;
/* if iorequest belongs to another epoch, don't send response
back to server due to it's considered as abdonend.
*/
}
static void *
{
while (1)
{
}
return NULL;
}
static void
{
int Result = 0;
{
{
/* double check with lock held.... */
{
continue;
}
/* Wake up thread */
return;
}
}
if (!cur)
return;
threadCount++;
if (0 != Result)
{
}
threadList = cur;
}
static void *
queue_handler_function(void *data)
{
while (1)
{
{
case SC_ESTABLISH_CONTEXT:
case SC_RELEASE_CONTEXT:
{
break;
}
default:
{
break;
}
}
}
return NULL;
}
static RD_NTSTATUS
{
return RD_STATUS_PENDING | 0xC0000000;
else
return RD_STATUS_NO_SUCH_FILE;
}
DEVICE_FNS scard_fns = {
};
#endif /* MAKE_PROTO */
void
scard_lock(int lock)
{
if (!scard_mutex)
{
int i;
for (i = 0; i < SCARD_LOCK_LAST; i++)
{
scard_mutex[i] = NULL;
}
}
if (!scard_mutex[lock])
{
}
}
void
scard_unlock(int lock)
{
}
void
{
curDevice = 0;
curId = 0;
curBytesOut = 0;
}