annotate jdk/src/java.smartcardio/share/native/libj2pcsc/pcsc.c @ 33653:c1ee09fe3274

8136556: Add the ability to perform static builds of MacOSX x64 binaries Reviewed-by: ihse, bdelsart, gadams, lfoltan, rriggs, hseigel, twisti
author bobv
date Mon, 19 Oct 2015 13:41:09 -0400
parents 3317bb8137f4
children
rev   line source
duke@2 1 /*
bobv@33653 2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
duke@2 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@2 4 *
duke@2 5 * This code is free software; you can redistribute it and/or modify it
duke@2 6 * under the terms of the GNU General Public License version 2 only, as
ohair@5506 7 * published by the Free Software Foundation. Oracle designates this
duke@2 8 * particular file as subject to the "Classpath" exception as provided
ohair@5506 9 * by Oracle in the LICENSE file that accompanied this code.
duke@2 10 *
duke@2 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@2 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@2 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@2 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@2 15 * accompanied this code).
duke@2 16 *
duke@2 17 * You should have received a copy of the GNU General Public License version
duke@2 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@2 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@2 20 *
ohair@5506 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@5506 22 * or visit www.oracle.com if you need additional information or have any
ohair@5506 23 * questions.
duke@2 24 */
duke@2 25
duke@2 26 /* disable asserts in product mode */
duke@2 27 #ifndef DEBUG
duke@2 28 #ifndef NDEBUG
duke@2 29 #define NDEBUG
duke@2 30 #endif
duke@2 31 #endif
duke@2 32
duke@2 33 #include <stdio.h>
duke@2 34 #include <stdlib.h>
duke@2 35 #include <string.h>
duke@2 36 #include <assert.h>
duke@2 37
duke@2 38 #include <winscard.h>
duke@2 39
duke@2 40 // #define J2PCSC_DEBUG
duke@2 41
duke@2 42 #ifdef J2PCSC_DEBUG
duke@2 43 #define dprintf(s) printf(s)
duke@2 44 #define dprintf1(s, p1) printf(s, p1)
duke@2 45 #define dprintf2(s, p1, p2) printf(s, p1, p2)
duke@2 46 #define dprintf3(s, p1, p2, p3) printf(s, p1, p2, p3)
duke@2 47 #else
duke@2 48 #define dprintf(s)
duke@2 49 #define dprintf1(s, p1)
duke@2 50 #define dprintf2(s, p1, p2)
duke@2 51 #define dprintf3(s, p1, p2, p3)
duke@2 52 #endif
duke@2 53
duke@2 54 #include "sun_security_smartcardio_PCSC.h"
duke@2 55
duke@2 56 #include "pcsc_md.h"
duke@2 57
bobv@33653 58 #include "jni_util.h"
bobv@33653 59
duke@2 60 #define MAX_STACK_BUFFER_SIZE 8192
duke@2 61
duke@2 62 // make the buffers larger than what should be necessary, just in case
duke@2 63 #define ATR_BUFFER_SIZE 128
duke@2 64 #define READERNAME_BUFFER_SIZE 128
duke@2 65 #define RECEIVE_BUFFER_SIZE MAX_STACK_BUFFER_SIZE
duke@2 66
duke@2 67 #define J2PCSC_EXCEPTION_NAME "sun/security/smartcardio/PCSCException"
duke@2 68
chegar@23709 69 void throwOutOfMemoryError(JNIEnv *env, const char *msg) {
chegar@23709 70 jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
valeriep@23704 71
chegar@23709 72 if (cls != NULL) /* Otherwise an exception has already been thrown */
chegar@23709 73 (*env)->ThrowNew(env, cls, msg);
chegar@23709 74
valeriep@23704 75 }
valeriep@23704 76
duke@2 77 void throwPCSCException(JNIEnv* env, LONG code) {
duke@2 78 jclass pcscClass;
duke@2 79 jmethodID constructor;
duke@2 80 jthrowable pcscException;
duke@2 81
duke@2 82 pcscClass = (*env)->FindClass(env, J2PCSC_EXCEPTION_NAME);
valeriep@23704 83 if (pcscClass == NULL) {
valeriep@23704 84 return;
valeriep@23704 85 }
duke@2 86 constructor = (*env)->GetMethodID(env, pcscClass, "<init>", "(I)V");
valeriep@23704 87 if (constructor == NULL) {
valeriep@23704 88 return;
valeriep@23704 89 }
valeriep@23704 90 pcscException = (jthrowable) (*env)->NewObject(env, pcscClass,
valeriep@23704 91 constructor, (jint)code);
valeriep@23704 92 if (pcscException != NULL) {
valeriep@23704 93 (*env)->Throw(env, pcscException);
valeriep@23704 94 }
duke@2 95 }
duke@2 96
duke@2 97 jboolean handleRV(JNIEnv* env, LONG code) {
duke@2 98 if (code == SCARD_S_SUCCESS) {
duke@2 99 return JNI_FALSE;
duke@2 100 } else {
duke@2 101 throwPCSCException(env, code);
duke@2 102 return JNI_TRUE;
duke@2 103 }
duke@2 104 }
duke@2 105
bobv@33653 106 JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
duke@2 107 return JNI_VERSION_1_4;
duke@2 108 }
duke@2 109
duke@2 110 JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardEstablishContext
duke@2 111 (JNIEnv *env, jclass thisClass, jint dwScope)
duke@2 112 {
igerasim@24516 113 SCARDCONTEXT context = 0;
duke@2 114 LONG rv;
duke@2 115 dprintf("-establishContext\n");
duke@2 116 rv = CALL_SCardEstablishContext(dwScope, NULL, NULL, &context);
duke@2 117 if (handleRV(env, rv)) {
duke@2 118 return 0;
duke@2 119 }
duke@2 120 // note: SCARDCONTEXT is typedef'd as long, so this works
duke@2 121 return (jlong)context;
duke@2 122 }
duke@2 123
duke@2 124 /**
duke@2 125 * Convert a multi string to a java string array,
duke@2 126 */
igerasim@24630 127 jobjectArray pcsc_multi2jstring(JNIEnv *env, char *spec) {
duke@2 128 jobjectArray result;
duke@2 129 jclass stringClass;
igerasim@24630 130 char *cp, **tab = NULL;
duke@2 131 jstring js;
duke@2 132 int cnt = 0;
duke@2 133
igerasim@24630 134 cp = spec;
igerasim@24630 135 while (*cp != 0) {
igerasim@24630 136 cp += (strlen(cp) + 1);
igerasim@24630 137 ++cnt;
igerasim@24630 138 }
igerasim@24630 139
igerasim@24630 140 tab = (char **)malloc(cnt * sizeof(char *));
igerasim@24630 141 if (tab == NULL) {
igerasim@24630 142 throwOutOfMemoryError(env, NULL);
igerasim@24630 143 return NULL;
igerasim@24630 144 }
igerasim@24630 145
igerasim@24630 146 cnt = 0;
igerasim@24630 147 cp = spec;
igerasim@24630 148 while (*cp != 0) {
igerasim@24630 149 tab[cnt++] = cp;
igerasim@24630 150 cp += (strlen(cp) + 1);
duke@2 151 }
duke@2 152
duke@2 153 stringClass = (*env)->FindClass(env, "java/lang/String");
valeriep@23704 154 if (stringClass == NULL) {
igerasim@24630 155 free(tab);
valeriep@23704 156 return NULL;
valeriep@23704 157 }
duke@2 158
duke@2 159 result = (*env)->NewObjectArray(env, cnt, stringClass, NULL);
valeriep@23704 160 if (result != NULL) {
valeriep@23704 161 while (cnt-- > 0) {
valeriep@23704 162 js = (*env)->NewStringUTF(env, tab[cnt]);
valeriep@23704 163 if ((*env)->ExceptionCheck(env)) {
igerasim@24630 164 free(tab);
valeriep@23704 165 return NULL;
valeriep@23704 166 }
valeriep@23704 167 (*env)->SetObjectArrayElement(env, result, cnt, js);
valeriep@23704 168 if ((*env)->ExceptionCheck(env)) {
igerasim@24630 169 free(tab);
valeriep@23704 170 return NULL;
valeriep@23704 171 }
valeriep@23704 172 (*env)->DeleteLocalRef(env, js);
valeriep@23704 173 }
duke@2 174 }
igerasim@24630 175 free(tab);
duke@2 176 return result;
duke@2 177 }
duke@2 178
duke@2 179 JNIEXPORT jobjectArray JNICALL Java_sun_security_smartcardio_PCSC_SCardListReaders
duke@2 180 (JNIEnv *env, jclass thisClass, jlong jContext)
duke@2 181 {
duke@2 182 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 183 LONG rv;
igerasim@24627 184 LPTSTR mszReaders = NULL;
igerasim@24516 185 DWORD size = 0;
duke@2 186 jobjectArray result;
duke@2 187
duke@2 188 dprintf1("-context: %x\n", context);
duke@2 189 rv = CALL_SCardListReaders(context, NULL, NULL, &size);
duke@2 190 if (handleRV(env, rv)) {
duke@2 191 return NULL;
duke@2 192 }
duke@2 193 dprintf1("-size: %d\n", size);
duke@2 194
igerasim@24627 195 if (size) {
igerasim@24627 196 mszReaders = malloc(size);
igerasim@24627 197 if (mszReaders == NULL) {
igerasim@24627 198 throwOutOfMemoryError(env, NULL);
igerasim@24627 199 return NULL;
igerasim@24627 200 }
igerasim@24627 201
igerasim@24627 202 rv = CALL_SCardListReaders(context, NULL, mszReaders, &size);
igerasim@24627 203 if (handleRV(env, rv)) {
igerasim@24627 204 free(mszReaders);
igerasim@24627 205 return NULL;
igerasim@24627 206 }
igerasim@24627 207 dprintf1("-String: %s\n", mszReaders);
valeriep@23704 208 }
valeriep@23704 209
igerasim@24630 210 result = pcsc_multi2jstring(env, mszReaders);
duke@2 211 free(mszReaders);
duke@2 212 return result;
duke@2 213 }
duke@2 214
duke@2 215 JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardConnect
duke@2 216 (JNIEnv *env, jclass thisClass, jlong jContext, jstring jReaderName,
duke@2 217 jint jShareMode, jint jPreferredProtocols)
duke@2 218 {
duke@2 219 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 220 LONG rv;
duke@2 221 LPCTSTR readerName;
igerasim@24516 222 SCARDHANDLE card = 0;
igerasim@24516 223 DWORD proto = 0;
duke@2 224
duke@2 225 readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
valeriep@23704 226 if (readerName == NULL) {
valeriep@23704 227 return 0;
valeriep@23704 228 }
duke@2 229 rv = CALL_SCardConnect(context, readerName, jShareMode, jPreferredProtocols, &card, &proto);
duke@2 230 (*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
duke@2 231 dprintf1("-cardhandle: %x\n", card);
duke@2 232 dprintf1("-protocol: %d\n", proto);
duke@2 233 if (handleRV(env, rv)) {
duke@2 234 return 0;
duke@2 235 }
duke@2 236
duke@2 237 return (jlong)card;
duke@2 238 }
duke@2 239
duke@2 240 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardTransmit
duke@2 241 (JNIEnv *env, jclass thisClass, jlong jCard, jint protocol,
duke@2 242 jbyteArray jBuf, jint jOfs, jint jLen)
duke@2 243 {
duke@2 244 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 245 LONG rv;
duke@2 246 SCARD_IO_REQUEST sendPci;
duke@2 247 unsigned char *sbuf;
duke@2 248 unsigned char rbuf[RECEIVE_BUFFER_SIZE];
duke@2 249 DWORD rlen = RECEIVE_BUFFER_SIZE;
duke@2 250 int ofs = (int)jOfs;
duke@2 251 int len = (int)jLen;
duke@2 252 jbyteArray jOut;
duke@2 253
duke@2 254 sendPci.dwProtocol = protocol;
duke@2 255 sendPci.cbPciLength = sizeof(SCARD_IO_REQUEST);
duke@2 256
duke@2 257 sbuf = (unsigned char *) ((*env)->GetByteArrayElements(env, jBuf, NULL));
valeriep@23704 258 if (sbuf == NULL) {
valeriep@23704 259 return NULL;
valeriep@23704 260 }
duke@2 261 rv = CALL_SCardTransmit(card, &sendPci, sbuf + ofs, len, NULL, rbuf, &rlen);
duke@2 262 (*env)->ReleaseByteArrayElements(env, jBuf, (jbyte *)sbuf, JNI_ABORT);
duke@2 263
duke@2 264 if (handleRV(env, rv)) {
duke@2 265 return NULL;
duke@2 266 }
duke@2 267
duke@2 268 jOut = (*env)->NewByteArray(env, rlen);
valeriep@23704 269 if (jOut != NULL) {
valeriep@23704 270 (*env)->SetByteArrayRegion(env, jOut, 0, rlen, (jbyte *)rbuf);
valeriep@23704 271 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 272 return NULL;
valeriep@23704 273 }
valeriep@23704 274 }
duke@2 275 return jOut;
duke@2 276 }
duke@2 277
duke@2 278 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardStatus
duke@2 279 (JNIEnv *env, jclass thisClass, jlong jCard, jbyteArray jStatus)
duke@2 280 {
duke@2 281 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 282 LONG rv;
duke@2 283 char readerName[READERNAME_BUFFER_SIZE];
duke@2 284 DWORD readerLen = READERNAME_BUFFER_SIZE;
duke@2 285 unsigned char atr[ATR_BUFFER_SIZE];
duke@2 286 DWORD atrLen = ATR_BUFFER_SIZE;
igerasim@24516 287 DWORD state = 0;
igerasim@24516 288 DWORD protocol = 0;
duke@2 289 jbyteArray jArray;
valeriep@23704 290 jbyte status[2];
duke@2 291
duke@2 292 rv = CALL_SCardStatus(card, readerName, &readerLen, &state, &protocol, atr, &atrLen);
duke@2 293 if (handleRV(env, rv)) {
duke@2 294 return NULL;
duke@2 295 }
duke@2 296 dprintf1("-reader: %s\n", readerName);
duke@2 297 dprintf1("-status: %d\n", state);
duke@2 298 dprintf1("-protocol: %d\n", protocol);
duke@2 299
duke@2 300 jArray = (*env)->NewByteArray(env, atrLen);
valeriep@23704 301 if (jArray == NULL) {
valeriep@23704 302 return NULL;
valeriep@23704 303 }
duke@2 304 (*env)->SetByteArrayRegion(env, jArray, 0, atrLen, (jbyte *)atr);
valeriep@23704 305 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 306 return NULL;
valeriep@23704 307 }
valeriep@23704 308 status[0] = (jbyte) state;
valeriep@23704 309 status[1] = (jbyte) protocol;
valeriep@23704 310 (*env)->SetByteArrayRegion(env, jStatus, 0, 2, status);
valeriep@23704 311 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 312 return NULL;
valeriep@23704 313 }
duke@2 314 return jArray;
duke@2 315 }
duke@2 316
duke@2 317 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardDisconnect
duke@2 318 (JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
duke@2 319 {
duke@2 320 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 321 LONG rv;
duke@2 322
duke@2 323 rv = CALL_SCardDisconnect(card, jDisposition);
duke@2 324 dprintf1("-disconnect: 0x%X\n", rv);
duke@2 325 handleRV(env, rv);
duke@2 326 return;
duke@2 327 }
duke@2 328
duke@2 329 JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusChange
duke@2 330 (JNIEnv *env, jclass thisClass, jlong jContext, jlong jTimeout,
duke@2 331 jintArray jCurrentState, jobjectArray jReaderNames)
duke@2 332 {
duke@2 333 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 334 LONG rv;
duke@2 335 int readers = (*env)->GetArrayLength(env, jReaderNames);
valeriep@23704 336 SCARD_READERSTATE *readerState;
duke@2 337 int i;
valeriep@23704 338 jintArray jEventState = NULL;
valeriep@23704 339 int *currentState = NULL;
valeriep@23704 340 const char *readerName;
valeriep@23704 341
valeriep@23704 342 readerState = calloc(readers, sizeof(SCARD_READERSTATE));
igerasim@24627 343 if (readerState == NULL && readers > 0) {
valeriep@23704 344 throwOutOfMemoryError(env, NULL);
valeriep@23704 345 return NULL;
valeriep@23704 346 }
valeriep@23704 347
valeriep@23704 348 currentState = (*env)->GetIntArrayElements(env, jCurrentState, NULL);
valeriep@23704 349 if (currentState == NULL) {
valeriep@23704 350 free(readerState);
valeriep@23704 351 return NULL;
valeriep@23704 352 }
duke@2 353
duke@2 354 for (i = 0; i < readers; i++) {
igerasim@24627 355 readerState[i].szReader = NULL;
igerasim@24627 356 }
igerasim@24627 357
igerasim@24627 358 for (i = 0; i < readers; i++) {
duke@2 359 jobject jReaderName = (*env)->GetObjectArrayElement(env, jReaderNames, i);
valeriep@23704 360 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 361 goto cleanup;
valeriep@23704 362 }
valeriep@23704 363 readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
valeriep@23704 364 if (readerName == NULL) {
valeriep@23704 365 goto cleanup;
valeriep@23704 366 }
valeriep@23704 367 readerState[i].szReader = strdup(readerName);
valeriep@23704 368 (*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
valeriep@23704 369 if (readerState[i].szReader == NULL) {
valeriep@23704 370 throwOutOfMemoryError(env, NULL);
valeriep@23704 371 goto cleanup;
valeriep@23704 372 }
duke@2 373 readerState[i].pvUserData = NULL;
duke@2 374 readerState[i].dwCurrentState = currentState[i];
duke@2 375 readerState[i].dwEventState = SCARD_STATE_UNAWARE;
duke@2 376 readerState[i].cbAtr = 0;
valeriep@23704 377 (*env)->DeleteLocalRef(env, jReaderName);
duke@2 378 }
duke@2 379
igerasim@24627 380 if (readers > 0) {
igerasim@24627 381 rv = CALL_SCardGetStatusChange(context, (DWORD)jTimeout, readerState, readers);
igerasim@24627 382 if (handleRV(env, rv)) {
igerasim@24627 383 goto cleanup;
igerasim@24627 384 }
valeriep@23704 385 }
duke@2 386
duke@2 387 jEventState = (*env)->NewIntArray(env, readers);
valeriep@23704 388 if (jEventState == NULL) {
valeriep@23704 389 goto cleanup;
valeriep@23704 390 }
duke@2 391 for (i = 0; i < readers; i++) {
duke@2 392 jint eventStateTmp;
duke@2 393 dprintf3("-reader status %s: 0x%X, 0x%X\n", readerState[i].szReader,
duke@2 394 readerState[i].dwCurrentState, readerState[i].dwEventState);
duke@2 395 eventStateTmp = (jint)readerState[i].dwEventState;
duke@2 396 (*env)->SetIntArrayRegion(env, jEventState, i, 1, &eventStateTmp);
valeriep@23704 397 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 398 jEventState = NULL;
valeriep@23704 399 goto cleanup;
valeriep@23704 400 }
valeriep@23704 401 }
valeriep@23704 402 cleanup:
valeriep@23704 403 (*env)->ReleaseIntArrayElements(env, jCurrentState, currentState, JNI_ABORT);
valeriep@23704 404 for (i = 0; i < readers; i++) {
valeriep@23704 405 free((char *)readerState[i].szReader);
duke@2 406 }
duke@2 407 free(readerState);
duke@2 408 return jEventState;
duke@2 409 }
duke@2 410
duke@2 411 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardBeginTransaction
duke@2 412 (JNIEnv *env, jclass thisClass, jlong jCard)
duke@2 413 {
duke@2 414 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 415 LONG rv;
duke@2 416
duke@2 417 rv = CALL_SCardBeginTransaction(card);
duke@2 418 dprintf1("-beginTransaction: 0x%X\n", rv);
duke@2 419 handleRV(env, rv);
duke@2 420 return;
duke@2 421 }
duke@2 422
duke@2 423 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardEndTransaction
duke@2 424 (JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
duke@2 425 {
duke@2 426 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 427 LONG rv;
duke@2 428
duke@2 429 rv = CALL_SCardEndTransaction(card, jDisposition);
duke@2 430 dprintf1("-endTransaction: 0x%X\n", rv);
duke@2 431 handleRV(env, rv);
duke@2 432 return;
duke@2 433 }
duke@2 434
duke@2 435 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardControl
duke@2 436 (JNIEnv *env, jclass thisClass, jlong jCard, jint jControlCode, jbyteArray jSendBuffer)
duke@2 437 {
duke@2 438 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 439 LONG rv;
valeriep@23704 440 jbyte* sendBuffer;
duke@2 441 jint sendBufferLength = (*env)->GetArrayLength(env, jSendBuffer);
duke@2 442 jbyte receiveBuffer[MAX_STACK_BUFFER_SIZE];
duke@2 443 jint receiveBufferLength = MAX_STACK_BUFFER_SIZE;
duke@2 444 ULONG returnedLength = 0;
duke@2 445 jbyteArray jReceiveBuffer;
duke@2 446
valeriep@23704 447 sendBuffer = (*env)->GetByteArrayElements(env, jSendBuffer, NULL);
valeriep@23704 448 if (sendBuffer == NULL) {
valeriep@23704 449 return NULL;
valeriep@23704 450 }
valeriep@23704 451
duke@2 452 #ifdef J2PCSC_DEBUG
duke@2 453 {
duke@2 454 int k;
duke@2 455 printf("-control: 0x%X\n", jControlCode);
duke@2 456 printf("-send: ");
duke@2 457 for (k = 0; k < sendBufferLength; k++) {
duke@2 458 printf("%02x ", sendBuffer[k]);
duke@2 459 }
duke@2 460 printf("\n");
duke@2 461 }
duke@2 462 #endif
duke@2 463
duke@2 464 rv = CALL_SCardControl(card, jControlCode, sendBuffer, sendBufferLength,
duke@2 465 receiveBuffer, receiveBufferLength, &returnedLength);
duke@2 466
duke@2 467 (*env)->ReleaseByteArrayElements(env, jSendBuffer, sendBuffer, JNI_ABORT);
duke@2 468 if (handleRV(env, rv)) {
duke@2 469 return NULL;
duke@2 470 }
duke@2 471
duke@2 472 #ifdef J2PCSC_DEBUG
duke@2 473 {
duke@2 474 int k;
duke@2 475 printf("-recv: ");
duke@2 476 for (k = 0; k < returnedLength; k++) {
duke@2 477 printf("%02x ", receiveBuffer[k]);
duke@2 478 }
duke@2 479 printf("\n");
duke@2 480 }
duke@2 481 #endif
duke@2 482
duke@2 483 jReceiveBuffer = (*env)->NewByteArray(env, returnedLength);
valeriep@23704 484 if (jReceiveBuffer == NULL) {
valeriep@23704 485 return NULL;
valeriep@23704 486 }
duke@2 487 (*env)->SetByteArrayRegion(env, jReceiveBuffer, 0, returnedLength, receiveBuffer);
valeriep@23704 488 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 489 return NULL;
valeriep@23704 490 }
duke@2 491 return jReceiveBuffer;
duke@2 492 }