[Pcsclite-cvs-commit] r4553 - in /trunk/PCSC/src: Makefile.am pcscd.h.in pcscdaemon.c readerfactory.c readerfactory.h winscard_clnt.c winscard_svc.c winscard_svc.h

rousseau at users.alioth.debian.org rousseau at users.alioth.debian.org
Tue Nov 17 14:48:46 UTC 2009


Author: rousseau
Date: Tue Nov 17 14:48:46 2009
New Revision: 4553

URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=4553
Log:
Use lists instead of fixed size arrays to store handles.

It is now possible to have:
- 200 simultaneous PC/SC clients instead of 16
- 200 SCardConnect per client instead of 16
- 200 clients per reader instead of 16

The default value of 200 can be changed by giving an argument to pcscd
--max-thread
--max-card-handle-per-thread
--max-card-handle-per-reader

Thanks to Jean-Luc Giraud for the big patch

Modified:
    trunk/PCSC/src/Makefile.am
    trunk/PCSC/src/pcscd.h.in
    trunk/PCSC/src/pcscdaemon.c
    trunk/PCSC/src/readerfactory.c
    trunk/PCSC/src/readerfactory.h
    trunk/PCSC/src/winscard_clnt.c
    trunk/PCSC/src/winscard_svc.c
    trunk/PCSC/src/winscard_svc.h

Modified: trunk/PCSC/src/Makefile.am
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/Makefile.am?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/Makefile.am (original)
+++ trunk/PCSC/src/Makefile.am Tue Nov 17 14:48:46 2009
@@ -13,6 +13,7 @@
 	debug.h \
 	error.c \
 	winscard_clnt.c \
+	simclist.c \
 	strlcat.c \
 	strlcpy.c \
 	sys_unix.c \
@@ -20,7 +21,7 @@
 	utils.c \
 	winscard_msg.c
 libpcsclite_la_LDFLAGS = -version-info 1:0:0
-libpcsclite_la_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) -DLIBPCSCLITE
+libpcsclite_la_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) -DLIBPCSCLITE -DSIMCLIST_NO_DUMPRESTORE
 libpcsclite_la_LIBADD = $(COREFOUNDATION) $(LIBSMARTCARD) $(LIBDL) \
 	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
 

Modified: trunk/PCSC/src/pcscd.h.in
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/pcscd.h.in?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/pcscd.h.in (original)
+++ trunk/PCSC/src/pcscd.h.in Tue Nov 17 14:48:46 2009
@@ -37,17 +37,9 @@
 #define PCSCLITE_STATUS_POLL_RATE	400000		/**< Status polling rate */
 #define PCSCLITE_LOCK_POLL_RATE		100000		/**< Lock polling rate */
 
-/** Maximum applications */
-#define PCSCLITE_MAX_APPLICATIONS			16
-/** Maximum contexts by application */
-#define PCSCLITE_MAX_APPLICATION_CONTEXTS		16
-/** Maximum of applications contexts that pcscd can accept */
-#define PCSCLITE_MAX_APPLICATIONS_CONTEXTS \
-	PCSCLITE_MAX_APPLICATIONS * PCSCLITE_MAX_APPLICATION_CONTEXTS
-/** Maximum channels on a reader context */
-#define PCSCLITE_MAX_READER_CONTEXT_CHANNELS		16
-/** Maximum channels on an application context */
-#define PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS	16
+#define PCSC_MAX_CONTEXT_THREADS 200
+#define PCSC_MAX_CONTEXT_CARD_HANDLES 200
+#define PCSC_MAX_READER_HANDLES 200
 
 #define PCSCLITE_STATUS_WAIT		200000	/**< Status Change Sleep */
 #define MAX_LIBNAME			100

Modified: trunk/PCSC/src/pcscdaemon.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/pcscdaemon.c?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/pcscdaemon.c (original)
+++ trunk/PCSC/src/pcscdaemon.c Tue Nov 17 14:48:46 2009
@@ -75,7 +75,8 @@
  * If the message is valid, \c CreateContextThread() is called to serve this
  * request.
  */
-static void SVCServiceRunLoop(void)
+static void SVCServiceRunLoop(int customMaxThreadCounter,
+	int customMaxThreadCardHandles)
 {
 	int rsp;
 	LONG rv;
@@ -98,7 +99,7 @@
 	/*
 	 * Initialize the contexts structure
 	 */
-	rv = ContextsInitialize();
+	rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
 
 	if (rv == -1)
 	{
@@ -176,6 +177,7 @@
 
 			/* now stop all the drivers */
 			RFCleanupReaders();
+			ContextsDeinitialize();
 			exit(0);
 		}
 	}
@@ -188,6 +190,9 @@
 	char HotPlug;
 	char *newReaderConfig;
 	struct stat fStatBuf;
+	unsigned int customMaxThreadCounter = 0;
+	unsigned int customMaxReaderHandles = 0;
+	unsigned int customMaxThreadCardHandles = 0;
 	int opt;
 #ifdef HAVE_GETOPT_LONG
 	int option_index = 0;
@@ -203,10 +208,13 @@
 		{"critical", 0, NULL, 'C'},
 		{"hotplug", 0, NULL, 'H'},
 		{"force-reader-polling", optional_argument, NULL, 0},
+		{"max-thread", 1, NULL, 't'},
+		{"max-card-handle-per-thread", 1, NULL, 's'},
+		{"max-card-handle-per-reader", 1, NULL, 'r'},
 		{NULL, 0, NULL, 0}
 	};
 #endif
-#define OPT_STRING "c:fdhvaeCH"
+#define OPT_STRING "c:fdhvaeCHt:r:s:"
 
 	rv = 0;
 	newReaderConfig = NULL;
@@ -291,6 +299,24 @@
 				HotPlug = TRUE;
 				break;
 
+			case 't':
+				customMaxThreadCounter = optarg ? atoi(optarg) : 0; 
+				Log2(PCSC_LOG_INFO, "setting customMaxThreadCounter to: %d",
+					customMaxThreadCounter);
+				break;
+
+			case 'r':
+				customMaxReaderHandles = optarg ? atoi(optarg) : 0; 
+				Log2(PCSC_LOG_INFO, "setting customMaxReaderHandles to: %d",
+					customMaxReaderHandles);
+				break;
+
+			case 's':
+				customMaxThreadCardHandles = optarg ? atoi(optarg) : 0; 
+				Log2(PCSC_LOG_INFO, "setting customMaxThreadCardHandles to: %d",
+					customMaxThreadCardHandles);
+				break;
+
 			default:
 				print_usage (argv[0]);
 				return EXIT_FAILURE;
@@ -438,7 +464,7 @@
 	/*
 	 * Allocate memory for reader structures
 	 */
-	rv = RFAllocateReaderSpace();
+	rv = RFAllocateReaderSpace(customMaxReaderHandles);
 	if (SCARD_S_SUCCESS != rv)
 		at_exit();
 
@@ -502,7 +528,7 @@
 
 	(void)signal(SIGUSR1, signal_reload);
 
-	SVCServiceRunLoop();
+	SVCServiceRunLoop(customMaxThreadCounter, customMaxThreadCardHandles);
 
 	Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
 	return EXIT_FAILURE;
@@ -593,6 +619,9 @@
 	printf("  -e  --error	 	display error level debug messages\n");
 	printf("  -C  --critical 	display critical only level debug messages\n");
 	printf("  --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
+	printf("  -t, --max-thread	maximum number of threads (default %d)\n", PCSC_MAX_CONTEXT_THREADS);
+	printf("  -s, --max-card-handle-per-thread	maximum number of card handle per thread (default: %d)\n", PCSC_MAX_CONTEXT_CARD_HANDLES);
+	printf("  -r, --max-card-handle-per-reader	maximum number of card handle per reader (default: %d)\n", PCSC_MAX_READER_HANDLES);
 #else
 	printf("  -a    log APDU commands and results\n");
 	printf("  -c 	path to reader.conf\n");
@@ -601,6 +630,9 @@
 	printf("  -h 	display usage information\n");
 	printf("  -H	ask the daemon to rescan the available readers\n");
 	printf("  -v 	display the program version number\n");
+	printf("  -t    maximum number of threads\n");
+	printf("  -s    maximum number of card handle per thread\n");
+	printf("  -r    maximum number of card handle per reader\n");
 #endif
 }
 

Modified: trunk/PCSC/src/readerfactory.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/readerfactory.c?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/readerfactory.c (original)
+++ trunk/PCSC/src/readerfactory.c Tue Nov 17 14:48:46 2009
@@ -47,6 +47,7 @@
 #endif
 
 static PREADER_CONTEXT sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS];
+static unsigned int maxReaderHandles = PCSC_MAX_READER_HANDLES;
 static DWORD dwNumReadersContexts = 0;
 static char *ConfigFile = NULL;
 static int ConfigFileCRC = 0;
@@ -54,9 +55,28 @@
 
 #define IDENTITY_SHIFT 16
 
-LONG RFAllocateReaderSpace(void)
+static int RDR_CLIHANDLES_seeker(const void *el, const void *key)
+{
+	const RDR_CLIHANDLES *rdrCliHandles = el;
+
+	if ((el == NULL) || (key == NULL))
+		Log3(PCSC_LOG_CRITICAL,
+			"RDR_CLIHANDLES_seeker called with NULL pointer: el=%X, key=%X",
+			el, key);
+
+	if (rdrCliHandles->hCard == *(SCARDHANDLE *)key)
+		return 1;
+
+	return 0;
+}
+
+
+LONG RFAllocateReaderSpace(unsigned int customMaxReaderHandles)
 {
 	int i;	/* Counter */
+
+	if (customMaxReaderHandles != 0)
+		maxReaderHandles = customMaxReaderHandles;
 
 	/* Allocate each reader structure */
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
@@ -76,6 +96,7 @@
 	UCHAR ucGetData[1], ucThread[1];
 	LONG rv, parentNode;
 	int i, j;
+	int lrv = 0;
 
 	if ((lpcReader == NULL) || (lpcLibrary == NULL) || (lpcDevice == NULL))
 		return SCARD_E_INVALID_VALUE;
@@ -171,8 +192,21 @@
 		(dwContext + 1) << IDENTITY_SHIFT;
 	(sReadersContexts[dwContext])->readerState = NULL;
 
-	for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-		(sReadersContexts[dwContext])->psHandles[i].hCard = 0;
+	lrv = list_init(&((sReadersContexts[dwContext])->handlesList));
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
+		return SCARD_E_NO_MEMORY;
+	}
+
+	lrv = list_attributes_seeker(&((sReadersContexts[dwContext])->handlesList),
+		RDR_CLIHANDLES_seeker);
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL,
+			"list_attributes_seeker failed with return value: %X", lrv);
+		return SCARD_E_NO_MEMORY;
+	}
 
 	/* If a clone to this reader exists take some values from that clone */
 	if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
