43
#define dprintf(s) printf(s)
44
#define dprintf1(s, p1) printf(s, p1)
45
#define dprintf2(s, p1, p2) printf(s, p1, p2)
46
#define dprintf3(s, p1, p2, p3) printf(s, p1, p2, p3)
49
#define dprintf1(s, p1)
50
#define dprintf2(s, p1, p2)
51
#define dprintf3(s, p1, p2, p3)
54
#include "sun_security_smartcardio_PCSC.h"
60
#define MAX_STACK_BUFFER_SIZE 8192
63
#define ATR_BUFFER_SIZE 128
64
#define READERNAME_BUFFER_SIZE 128
65
#define RECEIVE_BUFFER_SIZE MAX_STACK_BUFFER_SIZE
67
#define J2PCSC_EXCEPTION_NAME "sun/security/smartcardio/PCSCException"
69
static void throwOutOfMemoryError(JNIEnv *env, const char *msg) {
70
jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
73
(*env)->ThrowNew(env, cls, msg);
77
void throwPCSCException(JNIEnv* env, LONG code) {
79
jmethodID constructor;
80
jthrowable pcscException;
82
pcscClass = (*env)->FindClass(env, J2PCSC_EXCEPTION_NAME);
83
if (pcscClass == NULL) {
86
constructor = (*env)->GetMethodID(env, pcscClass, "<init>", "(I)V");
87
if (constructor == NULL) {
90
pcscException = (jthrowable) (*env)->NewObject(env, pcscClass,
91
constructor, (jint)code);
92
if (pcscException != NULL) {
93
(*env)->Throw(env, pcscException);
97
jboolean handleRV(JNIEnv* env, LONG code) {
98
if (code == SCARD_S_SUCCESS) {
101
throwPCSCException(env, code);
106
JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
107
return JNI_VERSION_1_4;
110
JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardEstablishContext
111
(JNIEnv *env, jclass thisClass, jint dwScope)
113
SCARDCONTEXT context = 0;
115
dprintf("-establishContext\n");
116
rv = CALL_SCardEstablishContext(dwScope, NULL, NULL, &context);
117
if (handleRV(env, rv)) {
121
return (jlong)context;
127
jobjectArray pcsc_multi2jstring(JNIEnv *env, char *spec) {
130
char *cp, **tab = NULL;
136
cp += (strlen(cp) + 1);
140
tab = (char **)malloc(cnt * sizeof(char *));
142
throwOutOfMemoryError(env, NULL);
150
cp += (strlen(cp) + 1);
153
stringClass = (*env)->FindClass(env, "java/lang/String");
154
if (stringClass == NULL) {
159
result = (*env)->NewObjectArray(env, cnt, stringClass, NULL);
160
if (result != NULL) {
162
js = (*env)->NewStringUTF(env, tab[cnt]);
163
if ((*env)->ExceptionCheck(env)) {
167
(*env)->SetObjectArrayElement(env, result, cnt, js);
168
if ((*env)->ExceptionCheck(env)) {
172
(*env)->DeleteLocalRef(env, js);
179
JNIEXPORT jobjectArray JNICALL Java_sun_security_smartcardio_PCSC_SCardListReaders
180
(JNIEnv *env, jclass thisClass, jlong jContext)
182
SCARDCONTEXT context = (SCARDCONTEXT)jContext;
184
LPSTR mszReaders = NULL;
188
dprintf1("-context: %x\n", context);
189
rv = CALL_SCardListReaders(context, NULL, NULL, &size);
190
if (handleRV(env, rv)) {
193
dprintf1("-size: %d\n", size);
196
mszReaders = malloc(size);
197
if (mszReaders == NULL) {
198
throwOutOfMemoryError(env, NULL);
202
rv = CALL_SCardListReaders(context, NULL, mszReaders, &size);
203
if (handleRV(env, rv)) {
207
dprintf1("-String: %s\n", mszReaders);
212
result = pcsc_multi2jstring(env, mszReaders);
217
JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardConnect
218
(JNIEnv *env, jclass thisClass, jlong jContext, jstring jReaderName,
219
jint jShareMode, jint jPreferredProtocols)
221
SCARDCONTEXT context = (SCARDCONTEXT)jContext;
224
SCARDHANDLE card = 0;
227
readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
228
if (readerName == NULL) {
231
rv = CALL_SCardConnect(context, readerName, jShareMode, jPreferredProtocols, &card, &proto);
232
(*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
233
dprintf1("-cardhandle: %x\n", card);
234
dprintf1("-protocol: %d\n", proto);
235
if (handleRV(env, rv)) {
242
JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardTransmit
243
(JNIEnv *env, jclass thisClass, jlong jCard, jint protocol,
244
jbyteArray jBuf, jint jOfs, jint jLen)
246
SCARDHANDLE card = (SCARDHANDLE)jCard;
248
SCARD_IO_REQUEST sendPci;
250
unsigned char rbuf[RECEIVE_BUFFER_SIZE];
251
DWORD rlen = RECEIVE_BUFFER_SIZE;
256
sendPci.dwProtocol = protocol;
257
sendPci.cbPciLength = sizeof(SCARD_IO_REQUEST);
259
sbuf = (unsigned char *) ((*env)->GetByteArrayElements(env, jBuf, NULL));
263
rv = CALL_SCardTransmit(card, &sendPci, sbuf + ofs, len, NULL, rbuf, &rlen);
264
(*env)->ReleaseByteArrayElements(env, jBuf, (jbyte *)sbuf, JNI_ABORT);
266
if (handleRV(env, rv)) {
270
jOut = (*env)->NewByteArray(env, rlen);
272
(*env)->SetByteArrayRegion(env, jOut, 0, rlen, (jbyte *)rbuf);
273
if ((*env)->ExceptionCheck(env)) {
280
JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardStatus
281
(JNIEnv *env, jclass thisClass, jlong jCard, jbyteArray jStatus)
283
SCARDHANDLE card = (SCARDHANDLE)jCard;
285
char readerName[READERNAME_BUFFER_SIZE];
286
DWORD readerLen = READERNAME_BUFFER_SIZE;
287
unsigned char atr[ATR_BUFFER_SIZE];
288
DWORD atrLen = ATR_BUFFER_SIZE;
294
rv = CALL_SCardStatus(card, readerName, &readerLen, &state, &protocol, atr, &atrLen);
295
if (handleRV(env, rv)) {
298
dprintf1("-reader: %s\n", readerName);
299
dprintf1("-status: %d\n", state);
300
dprintf1("-protocol: %d\n", protocol);
302
jArray = (*env)->NewByteArray(env, atrLen);
303
if (jArray == NULL) {
306
(*env)->SetByteArrayRegion(env, jArray, 0, atrLen, (jbyte *)atr);
307
if ((*env)->ExceptionCheck(env)) {
310
status[0] = (jbyte) state;
311
status[1] = (jbyte) protocol;
312
(*env)->SetByteArrayRegion(env, jStatus, 0, 2, status);
313
if ((*env)->ExceptionCheck(env)) {
319
JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardDisconnect
320
(JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
322
SCARDHANDLE card = (SCARDHANDLE)jCard;
325
rv = CALL_SCardDisconnect(card, jDisposition);
326
dprintf1("-disconnect: 0x%X\n", rv);
331
JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusChange
332
(JNIEnv *env, jclass thisClass, jlong jContext, jlong jTimeout,
333
jintArray jCurrentState, jobjectArray jReaderNames)
335
SCARDCONTEXT context = (SCARDCONTEXT)jContext;
337
int readers = (*env)->GetArrayLength(env, jReaderNames);
338
SCARD_READERSTATE *readerState;
340
jintArray jEventState = NULL;
341
int *currentState = NULL;
342
const char *readerName;
344
readerState = calloc(readers, sizeof(SCARD_READERSTATE));
345
if (readerState == NULL && readers > 0) {
346
throwOutOfMemoryError(env, NULL);
350
currentState = (*env)->GetIntArrayElements(env, jCurrentState, NULL);
351
if (currentState == NULL) {
356
for (i = 0; i < readers; i++) {
357
readerState[i].szReader = NULL;
360
for (i = 0; i < readers; i++) {
361
jobject jReaderName = (*env)->GetObjectArrayElement(env, jReaderNames, i);
362
if ((*env)->ExceptionCheck(env)) {
365
readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
366
if (readerName == NULL) {
369
readerState[i].szReader = strdup(readerName);
370
(*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
371
if (readerState[i].szReader == NULL) {
372
throwOutOfMemoryError(env, NULL);
375
readerState[i].pvUserData = NULL;
376
readerState[i].dwCurrentState = currentState[i];
377
readerState[i].dwEventState = SCARD_STATE_UNAWARE;
378
readerState[i].cbAtr = 0;
379
(*env)->DeleteLocalRef(env, jReaderName);
383
rv = CALL_SCardGetStatusChange(context, (DWORD)jTimeout, readerState, readers);
384
if (handleRV(env, rv)) {
389
jEventState = (*env)->NewIntArray(env, readers);
390
if (jEventState == NULL) {
393
for (i = 0; i < readers; i++) {
395
dprintf3("-reader status %s: 0x%X, 0x%X\n", readerState[i].szReader,
396
readerState[i].dwCurrentState, readerState[i].dwEventState);
397
eventStateTmp = (jint)readerState[i].dwEventState;
398
(*env)->SetIntArrayRegion(env, jEventState, i, 1, &eventStateTmp);
399
if ((*env)->ExceptionCheck(env)) {
405
(*env)->ReleaseIntArrayElements(env, jCurrentState, currentState, JNI_ABORT);
406
for (i = 0; i < readers; i++) {
407
free((char *)readerState[i].szReader);
413
JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardBeginTransaction
414
(JNIEnv *env, jclass thisClass, jlong jCard)
416
SCARDHANDLE card = (SCARDHANDLE)jCard;
419
rv = CALL_SCardBeginTransaction(card);
420
dprintf1("-beginTransaction: 0x%X\n", rv);
425
JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardEndTransaction
426
(JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
428
SCARDHANDLE card = (SCARDHANDLE)jCard;
431
rv = CALL_SCardEndTransaction(card, jDisposition);
432
dprintf1("-endTransaction: 0x%X\n", rv);
437
JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardControl
438
(JNIEnv *env, jclass thisClass, jlong jCard, jint jControlCode, jbyteArray jSendBuffer)
440
SCARDHANDLE card = (SCARDHANDLE)jCard;
443
jint sendBufferLength = (*env)->GetArrayLength(env, jSendBuffer);
444
jbyte receiveBuffer[MAX_STACK_BUFFER_SIZE];
445
jint receiveBufferLength = MAX_STACK_BUFFER_SIZE;
446
ULONG returnedLength = 0;
447
jbyteArray jReceiveBuffer;
449
sendBuffer = (*env)->GetByteArrayElements(env, jSendBuffer, NULL);
450
if (sendBuffer == NULL) {
457
printf("-control: 0x%X\n", jControlCode);
459
for (k = 0; k < sendBufferLength; k++) {
460
printf("%02x ", sendBuffer[k]);
466
rv = CALL_SCardControl(card, jControlCode, sendBuffer, sendBufferLength,
467
receiveBuffer, receiveBufferLength, &returnedLength);
469
(*env)->ReleaseByteArrayElements(env, jSendBuffer, sendBuffer, JNI_ABORT);
470
if (handleRV(env, rv)) {
478
for (k = 0; k < returnedLength; k++) {
479
printf("%02x ", receiveBuffer[k]);
485
jReceiveBuffer = (*env)->NewByteArray(env, returnedLength);
486
if (jReceiveBuffer == NULL) {
489
(*env)->SetByteArrayRegion(env, jReceiveBuffer, 0, returnedLength, receiveBuffer);
490
if ((*env)->ExceptionCheck(env)) {
493
return jReceiveBuffer;