@@ -346,8 +380,21 @@
 		(sReadersContexts[dwContextB])->dwIdentity =
 			(dwContextB + 1) << IDENTITY_SHIFT;
 
-		for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-			(sReadersContexts[dwContextB])->psHandles[i].hCard = 0;
+		lrv = list_init(&((sReadersContexts[dwContextB])->handlesList));
+		if (lrv < 0)
+		{
+			Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
+			return SCARD_E_NO_MEMORY;
+		}
+
+		lrv = list_attributes_seeker(&((sReadersContexts[dwContextB])->handlesList),
+			RDR_CLIHANDLES_seeker);
+		if (lrv < 0)
+		{
+			Log2(PCSC_LOG_CRITICAL,
+					"list_attributes_seeker failed with return value: %X", lrv);
+			return SCARD_E_NO_MEMORY;
+		}
 
 		/* Call on the parent driver to see if the slots are thread safe */
 		dwGetSize = sizeof(ucThread);
@@ -412,7 +459,6 @@
 	while (SCARD_S_SUCCESS ==
 		RFReaderInfoNamePort(dwPort, lpcReader, &sContext))
 	{
-		int i;
 
 		/* Try to destroy the thread */
 		rv = EHDestroyEventHandler(sContext);
@@ -466,9 +512,20 @@
 		sContext->dwIdentity = 0;
 		sContext->readerState = NULL;
 
-		for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-			sContext->psHandles[i].hCard = 0;
-
+		while (list_size(&(sContext->handlesList)) != 0)
+		{
+			int lrv;
+			RDR_CLIHANDLES *currentHandle;
+
+			currentHandle = list_get_at(&(sContext->handlesList), 0);
+			lrv = list_delete_at(&(sContext->handlesList), 0);
+			if (lrv < 0)
+				Log2(PCSC_LOG_CRITICAL,
+					"list_delete_at failed with return value: %X", lrv);
+
+			free(currentHandle);
+		}
+		list_destroy(&(sContext->handlesList));
 		dwNumReadersContexts -= 1;
 
 		/* signal an event to clients */
@@ -1001,35 +1058,34 @@
 	 * for authentication. */
 	randHandle = SYS_RandomInt(10, 65000);
 
-	while (1)
-	{
-		int i;
-
-		for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-		{
-			if ((sReadersContexts[i])->vHandle != 0)
+	int i;
+again:
+	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
+	{
+		if ((sReadersContexts[i])->vHandle != 0)
+		{
+			RDR_CLIHANDLES *currentHandle;
+			list_t * l = &((sReadersContexts[i])->handlesList);
+
+			list_iterator_start(l);
+			while (list_iterator_hasnext(l))
 			{
-				int j;
-
-				for (j = 0; j < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; j++)
+				currentHandle = list_iterator_next(l);
+				if ((rContext->dwIdentity + randHandle) ==
+					(currentHandle->hCard))
 				{
-					if ((rContext->dwIdentity + randHandle) ==
-						(sReadersContexts[i])->psHandles[j].hCard)
-					{
-						/* Get a new handle and loop again */
-						randHandle = SYS_RandomInt(10, 65000);
-						continue;
-					}
+					/* Get a new handle and loop again */
+					randHandle = SYS_RandomInt(10, 65000);
+					list_iterator_stop(l);
+					goto again;
 				}
 			}
-		}
-
-		/* Once the for loop is completed w/o restart a good handle was
-		 * found and the loop can be exited. */
-		if (i == PCSCLITE_MAX_READERS_CONTEXTS)
-			break;
-	}
-
+			list_iterator_stop(l);
+		}
+	}
+
+	/* Once the for loop is completed w/o restart a good handle was
+	 * found and the loop can be exited. */
 	return rContext->dwIdentity + randHandle;
 }
 
@@ -1041,13 +1097,11 @@
 	{
 		if ((sReadersContexts[i])->vHandle != 0)
 		{
-			int j;
-
-			for (j = 0; j < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; j++)
-			{
-				if (hCard == (sReadersContexts[i])->psHandles[j].hCard)
-					return SCARD_S_SUCCESS;
-			}
+			RDR_CLIHANDLES * currentHandle;
+			currentHandle = list_seek(&((sReadersContexts[i])->handlesList),
+				&hCard);
+			if (currentHandle != NULL)
+				return SCARD_S_SUCCESS;
 		}
 	}
 
@@ -1062,55 +1116,89 @@
 
 LONG RFAddReaderHandle(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
 {
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-	{
-		if (rContext->psHandles[i].hCard == 0)
-		{
-			rContext->psHandles[i].hCard = hCard;
-			rContext->psHandles[i].dwEventStatus = 0;
-			break;
-		}
-	}
-
-	if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS)
-		/* List is full */
-		return SCARD_E_INSUFFICIENT_BUFFER;
-
+	int listLength, lrv;
+	RDR_CLIHANDLES *newHandle;
+
+	listLength = list_size(&(rContext->handlesList));
+
+	/* Throttle the number of possible handles */
+	if (listLength >= maxReaderHandles)
+	{
+		Log2(PCSC_LOG_CRITICAL,
+			"Too many handles opened, exceeding configured max (%d)",
+			maxReaderHandles);
+		return SCARD_E_NO_MEMORY;
+	}
+
+	newHandle = malloc(sizeof(RDR_CLIHANDLES));
+	if (NULL == newHandle)
+	{
+		Log1(PCSC_LOG_CRITICAL, "malloc failed");
+		return SCARD_E_NO_MEMORY;
+	}
+
+	newHandle->hCard = hCard;
+	newHandle->dwEventStatus = 0;
+
+	lrv = list_append(&(rContext->handlesList), newHandle);
+	if (lrv < 0)
+	{
+		free(newHandle);
+		Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X",
+			lrv);
+		return SCARD_E_NO_MEMORY;
+	}
 	return SCARD_S_SUCCESS;
 }
 
 LONG RFRemoveReaderHandle(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
 {
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-	{
-		if (rContext->psHandles[i].hCard == hCard)
-		{
-			rContext->psHandles[i].hCard = 0;
-			rContext->psHandles[i].dwEventStatus = 0;
-			break;
-		}
-	}
-
-	if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS)
-		/* Not Found */
+	RDR_CLIHANDLES *currentHandle;
+	int list_index, lrv;
+
+	currentHandle = list_seek(&(rContext->handlesList), &hCard);
+	if (NULL == currentHandle)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_seek failed to locate hCard=%X", hCard);
 		return SCARD_E_INVALID_HANDLE;
-
+	}
+
+	list_index = list_locate(&(rContext->handlesList), currentHandle);
+	if (list_index < 0)
+		Log2(PCSC_LOG_CRITICAL,
+			"list_locate failed with return value: %X", list_index);
+	else
+	{
+		lrv = list_delete_at(&(rContext->handlesList), list_index);
+		if (lrv < 0)
+			Log2(PCSC_LOG_CRITICAL,
+				"list_delete_at failed with return value: %X", lrv);
+	}
+	free(currentHandle);
+
+	/* Not Found */
 	return SCARD_S_SUCCESS;
 }
 
 LONG RFSetReaderEventState(PREADER_CONTEXT rContext, DWORD dwEvent)
 {
-	int i;
-
 	/* Set all the handles for that reader to the event */
-	for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-	{
-		if (rContext->psHandles[i].hCard != 0)
-			rContext->psHandles[i].dwEventStatus = dwEvent;
+	int list_index, listSize;
+	RDR_CLIHANDLES *currentHandle;
+
+	listSize = list_size(&(rContext->handlesList));
+
+	for (list_index = 0; list_index < listSize; list_index++)
+	{
+		currentHandle = list_get_at(&(rContext->handlesList), list_index);
+		if (NULL == currentHandle)
+		{
+			Log2(PCSC_LOG_CRITICAL, "list_get_at failed at index %s",
+				list_index);
+			continue;
+		}
+
+		currentHandle->dwEventStatus = dwEvent;
 	}
 
 	if (SCARD_REMOVED == dwEvent)
@@ -1125,46 +1213,52 @@
 
 LONG RFCheckReaderEventState(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
 {
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-	{
-		if (rContext->psHandles[i].hCard == hCard)
-		{
-			if (rContext->psHandles[i].dwEventStatus == SCARD_REMOVED)
-				return SCARD_W_REMOVED_CARD;
-			else
-			{
-				if (rContext->psHandles[i].dwEventStatus == SCARD_RESET)
-					return SCARD_W_RESET_CARD;
-				else
-				{
-					if (rContext->psHandles[i].dwEventStatus == 0)
-						return SCARD_S_SUCCESS;
-					else
-						return SCARD_E_INVALID_VALUE;
-				}
-			}
-		}
-	}
-
-	return SCARD_E_INVALID_HANDLE;
+	LONG rv;
+	RDR_CLIHANDLES *currentHandle;
+
+	currentHandle = list_seek(&(rContext->handlesList), &hCard);
+	if (NULL == currentHandle)
+	{
+		/* Not Found */
+		Log2(PCSC_LOG_CRITICAL, "list_seek failed for hCard %X", hCard);
+		return SCARD_E_INVALID_HANDLE;
+	}
+
+	switch(currentHandle->dwEventStatus)
+	{
+		case 0:
+			rv = SCARD_S_SUCCESS;
+			break;
+
+		case SCARD_REMOVED:
+			rv = SCARD_W_REMOVED_CARD;
+			break;
+
+		case SCARD_RESET:
+			rv = SCARD_W_RESET_CARD;
+			break;
+
+		default:
+			rv = SCARD_E_INVALID_VALUE;
+	}
+
+	return rv;
 }
 
 LONG RFClearReaderEventState(PREADER_CONTEXT rContext, SCARDHANDLE hCard)
 {
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
-	{
-		if (rContext->psHandles[i].hCard == hCard)
-			rContext->psHandles[i].dwEventStatus = 0;
-	}
-
-	if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS)
+	RDR_CLIHANDLES *currentHandle;
+
+	currentHandle = list_seek(&(rContext->handlesList), &hCard);
+	if (NULL == currentHandle)
 		/* Not Found */
 		return SCARD_E_INVALID_HANDLE;
 
+	currentHandle->dwEventStatus = 0;
+
+	/* hCards should be unique so we
+	 * should be able to return
+	 * as soon as we have a hit */
 	return SCARD_S_SUCCESS;
 }
 

Modified: trunk/PCSC/src/readerfactory.h
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/readerfactory.h?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/readerfactory.h (original)
+++ trunk/PCSC/src/readerfactory.h Tue Nov 17 14:48:46 2009
@@ -22,6 +22,7 @@
 #include "thread_generic.h"
 #include "ifdhandler.h"
 #include "pcscd.h"
+#include "simclist.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -110,7 +111,7 @@
 		PCSCLITE_THREAD_T pthThread;	/**< Event polling thread */
 		RESPONSECODE (*pthCardEvent)(DWORD);	/**< Card Event sync */
 		PCSCLITE_MUTEX *mMutex;	/**< Mutex for this connection */
-		RDR_CLIHANDLES psHandles[PCSCLITE_MAX_READER_CONTEXT_CHANNELS];
+		list_t handlesList;
                                          /**< Structure of connected handles */
 		union
 		{
@@ -138,7 +139,7 @@
 
 	typedef struct ReaderContext READER_CONTEXT, *PREADER_CONTEXT;
 
-	LONG RFAllocateReaderSpace(void);
+	LONG RFAllocateReaderSpace(unsigned int);
 	LONG RFAddReader(LPSTR, DWORD, LPSTR, LPSTR);
 	LONG RFRemoveReader(LPSTR, DWORD);
 	LONG RFSetReaderName(PREADER_CONTEXT, LPSTR, LPSTR, DWORD, DWORD);

Modified: trunk/PCSC/src/winscard_clnt.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_clnt.c?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_clnt.c (original)
+++ trunk/PCSC/src/winscard_clnt.c Tue Nov 17 14:48:46 2009
@@ -186,18 +186,55 @@
 
 typedef struct _psChannelMap CHANNEL_MAP;
 
+static int CHANNEL_MAP_seeker(const void *el, const void *key)
+{
+	const CHANNEL_MAP * channelMap = el;
+
+	if ((el == NULL) || (key == NULL))
+	{
+		Log3(PCSC_LOG_CRITICAL,
+			"CHANNEL_MAP_seeker called with NULL pointer: el=%X, key=%X",
+			el, key);
+	}
+
+	if (channelMap->hCard == *(SCARDHANDLE *)key)
+		return 1;
+
+	return 0;
+}
+
 /**
  * @brief Represents the an Application Context on the Client side.
  *
  * An Application Context contains Channels (\c _psChannelMap).
  */
-static struct _psContextMap
+struct _psContextMap
 {
 	DWORD dwClientID;				/**< Client Connection ID */
 	SCARDCONTEXT hContext;			/**< Application Context ID */
 	PCSCLITE_MUTEX * mMutex;		/**< Mutex for this context */
-	CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
-} psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
+	list_t channelMapList;
+};
+typedef struct _psContextMap SCONTEXTMAP;
+
+static list_t contextMapList;
+
+static int SCONTEXTMAP_seeker(const void *el, const void *key)
+{
+	const SCONTEXTMAP * contextMap = el;
+
+	if ((el == NULL) || (key == NULL))
+	{
+		Log3(PCSC_LOG_CRITICAL,
+			"SCONTEXTMAP_seeker called with NULL pointer: el=%X, key=%X",
+			el, key);
+	}
+
+	if (contextMap->hContext == *(SCARDCONTEXT *) key)
+		return 1;
+
+	return 0;
+}
 
 /**
  * Make sure the initialization code is executed only once.
@@ -233,23 +270,21 @@
 
 
 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
-static LONG SCardGetContextIndice(SCARDCONTEXT);
-static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
+static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT);
+static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT);
 static LONG SCardRemoveContext(SCARDCONTEXT);
-static LONG SCardCleanContext(LONG indice);
-
-static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPCSTR);
-static LONG SCardGetIndicesFromHandle(SCARDHANDLE, /*@out@*/ PDWORD,
-	/*@out@*/ PDWORD);
-static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, /*@out@*/ PDWORD,
-	/*@out@*/ PDWORD);
+static LONG SCardCleanContext(SCONTEXTMAP *);
+
+static LONG SCardAddHandle(SCARDHANDLE, SCONTEXTMAP *, LPCSTR);
+static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE, /*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
+static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE, /*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
 static LONG SCardRemoveHandle(SCARDHANDLE);
 
 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
 	LPBYTE pbAttr, LPDWORD pcbAttrLen);
 
 void DESTRUCTOR SCardUnload(void);
-static LONG getReaderStates(LONG dwContextIndex);
+static LONG getReaderStates(SCONTEXTMAP * currentContextMap);
 
 /*
  * Thread safety functions
@@ -368,7 +403,6 @@
 	/*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
 {
 	LONG rv;
-	int i;
 	struct establish_struct scEstablishStruct;
 	uint32_t dwClientID = 0;
 
@@ -381,53 +415,36 @@
 
 	/*
 	 * Do this only once:
-	 * - Initialize debug of need.
-	 * - Set up the memory mapped structures for reader states.
-	 * - Allocate each reader structure.
-	 * - Initialize context struct.
+	 * - Initialize context list.
 	 */
 	if (isExecuted == 0)
 	{
-		/*
-		 * Initializes the application contexts and all channels for each one
-		 */
-		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
+		int lrv;
+
+		/* NOTE: The list will never be freed (No API call exists to
+		 * "close all contexts".
+		 * Applications which load and unload the library will leak
+		 * the list's internal structures. */
+		lrv = list_init(&contextMapList);
+		if (lrv < 0)
 		{
-			int j;
-
-			/*
-			 * Initially set the context struct to zero
-			 */
-			psContextMap[i].dwClientID = 0;
-			psContextMap[i].hContext = 0;
-			psContextMap[i].mMutex = NULL;
-
-			for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
-			{
-				/*
-				 * Initially set the hcard structs to zero
-				 */
-				psContextMap[i].psChannelMap[j].hCard = 0;
-				psContextMap[i].psChannelMap[j].readerName = NULL;
-			}
+			Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
+			return SCARD_E_NO_MEMORY;
 		}
 
-	}
-
-	/*
-	 * Is there a free slot for this connection ?
-	 */
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
-	{
-		if (psContextMap[i].dwClientID == 0)
-			break;
-	}
-
-	if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
-	{
-		return SCARD_E_NO_MEMORY;
-	}
+		lrv = list_attributes_seeker(&contextMapList,
+				SCONTEXTMAP_seeker);
+		if (lrv <0)
+		{
+			Log2(PCSC_LOG_CRITICAL,
+				"list_attributes_seeker failed with return value: %X", lrv);
+			list_destroy(&contextMapList);
+			return SCARD_E_NO_MEMORY;
+		}
+
+		isExecuted = 1;
+	}
+
 
 	/* Establishes a connection to the server */
 	if (SHMClientSetupSession(&dwClientID) != 0)
@@ -458,8 +475,6 @@
 
 		if (veStr.rv != SCARD_S_SUCCESS)
 			return veStr.rv;
-
-		isExecuted = 1;
 	}
 
 again:
@@ -488,8 +503,8 @@
 	if (scEstablishStruct.rv != SCARD_S_SUCCESS)
 		return scEstablishStruct.rv;
 
-	/* check we do not reuse an existing phContext */
-	if (-1 != SCardGetContextIndiceTH(scEstablishStruct.hContext))
+	/* check we do not reuse an existing hContext */
+	if (NULL != SCardGetContextTH(scEstablishStruct.hContext))
 		/* we do not need to release the allocated context since
 		 * SCardReleaseContext() does nothing on the server side */
 		goto again;
@@ -529,16 +544,16 @@
 {
 	LONG rv;
 	struct release_struct scReleaseStruct;
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 
 	PROFILE_START
 
 	/*
 	 * Make sure this context has been opened
-	 * and get dwContextIndex
-	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	 * and get currentContextMap
+	 */
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 	{
 		PROFILE_END(SCARD_E_INVALID_HANDLE)
 		return SCARD_E_INVALID_HANDLE;
@@ -557,11 +572,11 @@
 		return rv;
 	}
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the context is still opened */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		/* the context is now invalid
 		 * -> another thread may have called SCardReleaseContext
 		 * -> so the mMutex has been unlocked */
@@ -571,7 +586,7 @@
 	scReleaseStruct.rv = SCARD_S_SUCCESS;
 
 	rv = SHMMessageSendWithHeader(SCARD_RELEASE_CONTEXT,
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		sizeof(scReleaseStruct),
 		PCSCLITE_WRITE_TIMEOUT, (void *) &scReleaseStruct);
 
@@ -585,7 +600,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scReleaseStruct, sizeof(scReleaseStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -596,7 +611,7 @@
 
 	rv = scReleaseStruct.rv;
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	/*
 	 * Remove the local context from the stack
@@ -693,7 +708,7 @@
 {
 	LONG rv;
 	struct connect_struct scConnectStruct;
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 
 	PROFILE_START
 
@@ -721,15 +736,15 @@
 	/*
 	 * Make sure this context has been opened
 	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the context is still opened */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		/* the context is now invalid
 		 * -> another thread may have called SCardReleaseContext
 		 * -> so the mMutex has been unlocked */
@@ -744,7 +759,7 @@
 	scConnectStruct.dwActiveProtocol = 0;
 	scConnectStruct.rv = SCARD_S_SUCCESS;
 
-	rv = SHMMessageSendWithHeader(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
+	rv = SHMMessageSendWithHeader(SCARD_CONNECT, currentContextMap->dwClientID,
 		sizeof(scConnectStruct),
 		PCSCLITE_READ_TIMEOUT, (void *) &scConnectStruct);
 
@@ -758,7 +773,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scConnectStruct, sizeof(scConnectStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -775,13 +790,13 @@
 		/*
 		 * Keep track of the handle locally
 		 */
-		rv = SCardAddHandle(*phCard, dwContextIndex, szReader);
+		rv = SCardAddHandle(*phCard, currentContextMap, szReader);
 	}
 	else
 		rv = scConnectStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -861,7 +876,8 @@
 {
 	LONG rv;
 	struct reconnect_struct scReconnectStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 
 	PROFILE_START
 
@@ -875,14 +891,16 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -896,9 +914,10 @@
 	scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
 	scReconnectStruct.rv = SCARD_S_SUCCESS;
 
-	rv = SHMMessageSendWithHeader(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
-			sizeof(scReconnectStruct),
-			PCSCLITE_READ_TIMEOUT, (void *) &scReconnectStruct);
+	rv = SHMMessageSendWithHeader(SCARD_RECONNECT,
+		currentContextMap->dwClientID,
+		sizeof(scReconnectStruct),
+		PCSCLITE_READ_TIMEOUT, (void *) &scReconnectStruct);
 
 	if (rv == -1)
 	{
@@ -910,9 +929,9 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scReconnectStruct,
-			sizeof(scReconnectStruct),
-			psContextMap[dwContextIndex].dwClientID,
-			PCSCLITE_READ_TIMEOUT);
+		sizeof(scReconnectStruct),
+		currentContextMap->dwClientID,
+		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
 	{
@@ -924,7 +943,7 @@
 	rv = scReconnectStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -965,7 +984,8 @@
 {
 	LONG rv;
 	struct disconnect_struct scDisconnectStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 
 	PROFILE_START
 
@@ -976,14 +996,16 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -994,7 +1016,8 @@
 	scDisconnectStruct.dwDisposition = dwDisposition;
 	scDisconnectStruct.rv = SCARD_S_SUCCESS;
 
-	rv = SHMMessageSendWithHeader(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
+	rv = SHMMessageSendWithHeader(SCARD_DISCONNECT,
+		currentContextMap->dwClientID,
 		sizeof(scDisconnectStruct),
 		PCSCLITE_READ_TIMEOUT, (void *) &scDisconnectStruct);
 
@@ -1009,7 +1032,7 @@
 	 */
 	rv = SHMMessageReceive(&scDisconnectStruct,
 		sizeof(scDisconnectStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -1022,7 +1045,7 @@
 	rv = scDisconnectStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -1069,7 +1092,8 @@
 
 	LONG rv;
 	struct begin_struct scBeginStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 
 	PROFILE_START
 
@@ -1080,14 +1104,16 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -1104,7 +1130,8 @@
 
 	do
 	{
-		rv = SHMMessageSendWithHeader(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
+		rv = SHMMessageSendWithHeader(SCARD_BEGIN_TRANSACTION,
+			currentContextMap->dwClientID,
 			sizeof(scBeginStruct),
 			PCSCLITE_READ_TIMEOUT, (void *) &scBeginStruct);
 
@@ -1118,7 +1145,7 @@
 		 * Read a message from the server
 		 */
 		rv = SHMMessageReceive(&scBeginStruct, sizeof(scBeginStruct),
-			psContextMap[dwContextIndex].dwClientID,
+			currentContextMap->dwClientID,
 			PCSCLITE_READ_TIMEOUT);
 
 		if (rv < 0)
@@ -1132,7 +1159,7 @@
 	rv = scBeginStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv);
 
@@ -1184,7 +1211,8 @@
 	LONG rv;
 	struct end_struct scEndStruct;
 	int randnum;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 
 	PROFILE_START
 
@@ -1200,14 +1228,16 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -1219,7 +1249,7 @@
 	scEndStruct.rv = SCARD_S_SUCCESS;
 
 	rv = SHMMessageSendWithHeader(SCARD_END_TRANSACTION,
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		sizeof(scEndStruct),
 		PCSCLITE_READ_TIMEOUT, (void *) &scEndStruct);
 
@@ -1233,7 +1263,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scEndStruct, sizeof(scEndStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -1250,7 +1280,7 @@
 	rv = scEndStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -1267,7 +1297,8 @@
 {
 	LONG rv;
 	struct cancel_transaction_struct scCancelStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 
 	PROFILE_START
 
@@ -1278,14 +1309,16 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -1295,7 +1328,7 @@
 	scCancelStruct.hCard = hCard;
 
 	rv = SHMMessageSendWithHeader(SCARD_CANCEL_TRANSACTION,
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		sizeof(scCancelStruct),
 		PCSCLITE_READ_TIMEOUT, (void *) &scCancelStruct);
 
@@ -1309,7 +1342,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scCancelStruct, sizeof(scCancelStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -1320,7 +1353,7 @@
 	rv = scCancelStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -1422,7 +1455,8 @@
 	LONG rv;
 	int i;
 	struct status_struct scStatusStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 	char *r;
 	char *bufReader = NULL;
 	LPBYTE bufAtr = NULL;
@@ -1458,14 +1492,16 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -1473,11 +1509,11 @@
 		return SCARD_E_INVALID_HANDLE;
 
 	/* synchronize reader states with daemon */
-	rv = getReaderStates(dwContextIndex);
+	rv = getReaderStates(currentContextMap);
 	if (rv != SCARD_S_SUCCESS)
 		goto end;
 
-	r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
+	r = pChannelMap->readerName;
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		/* by default r == NULL */
@@ -1499,7 +1535,7 @@
 	scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
 	scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
 
-	rv = SHMMessageSendWithHeader(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
+	rv = SHMMessageSendWithHeader(SCARD_STATUS, currentContextMap->dwClientID,
 		sizeof(scStatusStruct),
 		PCSCLITE_READ_TIMEOUT, (void *) &scStatusStruct);
 
@@ -1513,7 +1549,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scStatusStruct, sizeof(scStatusStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -1535,7 +1571,7 @@
 	 * Now continue with the client side SCardStatus
 	 */
 
-	*pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
+	*pcchReaderLen = strlen(pChannelMap->readerName) + 1;
 	*pcbAtrLen = readerStates[i].cardAtrLength;
 
 	if (pdwState)
@@ -1570,7 +1606,7 @@
 			rv = SCARD_E_INSUFFICIENT_BUFFER;
 
 		strncpy(bufReader,
-			psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
+			pChannelMap->readerName,
 			dwReaderLen);
 	}
 
@@ -1602,7 +1638,7 @@
 	}
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -1709,7 +1745,7 @@
 	DWORD dwState;
 	DWORD dwBreakFlag = 0;
 	int j;
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 	int currentReaderCount = 0;
 	LONG rv = SCARD_S_SUCCESS;
 
@@ -1749,22 +1785,22 @@
 	/*
 	 * Make sure this context has been opened
 	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the context is still opened */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		/* the context is now invalid
 		 * -> another thread may have called SCardReleaseContext
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
 	/* synchronize reader states with daemon */
-	rv = getReaderStates(dwContextIndex);
+	rv = getReaderStates(currentContextMap);
 	if (rv != SCARD_S_SUCCESS)
 		goto end;
 
@@ -1791,8 +1827,8 @@
 		rv = SCardCheckDaemonAvailability();
 		if (rv != SCARD_S_SUCCESS)
 		{
-			if (psContextMap[dwContextIndex].mMutex)
-				(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			if (currentContextMap->mMutex)
+				(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 			PROFILE_END(rv)
 
@@ -2079,7 +2115,7 @@
 				waitStatusStruct.timeOut = dwTime;
 
 				rv = SHMMessageSendWithHeader(CMD_WAIT_READER_STATE_CHANGE,
-					psContextMap[dwContextIndex].dwClientID,
+					currentContextMap->dwClientID,
 					sizeof(waitStatusStruct), PCSCLITE_WRITE_TIMEOUT,
 					&waitStatusStruct);
 
@@ -2093,7 +2129,7 @@
 				 * Read a message from the server
 				 */
 				rv = SHMMessageReceive(&waitStatusStruct, sizeof(waitStatusStruct),
-					psContextMap[dwContextIndex].dwClientID,
+					currentContextMap->dwClientID,
 					dwTime);
 
 				/* timeout */
@@ -2101,7 +2137,7 @@
 				{
 					/* ask server to remove us from the event list */
 					rv = SHMMessageSendWithHeader(CMD_STOP_WAITING_READER_STATE_CHANGE,
-						psContextMap[dwContextIndex].dwClientID,
+						currentContextMap->dwClientID,
 						sizeof(waitStatusStruct), PCSCLITE_WRITE_TIMEOUT,
 						&waitStatusStruct);
 
@@ -2113,7 +2149,7 @@
 
 					/* Read a message from the server */
 					rv = SHMMessageReceive(&waitStatusStruct, sizeof(waitStatusStruct),
-						psContextMap[dwContextIndex].dwClientID,
+						currentContextMap->dwClientID,
 						PCSCLITE_READ_TIMEOUT);
 
 					if (rv == -1)
@@ -2137,7 +2173,7 @@
 				}
 
 				/* synchronize reader states with daemon */
-				rv = getReaderStates(dwContextIndex);
+				rv = getReaderStates(currentContextMap);
 				if (rv != SCARD_S_SUCCESS)
 					goto end;
 
@@ -2169,7 +2205,7 @@
 end:
 	Log1(PCSC_LOG_DEBUG, "Event Loop End");
 
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -2233,7 +2269,8 @@
 {
 	LONG rv;
 	struct control_struct scControlStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 
 	PROFILE_START
 
@@ -2248,17 +2285,19 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 	{
 		PROFILE_END(SCARD_E_INVALID_HANDLE)
 		return SCARD_E_INVALID_HANDLE;
 	}
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -2278,7 +2317,7 @@
 	scControlStruct.cbRecvLength = cbRecvLength;
 
 	rv = SHMMessageSendWithHeader(SCARD_CONTROL,
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		sizeof(scControlStruct), PCSCLITE_READ_TIMEOUT, &scControlStruct);
 
 	if (rv == -1)
@@ -2289,7 +2328,7 @@
 
 	/* write the sent buffer */
 	rv = SHMMessageSend((char *)pbSendBuffer, cbSendLength,
-		psContextMap[dwContextIndex].dwClientID, PCSCLITE_WRITE_TIMEOUT);
+		currentContextMap->dwClientID, PCSCLITE_WRITE_TIMEOUT);
 
 	if (rv == -1)
 	{
@@ -2301,7 +2340,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scControlStruct, sizeof(scControlStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -2314,7 +2353,7 @@
 	{
 		/* read the received buffer */
 		rv = SHMMessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
-			psContextMap[dwContextIndex].dwClientID,
+			currentContextMap->dwClientID,
 			PCSCLITE_READ_TIMEOUT);
 
 		if (rv < 0)
@@ -2331,7 +2370,7 @@
 	rv = scControlStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -2533,7 +2572,8 @@
 {
 	LONG rv;
 	struct getset_struct scGetSetStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 
 	rv = SCardCheckDaemonAvailability();
 	if (rv != SCARD_S_SUCCESS)
@@ -2542,14 +2582,16 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -2571,7 +2613,7 @@
 		memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
 
 	rv = SHMMessageSendWithHeader(command,
-		psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
+		currentContextMap->dwClientID, sizeof(scGetSetStruct),
 		PCSCLITE_READ_TIMEOUT, &scGetSetStruct);
 
 	if (rv == -1)
@@ -2584,7 +2626,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scGetSetStruct, sizeof(scGetSetStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -2614,7 +2656,7 @@
 	rv = scGetSetStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	return rv;
 }
@@ -2683,7 +2725,8 @@
 	LPDWORD pcbRecvLength)
 {
 	LONG rv;
-	DWORD dwContextIndex, dwChannelIndex;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * pChannelMap;
 	struct transmit_struct scTransmitStruct;
 
 	PROFILE_START
@@ -2699,7 +2742,8 @@
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 	{
 		*pcbRecvLength = 0;
@@ -2707,10 +2751,11 @@
 		return SCARD_E_INVALID_HANDLE;
 	}
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the handle is still valid */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&pChannelMap);
 	if (rv == -1)
 		/* the handle is now invalid
 		 * -> another thread may have called SCardReleaseContext
@@ -2743,7 +2788,7 @@
 	}
 
 	rv = SHMMessageSendWithHeader(SCARD_TRANSMIT,
-		psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
+		currentContextMap->dwClientID, sizeof(scTransmitStruct),
 		PCSCLITE_WRITE_TIMEOUT, (void *) &scTransmitStruct);
 
 	if (rv == -1)
@@ -2754,7 +2799,7 @@
 
 	/* write the sent buffer */
 	rv = SHMMessageSend((void *)pbSendBuffer, cbSendLength,
-		psContextMap[dwContextIndex].dwClientID, PCSCLITE_WRITE_TIMEOUT);
+		currentContextMap->dwClientID, PCSCLITE_WRITE_TIMEOUT);
 
 	if (rv == -1)
 	{
@@ -2766,7 +2811,7 @@
 	 * Read a message from the server
 	 */
 	rv = SHMMessageReceive(&scTransmitStruct, sizeof(scTransmitStruct),
-		psContextMap[dwContextIndex].dwClientID,
+		currentContextMap->dwClientID,
 		PCSCLITE_READ_TIMEOUT);
 
 	if (rv < 0)
@@ -2779,7 +2824,7 @@
 	{
 		/* read the received buffer */
 		rv = SHMMessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
-			psContextMap[dwContextIndex].dwClientID,
+			currentContextMap->dwClientID,
 			PCSCLITE_READ_TIMEOUT);
 
 		if (rv < 0)
@@ -2799,7 +2844,7 @@
 	rv = scTransmitStruct.rv;
 
 end:
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -2859,7 +2904,7 @@
 {
 	DWORD dwReadersLen = 0;
 	int i;
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 	LONG rv = SCARD_S_SUCCESS;
 	char *buf = NULL;
 
@@ -2879,25 +2924,25 @@
 	/*
 	 * Make sure this context has been opened
 	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 	{
 		PROFILE_END(SCARD_E_INVALID_HANDLE)
 		return SCARD_E_INVALID_HANDLE;
 	}
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the context is still opened */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		/* the context is now invalid
 		 * -> another thread may have called SCardReleaseContext
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
 	/* synchronize reader states with daemon */
-	rv = getReaderStates(dwContextIndex);
+	rv = getReaderStates(currentContextMap);
 	if (rv != SCARD_S_SUCCESS)
 		goto end;
 
@@ -2962,7 +3007,7 @@
 	/* set the reader names length */
 	*pcchReaders = dwReadersLen;
 
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -2984,7 +3029,7 @@
 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
 {
 	LONG rv = SCARD_S_SUCCESS;
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 
 	PROFILE_START
 
@@ -2995,8 +3040,8 @@
 	/*
 	 * Make sure this context has been opened
 	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		return SCARD_E_INVALID_HANDLE;
 
 	free((void *)pvMem);
@@ -3059,7 +3104,7 @@
 	LPDWORD pcchGroups)
 {
 	LONG rv = SCARD_S_SUCCESS;
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 	char *buf = NULL;
 
 	PROFILE_START
@@ -3075,15 +3120,15 @@
 	/*
 	 * Make sure this context has been opened
 	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexLock(currentContextMap->mMutex);
 
 	/* check the context is still opened */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		/* the context is now invalid
 		 * -> another thread may have called SCardReleaseContext
 		 * -> so the mMutex has been unlocked */
@@ -3121,7 +3166,7 @@
 end:
 	*pcchGroups = dwGroups;
 
-	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	(void)SYS_MutexUnLock(currentContextMap->mMutex);
 
 	PROFILE_END(rv)
 
@@ -3157,7 +3202,7 @@
  */
 LONG SCardCancel(SCARDCONTEXT hContext)
 {
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 	LONG rv = SCARD_S_SUCCESS;
 	uint32_t dwClientID = 0;
 	struct cancel_struct scCancelStruct;
@@ -3167,8 +3212,8 @@
 	/*
 	 * Make sure this context has been opened
 	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (NULL == currentContextMap)
 		return SCARD_E_INVALID_HANDLE;
 
 	/* create a new connection to the server */
@@ -3240,7 +3285,7 @@
 LONG SCardIsValidContext(SCARDCONTEXT hContext)
 {
 	LONG rv;
-	LONG dwContextIndex;
+	SCONTEXTMAP * currentContextMap;
 
 	PROFILE_START
 
@@ -3254,8 +3299,8 @@
 	/*
 	 * Make sure this context has been opened
 	 */
-	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	currentContextMap = SCardGetContext(hContext);
+	if (currentContextMap == NULL)
 		rv = SCARD_E_INVALID_HANDLE;
 
 	PROFILE_END(rv)
@@ -3281,19 +3326,59 @@
  */
 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
 {
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
-	{
-		if (psContextMap[i].hContext == 0)
-		{
-			psContextMap[i].hContext = hContext;
-			psContextMap[i].dwClientID = dwClientID;
-			psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
-			(void)SYS_MutexInit(psContextMap[i].mMutex);
-			return SCARD_S_SUCCESS;
-		}
-	}
+	int lrv;
+	SCONTEXTMAP * newContextMap;
+
+	newContextMap = malloc(sizeof(SCONTEXTMAP));
+	if (NULL == newContextMap)
+		return SCARD_E_NO_MEMORY;
+
+	Log2(PCSC_LOG_DEBUG, "Allocating new SCONTEXTMAP @%X", newContextMap);
+	newContextMap->hContext = hContext;
+	newContextMap->dwClientID = dwClientID;
+
+	newContextMap->mMutex = malloc(sizeof(PCSCLITE_MUTEX));
+	if (NULL == newContextMap->mMutex)
+	{
+		Log2(PCSC_LOG_DEBUG, "Freeing SCONTEXTMAP @%X", newContextMap);
+		free(newContextMap);
+		return SCARD_E_NO_MEMORY;
+	}
+	(void)SYS_MutexInit(newContextMap->mMutex);
+
+	lrv = list_init(&(newContextMap->channelMapList));
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
+		goto error;
+	}
+
+	lrv = list_attributes_seeker(&(newContextMap->channelMapList),
+		CHANNEL_MAP_seeker);
+	if (lrv <0)
+	{
+		Log2(PCSC_LOG_CRITICAL,
+			"list_attributes_seeker failed with return value: %X", lrv);
+		list_destroy(&(newContextMap->channelMapList));
+		goto error;
+	}
+
+	lrv = list_append(&contextMapList, newContextMap);
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X",
+			lrv);
+		list_destroy(&(newContextMap->channelMapList));
+		goto error;
+	}
+
+	return SCARD_S_SUCCESS;
+
+error:
+
+	(void)SYS_MutexDestroy(newContextMap->mMutex);
+	free(newContextMap->mMutex);
+	free(newContextMap);
 
 	return SCARD_E_NO_MEMORY;
 }
@@ -3303,50 +3388,39 @@
  * for the passed context.
  *
  * This function is a thread-safe wrapper to the function
- * SCardGetContextIndiceTH().
+ * SCardGetContextTH().
  *
  * @param[in] hContext Application Context whose index will be find.
  *
  * @return Index corresponding to the Application Context or -1 if it is
  * not found.
  */
-static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
-{
-	LONG rv;
+static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT hContext)
+{
+	SCONTEXTMAP * currentContextMap;
 
 	(void)SCardLockThread();
-	rv = SCardGetContextIndiceTH(hContext);
+	currentContextMap = SCardGetContextTH(hContext);
 	(void)SCardUnlockThread();
 
-	return rv;
+	return currentContextMap;
 }
 
 /**
- * @brief Get the index from the Application Context vector \c _psContextMap
+ * @brief Get the address from the Application Context list \c _psContextMap
  * for the passed context.
  *
  * This functions is not thread-safe and should not be called. Instead, call
- * the function SCardGetContextIndice().
+ * the function SCardGetContext().
  *
  * @param[in] hContext Application Context whose index will be find.
  *
- * @return Index corresponding to the Application Context or -1 if it is
+ * @return Address corresponding to the Application Context or NULL if it is
  * not found.
  */
-static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
-{
-	int i;
-
-	/*
-	 * Find this context and return its spot in the array
-	 */
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
-	{
-		if ((hContext == psContextMap[i].hContext) && (hContext != 0))
-			return i;
-	}
-
-	return -1;
+static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT hContext)
+{
+	return list_seek(&contextMapList, &hContext);
 }
 
 /**
@@ -3360,34 +3434,63 @@
  */
 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
 {
-	LONG  retIndice;
-
-	retIndice = SCardGetContextIndiceTH(hContext);
-
-	if (retIndice == -1)
+	SCONTEXTMAP * currentContextMap;
+	currentContextMap = SCardGetContextTH(hContext);
+
+	if (NULL == currentContextMap)
 		return SCARD_E_INVALID_HANDLE;
 	else
-		return SCardCleanContext(retIndice);
+		return SCardCleanContext(currentContextMap);
 }
 
-static LONG SCardCleanContext(LONG indice)
-{
-	int i;
-
-	psContextMap[indice].hContext = 0;
-	(void)SHMClientCloseSession(psContextMap[indice].dwClientID);
-	psContextMap[indice].dwClientID = 0;
-	free(psContextMap[indice].mMutex);
-	psContextMap[indice].mMutex = NULL;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
-	{
-		/*
-		 * Reset the \c hCard structs to zero
-		 */
-		psContextMap[indice].psChannelMap[i].hCard = 0;
-		free(psContextMap[indice].psChannelMap[i].readerName);
-		psContextMap[indice].psChannelMap[i].readerName = NULL;
+static LONG SCardCleanContext(SCONTEXTMAP * targetContextMap)
+{
+	int list_index;
+	int listSize;
+	CHANNEL_MAP * currentChannelMap;
+
+	targetContextMap->hContext = 0;
+	(void)SHMClientCloseSession(targetContextMap->dwClientID);
+	targetContextMap->dwClientID = 0;
+	(void)SYS_MutexDestroy(targetContextMap->mMutex);
+	free(targetContextMap->mMutex);
+	targetContextMap->mMutex = NULL;
+
+	listSize = list_size(&(targetContextMap->channelMapList));
+	for (list_index = 0; list_index < listSize; list_index++)
+	{
+		currentChannelMap = list_get_at(&(targetContextMap->channelMapList),
+			list_index);
+		if (NULL == currentChannelMap)
+		{
+			Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d",
+				list_index);
+			continue;
+		}
+		else
+		{
+			free(currentChannelMap->readerName);
+			free(currentChannelMap);
+		}
+
+	}
+	list_destroy(&(targetContextMap->channelMapList));
+	list_index = list_locate(&contextMapList, targetContextMap);
+	if (list_index < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL,
+			"list_locate failed with return value: %X", list_index);
+	}
+	else
+	{
+		int lrv;
+
+		lrv = list_delete_at(&contextMapList, list_index);
+		if (lrv < 0)
+		{
+			Log2(PCSC_LOG_CRITICAL,
+				"list_delete_at failed with return value: %X", lrv);
+		}
 	}
 
 	return SCARD_S_SUCCESS;
@@ -3397,43 +3500,71 @@
  * Functions for managing hCard values returned from SCardConnect.
  */
 
-static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
+static LONG SCardAddHandle(SCARDHANDLE hCard, SCONTEXTMAP * currentContextMap,
 	LPCSTR readerName)
 {
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
-	{
-		if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
-		{
-			psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
-			psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
-			return SCARD_S_SUCCESS;
-		}
-	}
-
-	return SCARD_E_NO_MEMORY;
+	CHANNEL_MAP * newChannelMap;
+	int lrv = -1;
+
+	newChannelMap = malloc(sizeof(CHANNEL_MAP));
+	if (NULL == newChannelMap)
+		return SCARD_E_NO_MEMORY;
+
+	newChannelMap->hCard = hCard;
+	newChannelMap->readerName = strdup(readerName);
+
+	lrv = list_append(&(currentContextMap->channelMapList), newChannelMap);
+	if (lrv < 0)
+	{
+		free(newChannelMap->readerName);
+		free(newChannelMap);
+		Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X", lrv);
+		return SCARD_E_NO_MEMORY;
+	}
+
+	return SCARD_S_SUCCESS;
 }
 
 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
 {
-	DWORD dwContextIndice, dwChannelIndice;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * currentChannelMap;
+	int list_index = 0;
 	LONG rv;
 
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
+	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		&currentChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
+
+	free(currentChannelMap->readerName);
+
+	list_index = list_locate(&(currentContextMap->channelMapList),
+		currentChannelMap);
+	if (list_index < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL,
+			"list_locate failed with return value: %X", list_index);
+	}
 	else
 	{
-		psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
-		free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
-		psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
-		return SCARD_S_SUCCESS;
-	}
+		int lrv;
+
+		lrv = list_delete_at(&(currentContextMap->channelMapList), list_index);
+		if (lrv < 0)
+		{
+			Log2(PCSC_LOG_CRITICAL,
+				"list_delete_at failed with return value: %X", lrv);
+		}
+	}
+
+	free(currentChannelMap);
+
+	return SCARD_S_SUCCESS;
 }
 
-static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard,
-	PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
+static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE hCard,
+	SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
 {
 	LONG rv;
 
@@ -3441,33 +3572,41 @@
 		return -1;
 
 	(void)SCardLockThread();
-	rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
+	rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap, targetChannelMap);
 	(void)SCardUnlockThread();
 
 	return rv;
 }
 
-static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard,
-	PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
-{
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
-	{
-		if (psContextMap[i].hContext != 0)
+static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE hCard,
+	SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
+{
+	int listSize;
+	int list_index;
+	SCONTEXTMAP * currentContextMap;
+	CHANNEL_MAP * currentChannelMap;
+
+	/* Best to get the caller a crash early if we fail unsafely */
+	*targetContextMap = NULL;
+	*targetChannelMap = NULL;
+
+	listSize = list_size(&contextMapList);
+
+	for (list_index = 0; list_index < listSize; list_index++)
+	{
+		currentContextMap = list_get_at(&contextMapList, list_index);
+		if (currentContextMap == NULL)
 		{
-			int j;
-
-			for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
-			{
-				if (psContextMap[i].psChannelMap[j].hCard == hCard)
-				{
-					*pdwContextIndice = i;
-					*pdwChannelIndice = j;
-					return SCARD_S_SUCCESS;
-				}
-			}
-
+			Log2(PCSC_LOG_CRITICAL, "list_get_at failed for index %d", list_index);
+			continue;
+		}
+		currentChannelMap = list_seek(&(currentContextMap->channelMapList),
+			&hCard);
+		if (currentChannelMap != NULL)
+		{
+			*targetContextMap = currentContextMap;
+			*targetChannelMap = currentChannelMap;
+			return SCARD_S_SUCCESS;
 		}
 	}
 
@@ -3522,14 +3661,29 @@
 
 	if (need_restart)
 	{
-		int i;
-
 		/* invalid all handles */
 		(void)SCardLockThread();
 
-		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
-			if (psContextMap[i].hContext)
-				(void)SCardCleanContext(i);
+		while (list_size(&contextMapList) != 0)
+		{
+			int lrv;
+			SCONTEXTMAP * currentContextMap;
+
+			currentContextMap = list_get_at(&contextMapList, 0);
+			if (currentContextMap != NULL)
+				(void)SCardCleanContext(currentContextMap);
+			else
+				Log1(PCSC_LOG_CRITICAL, "list_get_at returned NULL");
+
+			lrv = list_delete_at(&contextMapList, 0);
+			if (lrv < 0)
+			{
+				Log2(PCSC_LOG_CRITICAL,
+						"list_delete_at failed with return value: %X", lrv);
+			}
+			/* man free says it is OK to call free(NULL) */
+			free(currentContextMap);
+		}
 
 		(void)SCardUnlockThread();
 
@@ -3547,9 +3701,9 @@
 	return SCARD_S_SUCCESS;
 }
 
-static LONG getReaderStates(LONG dwContextIndex)
-{
-	int32_t dwClientID = psContextMap[dwContextIndex].dwClientID;
+static LONG getReaderStates(SCONTEXTMAP * currentContextMap)
+{
+	int32_t dwClientID = currentContextMap->dwClientID;
 
 	if (-1 == SHMMessageSendWithHeader(CMD_GET_READERS_STATE, dwClientID, 0,
 		PCSCLITE_WRITE_TIMEOUT, NULL))

Modified: trunk/PCSC/src/winscard_svc.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_svc.c?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_svc.c (original)
+++ trunk/PCSC/src/winscard_svc.c Tue Nov 17 14:48:46 2009
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stddef.h>
+#include <stdlib.h>
 
 #include "pcscd.h"
 #include "winscard.h"
@@ -36,36 +37,87 @@
 #include "thread_generic.h"
 #include "readerfactory.h"
 #include "eventhandler.h"
+#include "simclist.h"
 
 /**
  * @brief Represents an Application Context on the Server side.
  *
  * An Application Context contains Channels (\c hCard).
  */
-static struct _psContext
+
+static unsigned int contextMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
+static unsigned int contextMaxCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
+
+/* Context tracking list */
+static list_t contextsList;
+
+struct _psContext
 {
 	uint32_t hContext;
-	uint32_t hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
+	list_t cardsList;
 	uint32_t dwClientID;			/**< Connection ID used to reference the Client. */
 	PCSCLITE_THREAD_T pthThread;		/**< Event polling thread's ID */
 	int protocol_major, protocol_minor;	/**< Protocol number agreed between client and server*/
-} psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
-
-static LONG MSGCheckHandleAssociation(SCARDHANDLE, DWORD);
-static LONG MSGAddContext(SCARDCONTEXT, DWORD);
-static LONG MSGRemoveContext(SCARDCONTEXT, DWORD);
-static LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, DWORD);
-static LONG MSGRemoveHandle(SCARDHANDLE, DWORD);
-static LONG MSGCleanupClient(DWORD);
+};
+typedef struct _psContext SCONTEXT;
+
+static LONG MSGCheckHandleAssociation(SCARDHANDLE, SCONTEXT *);
+static LONG MSGAddContext(SCARDCONTEXT, SCONTEXT *);
+static LONG MSGRemoveContext(SCARDCONTEXT, SCONTEXT *);
+static LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, SCONTEXT *);
+static LONG MSGRemoveHandle(SCARDHANDLE, SCONTEXT *);
+static LONG MSGCleanupClient(SCONTEXT *);
 
 static void ContextThread(LPVOID pdwIndex);
 
 extern READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
 
-LONG ContextsInitialize(void)
-{
-	memset(psContext, 0, sizeof(struct _psContext)*PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
+static int contextsListhContext_seeker(const void *el, const void *key)
+{
+	const SCONTEXT * currentContext = (SCONTEXT *)el;
+
+	if ((el == NULL) || (key == NULL))
+	{
+		Log3(PCSC_LOG_CRITICAL, "contextsListhContext_seeker called with NULL pointer: el=%X, key=%X", el, key);
+	}
+
+	if (currentContext->hContext == *(uint32_t *)key)
+		return 1;
+	return 0;
+}
+
+LONG ContextsInitialize(unsigned int customMaxThreadCounter, unsigned int customMaxThreadCardHandles)
+{
+	int lrv = 0;
+
+	if (customMaxThreadCounter != 0)
+		contextMaxThreadCounter = customMaxThreadCounter;
+
+	if (customMaxThreadCardHandles != 0)
+		contextMaxCardHandles = customMaxThreadCardHandles;
+
+	lrv = list_init(&contextsList);
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
+		return -1;
+	}
+	lrv = list_attributes_seeker(& contextsList, contextsListhContext_seeker);
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_attributes_seeker failed with return value: %X", lrv);
+		return -1;
+	}
+
 	return 1;
+}
+
+void ContextsDeinitialize(void)
+{
+	int listSize;
+	listSize = list_size(&contextsList);
+	Log2(PCSC_LOG_DEBUG, "remaining threads: %d", listSize);
+	/* This is currently a no-op. It should terminate the threads properly. */
 }
 
 /**
@@ -80,37 +132,93 @@
  */
 LONG CreateContextThread(uint32_t *pdwClientID)
 {
-	long i;
 	int rv;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
-	{
-		if (psContext[i].dwClientID == 0)
-		{
-			psContext[i].dwClientID = *pdwClientID;
-			*pdwClientID = 0;
-			break;
-		}
-	}
-
-	if (i == PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
-	{
-		Log2(PCSC_LOG_CRITICAL, "No more context available (max: %d)",
-			PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
-		return SCARD_F_INTERNAL_ERROR;
-	}
-
-	rv = SYS_ThreadCreate(&psContext[i].pthThread, THREAD_ATTR_DETACHED,
-		(PCSCLITE_THREAD_FUNCTION( )) ContextThread, (LPVOID) i);
+	int lrv;
+	int listSize;
+	SCONTEXT * newContext = NULL;
+
+	listSize = list_size(&contextsList);
+
+	if (listSize >= contextMaxThreadCounter)
+	{
+		Log2(PCSC_LOG_CRITICAL, "Too many context running: %d", listSize);
+		goto error;
+	}
+
+	/* Create the context for this thread. */
+	newContext = malloc(sizeof(*newContext));
+	if (NULL == newContext)
+	{
+		Log1(PCSC_LOG_CRITICAL, "Could not allocate new context");
+		goto error;
+	}
+	memset(newContext, 0, sizeof(*newContext));
+
+	newContext->dwClientID = *pdwClientID;
+
+	/* Initialise the list of card contexts */
+	lrv = list_init(&(newContext->cardsList));
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %X", lrv);
+		goto error;
+	}
+
+	/* request to store copies, and provide the metric function */
+	list_attributes_copy(&(newContext->cardsList), list_meter_int32_t, 1);
+
+	/* Adding a comparator
+	 * The stored type is SCARDHANDLE (long) but has only 32 bits
+	 * usefull even on a 64-bit CPU since the API between pcscd and
+	 * libpcscliter uses "int32_t hCard;"
+	 */
+	lrv = list_attributes_comparator(&(newContext->cardsList), list_comparator_int32_t);
+	if (lrv != 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_attributes_comparator failed with return value: %X", lrv);
+		list_destroy(&(newContext->cardsList));
+		goto error;
+	}
+
+	lrv = list_append(&contextsList, newContext);
+	if (lrv < 0)
+	{
+		Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X", lrv);
+		list_destroy(&(newContext->cardsList));
+		goto error;
+	}
+
+	rv = SYS_ThreadCreate(&(newContext->pthThread), THREAD_ATTR_DETACHED,
+		(PCSCLITE_THREAD_FUNCTION( )) ContextThread, (LPVOID) newContext);
 	if (rv)
 	{
-		(void)SYS_CloseFile(psContext[i].dwClientID);
-		psContext[i].dwClientID = 0;
+		int list_index;
+
 		Log2(PCSC_LOG_CRITICAL, "SYS_ThreadCreate failed: %s", strerror(rv));
-		return SCARD_E_NO_MEMORY;
+		list_index = list_locate(&contextsList, (const void *) newContext);
+		if (list_index >= 0)
+		{
+			int lrv2 = list_delete_at(&contextsList, list_index);
+			if (lrv2 < 0)
+				Log2(PCSC_LOG_CRITICAL, "list_delete_at() failed with error %X", lrv2);
+		}
+		else
+		{
+			Log3(PCSC_LOG_CRITICAL,
+				"list_locate() failed with error %X when looking for threadContext %X",
+				list_index, newContext);
+		}
+		list_destroy(&(newContext->cardsList));
+		goto error;
 	}
 
 	return SCARD_S_SUCCESS;
+
+error:
+	if (newContext)
+		free(newContext);
+	(void)SYS_CloseFile(*pdwClientID);
+	return SCARD_E_NO_MEMORY;
 }
 
 /*
@@ -124,7 +232,7 @@
  * For each Client message a new instance of this thread is created.
  *
  * @param[in] dwIndex Index of an avaiable Application Context slot in
- * \c psContext.
+ * \c SCONTEXT *.
  */
 static const char *CommandsText[] = {
 	"NULL",
@@ -159,13 +267,13 @@
 #define WRITE_BODY(v) \
 	ret = SHMMessageSend(&v, sizeof(v), filedes, PCSCLITE_WRITE_TIMEOUT);
 
-static void ContextThread(LPVOID dwIndex)
-{
-	DWORD dwContextIndex = (DWORD)dwIndex;
-	int32_t filedes = psContext[dwContextIndex].dwClientID;
-
-	Log2(PCSC_LOG_DEBUG, "Thread is started: %d",
-		psContext[dwContextIndex].dwClientID);
+static void ContextThread(LPVOID newContext)
+{
+	SCONTEXT * threadContext = (SCONTEXT *) newContext;
+	int32_t filedes = threadContext->dwClientID;
+
+	Log3(PCSC_LOG_DEBUG, "Thread is started: dwClientID=%d, threadContext @%X",
+		threadContext->dwClientID, threadContext);
 
 	while (1)
 	{
@@ -193,8 +301,8 @@
 				READ_BODY(veStr)
 
 				/* get the client protocol version */
-				psContext[dwContextIndex].protocol_major = veStr.major;
-				psContext[dwContextIndex].protocol_minor = veStr.minor;
+				threadContext->protocol_major = veStr.major;
+				threadContext->protocol_minor = veStr.minor;
 
 				Log3(PCSC_LOG_DEBUG,
 						"Client is protocol version %d:%d",
@@ -275,7 +383,7 @@
 
 				if (esStr.rv == SCARD_S_SUCCESS)
 					esStr.rv =
-						MSGAddContext(esStr.hContext, dwContextIndex);
+						MSGAddContext(esStr.hContext, threadContext);
 
 				WRITE_BODY(esStr)
 			}
@@ -291,7 +399,7 @@
 
 				if (reStr.rv == SCARD_S_SUCCESS)
 					reStr.rv =
-						MSGRemoveContext(reStr.hContext, dwContextIndex);
+						MSGRemoveContext(reStr.hContext, threadContext);
 
 				WRITE_BODY(reStr)
 			}
@@ -317,7 +425,7 @@
 
 				if (coStr.rv == SCARD_S_SUCCESS)
 					coStr.rv =
-						MSGAddHandle(coStr.hContext, coStr.hCard, dwContextIndex);
+						MSGAddHandle(coStr.hContext, coStr.hCard, threadContext);
 
 				WRITE_BODY(coStr)
 			}
@@ -330,7 +438,7 @@
 
 				READ_BODY(rcStr)
 
-				if (MSGCheckHandleAssociation(rcStr.hCard, dwContextIndex))
+				if (MSGCheckHandleAssociation(rcStr.hCard, threadContext))
 					goto exit;
 
 				rcStr.rv = SCardReconnect(rcStr.hCard, rcStr.dwShareMode,
@@ -349,14 +457,14 @@
 
 				READ_BODY(diStr)
 
-				rv = MSGCheckHandleAssociation(diStr.hCard, dwContextIndex);
+				rv = MSGCheckHandleAssociation(diStr.hCard, threadContext);
 				if (0 == rv)
 				{
 					diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition);
 
 					if (SCARD_S_SUCCESS == diStr.rv)
 						diStr.rv =
-							MSGRemoveHandle(diStr.hCard, dwContextIndex);
+							MSGRemoveHandle(diStr.hCard, threadContext);
 				}
 
 				WRITE_BODY(diStr)
@@ -370,7 +478,7 @@
 
 				READ_BODY(beStr)
 
-				rv = MSGCheckHandleAssociation(beStr.hCard, dwContextIndex);
+				rv = MSGCheckHandleAssociation(beStr.hCard, threadContext);
 				if (0 == rv)
 					beStr.rv = SCardBeginTransaction(beStr.hCard);
 
@@ -385,7 +493,7 @@
 
 				READ_BODY(enStr)
 
-				rv = MSGCheckHandleAssociation(enStr.hCard, dwContextIndex);
+				rv = MSGCheckHandleAssociation(enStr.hCard, threadContext);
 				if (0 == rv)
 					enStr.rv =
 						SCardEndTransaction(enStr.hCard, enStr.dwDisposition);
@@ -401,7 +509,7 @@
 
 				READ_BODY(caStr)
 
-				rv = MSGCheckHandleAssociation(caStr.hCard, dwContextIndex);
+				rv = MSGCheckHandleAssociation(caStr.hCard, threadContext);
 				if (0 == rv)
 					caStr.rv = SCardCancelTransaction(caStr.hCard);
 
@@ -412,23 +520,17 @@
 			case SCARD_CANCEL:
 			{
 				struct cancel_struct caStr;
-				uint32_t fd = 0;
-				int i;
-
+				SCONTEXT * psTargetContext = NULL;
 				READ_BODY(caStr)
 
 				/* find the client */
-				for (i=0; i<PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
+				psTargetContext = (SCONTEXT *) list_seek(&contextsList,
+					&(caStr.hContext));
+				if (psTargetContext != NULL)
 				{
-					if (psContext[i].hContext == caStr.hContext)
-					{
-						fd = psContext[i].dwClientID;
-						break;
-					}
+					uint32_t fd = psTargetContext->dwClientID;
+					caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED);
 				}
-
-				if (fd)
-					caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED);
 				else
 					caStr.rv = SCARD_E_INVALID_VALUE;
 
@@ -443,7 +545,7 @@
 
 				READ_BODY(stStr)
 
-				rv = MSGCheckHandleAssociation(stStr.hCard, dwContextIndex);
+				rv = MSGCheckHandleAssociation(stStr.hCard, threadContext);
 				if (0 == rv)
 				{
 					DWORD cchReaderLen;
@@ -491,7 +593,7 @@
 
 				READ_BODY(trStr)
 
-				if (MSGCheckHandleAssociation(trStr.hCard, dwContextIndex))
+				if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
 					goto exit;
 
 				/* avoids buffer overflow */
@@ -542,7 +644,7 @@
 
 				READ_BODY(ctStr)
 
-				if (MSGCheckHandleAssociation(ctStr.hCard, dwContextIndex))
+				if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
 					goto exit;
 
 				/* avoids buffer overflow */
@@ -586,7 +688,7 @@
 
 				READ_BODY(gsStr)
 
-				if (MSGCheckHandleAssociation(gsStr.hCard, dwContextIndex))
+				if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
 					goto exit;
 
 				/* avoids buffer overflow */
@@ -610,7 +712,7 @@
 
 				READ_BODY(gsStr)
 
-				if (MSGCheckHandleAssociation(gsStr.hCard, dwContextIndex))
+				if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
 					goto buffer_overflow;
 
 				/* avoids buffer overflow */
@@ -645,7 +747,7 @@
 	Log2(PCSC_LOG_DEBUG, "Wrong length: %d", filedes);
 exit:
 	(void)SYS_CloseFile(filedes);
-	(void)MSGCleanupClient(dwContextIndex);
+	(void)MSGCleanupClient(threadContext);
 	(void)SYS_ThreadExit((LPVOID) NULL);
 }
 
@@ -662,139 +764,148 @@
 	return ret;
 } /* MSGSignalClient */
 
-static LONG MSGAddContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
-{
-	psContext[dwContextIndex].hContext = hContext;
+static LONG MSGAddContext(SCARDCONTEXT hContext, SCONTEXT * threadContext)
+{
+	threadContext->hContext = hContext;
 	return SCARD_S_SUCCESS;
 }
 
-static LONG MSGRemoveContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
-{
-	int i;
+static LONG MSGRemoveContext(SCARDCONTEXT hContext, SCONTEXT * threadContext)
+{
 	LONG rv;
-
-	if (psContext[dwContextIndex].hContext == hContext)
-	{
-		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
+	int lrv;
+
+	if (threadContext->hContext != hContext)
+		return SCARD_E_INVALID_VALUE;
+
+	while (list_size(&(threadContext->cardsList)) != 0)
+	{
+		PREADER_CONTEXT rContext = NULL;
+		DWORD dwLockId;
+		SCARDHANDLE hCard;
+		void *ptr;
+
+		/*
+		 * Disconnect each of these just in case
+		 */
+		ptr = list_get_at(&(threadContext->cardsList), 0);
+		if (NULL == ptr)
+		{
+			Log1(PCSC_LOG_CRITICAL, "list_get_at failed");
+			continue;
+		}
+		hCard = *(int32_t *)ptr;
+
+		/*
+		 * Unlock the sharing
+		 */
+		rv = RFReaderInfoById(hCard, &rContext);
+		if (rv != SCARD_S_SUCCESS)
+			return rv;
+
+		dwLockId = rContext->dwLockId;
+		rContext->dwLockId = 0;
+
+		if (hCard != dwLockId)
 		{
 			/*
-			 * Disconnect each of these just in case
+			 * if the card is locked by someone else we do not reset it
+			 * and simulate a card removal
 			 */
-
-			if (psContext[dwContextIndex].hCard[i] != 0)
-			{
-				PREADER_CONTEXT rContext = NULL;
-				DWORD dwLockId;
-
-				/*
-				 * Unlock the sharing
-				 */
-				rv = RFReaderInfoById(psContext[dwContextIndex].hCard[i],
-					&rContext);
-				if (rv != SCARD_S_SUCCESS)
-					return rv;
-
-				dwLockId = rContext->dwLockId;
-				rContext->dwLockId = 0;
-
-				if (psContext[dwContextIndex].hCard[i] != dwLockId)
-				{
-					/*
-					 * if the card is locked by someone else we do not reset it
-					 * and simulate a card removal
-					 */
-					rv = SCARD_W_REMOVED_CARD;
-				}
-				else
-				{
-					/*
-					 * We will use SCardStatus to see if the card has been
-					 * reset there is no need to reset each time
-					 * Disconnect is called
-					 */
-					rv = SCardStatus(psContext[dwContextIndex].hCard[i], NULL,
-						NULL, NULL, NULL, NULL, NULL);
-				}
-
-				if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD)
-					(void)SCardDisconnect(psContext[dwContextIndex].hCard[i],
-						SCARD_LEAVE_CARD);
-				else
-					(void)SCardDisconnect(psContext[dwContextIndex].hCard[i],
-						SCARD_RESET_CARD);
-
-				psContext[dwContextIndex].hCard[i] = 0;
-			}
-		}
-
-		psContext[dwContextIndex].hContext = 0;
-		return SCARD_S_SUCCESS;
-	}
-
-	return SCARD_E_INVALID_VALUE;
+			rv = SCARD_W_REMOVED_CARD;
+		}
+		else
+		{
+			/*
+			 * We will use SCardStatus to see if the card has been
+			 * reset there is no need to reset each time
+			 * Disconnect is called
+			 */
+			rv = SCardStatus(hCard, NULL, NULL, NULL, NULL, NULL, NULL);
+		}
+
+		if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD)
+			(void)SCardDisconnect(hCard, SCARD_LEAVE_CARD);
+		else
+			(void)SCardDisconnect(hCard, SCARD_RESET_CARD);
+
+		/* Remove entry from the list */
+		lrv = list_delete_at(&(threadContext->cardsList), 0);
+		if (lrv < 0)
+			Log2(PCSC_LOG_CRITICAL,
+				"list_delete_at failed with return value: %X", lrv);
+	}
+	list_destroy(&(threadContext->cardsList))	;
+
+	/* We only mark the context as no longer in use.
+	 * The memory is freed in MSGCleanupCLient() */
+	threadContext->hContext = 0;
+
+	return SCARD_S_SUCCESS;
 }
 
 static LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard,
-	DWORD dwContextIndex)
-{
-	int i;
-
-	if (psContext[dwContextIndex].hContext == hContext)
-	{
-
+	SCONTEXT * threadContext)
+{
+	if (threadContext->hContext == hContext)
+	{
 		/*
 		 * Find an empty spot to put the hCard value
 		 */
-		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
-		{
-			if (psContext[dwContextIndex].hCard[i] == 0)
-			{
-				psContext[dwContextIndex].hCard[i] = hCard;
-				break;
-			}
-		}
-
-		if (i == PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS)
-		{
-			return SCARD_F_INTERNAL_ERROR;
-		} else
-		{
-			return SCARD_S_SUCCESS;
-		}
-
+		int listLength, lrv;
+
+		listLength = list_size(&(threadContext->cardsList));
+		if (listLength >= contextMaxCardHandles)
+		{
+			Log4(PCSC_LOG_DEBUG, "Too many card handles for thread context @%X: %d (max is %d)"
+				"Restart pcscd with --max-card-handle-per-thread value",
+				threadContext, listLength, contextMaxCardHandles);
+			return SCARD_E_NO_MEMORY;
+		}
+
+		lrv = list_append(&(threadContext->cardsList), &hCard);
+		if (lrv < 0)
+		{
+			Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %X",
+				lrv);
+			return SCARD_E_NO_MEMORY;
+		}
+		return SCARD_S_SUCCESS;
 	}
 
 	return SCARD_E_INVALID_VALUE;
 }
 
-static LONG MSGRemoveHandle(SCARDHANDLE hCard, DWORD dwContextIndex)
-{
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
-	{
-		if (psContext[dwContextIndex].hCard[i] == hCard)
-		{
-			psContext[dwContextIndex].hCard[i] = 0;
-			return SCARD_S_SUCCESS;
-		}
-	}
-
+static LONG MSGRemoveHandle(SCARDHANDLE hCard, SCONTEXT * threadContext)
+{
+	int list_index = 0;
+
+	list_index = list_locate(&(threadContext->cardsList), &hCard);
+	if (list_index >= 0)
+	{
+		int lrv;
+
+		lrv = list_delete_at(&(threadContext->cardsList), list_index);
+		if (lrv < 0)
+			Log2(PCSC_LOG_CRITICAL, "list_delete_at() failed with error %X", lrv);
+
+		return SCARD_S_SUCCESS;
+	}
+	else
+	{
+		Log3(PCSC_LOG_CRITICAL, "list_locate() failed with error %X when looking for hCard %X",
+			list_index, hCard);
+	}
 	return SCARD_E_INVALID_VALUE;
 }
 
 
-static LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, DWORD dwContextIndex)
-{
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
-	{
-		if (psContext[dwContextIndex].hCard[i] == hCard)
-		{
-			return 0;
-		}
-	}
+static LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, SCONTEXT * threadContext)
+{
+	int list_index = 0;
+	list_index = list_locate(&(threadContext->cardsList), &hCard);
+	if (list_index >= 0)
+		return 0;
 
 	/* Must be a rogue client, debug log and sleep a couple of seconds */
 	Log1(PCSC_LOG_ERROR, "Client failed to authenticate");
@@ -803,18 +914,44 @@
 	return -1;
 }
 
-static LONG MSGCleanupClient(DWORD dwContextIndex)
-{
-	if (psContext[dwContextIndex].hContext != 0)
-	{
-		(void)SCardReleaseContext(psContext[dwContextIndex].hContext);
-		(void)MSGRemoveContext(psContext[dwContextIndex].hContext,
-			dwContextIndex);
-	}
-
-	psContext[dwContextIndex].dwClientID = 0;
-	psContext[dwContextIndex].protocol_major = 0;
-	psContext[dwContextIndex].protocol_minor = 0;
+
+/* Should be called just prior to exiting the thread as it de-allocates
+ * the thread memory strucutres
+ */
+static LONG MSGCleanupClient(SCONTEXT * threadContext)
+{
+	int list_index = 0;
+	if (threadContext->hContext != 0)
+	{
+		(void)SCardReleaseContext(threadContext->hContext);
+		(void)MSGRemoveContext(threadContext->hContext, threadContext);
+	}
+
+	Log3(PCSC_LOG_DEBUG,
+		"Thread is stopping: dwClientID=%d, threadContext @%X",
+		threadContext->dwClientID, threadContext);
+
+	/* Clear the struct to ensure that we detect
+	 * access to de-allocated memory
+	 * Hopefully the compiler won't optimise it out */
+	memset((void*) threadContext, 0, sizeof(SCONTEXT));
+	Log2(PCSC_LOG_DEBUG, "Freeing SCONTEXT @%X", threadContext);
+	list_index = list_locate(&contextsList, (const void *) threadContext);
+	if (list_index >= 0)
+	{
+		int lrv = list_delete_at(&contextsList, list_index);
+		if (lrv < 0)
+		{
+			Log2(PCSC_LOG_CRITICAL, "list_delete_at() failed with error %x", lrv);
+		}
+	}
+	else
+	{
+		Log3(PCSC_LOG_CRITICAL, "list_locate() failed with error %X when looking for threadContext %X",
+			list_index, threadContext);
+	}
+
+	free(threadContext);
 
 	return 0;
 }

Modified: trunk/PCSC/src/winscard_svc.h
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_svc.h?rev=4553&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_svc.h (original)
+++ trunk/PCSC/src/winscard_svc.h Tue Nov 17 14:48:46 2009
@@ -24,7 +24,8 @@
 extern "C"
 {
 #endif
-	LONG ContextsInitialize(void);
+	LONG ContextsInitialize(unsigned int, unsigned int);
+	void ContextsDeinitialize(void);
 	LONG CreateContextThread(uint32_t *);
 	LONG MSGSignalClient(uint32_t filedes, LONG rv);
 #ifdef __cplusplus




More information about the Pcsclite-cvs-commit mailing list