annotate src/java.smartcardio/share/native/libj2pcsc/pcsc.c @ 51794:dccdf51b10dd

8207233: Minor improvements of jdk C-coding Reviewed-by: rriggs, prr
author goetz
date Fri, 13 Jul 2018 17:42:24 +0200
parents 71c04702a3d5
children df3d253aaf81
rev   line source
duke@2 1 /*
goetz@51794 2 * Copyright (c) 2005, 2018, 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
goetz@51794 195 if (size != 0) {
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);
goetz@51794 208 } else {
goetz@51794 209 return NULL;
valeriep@23704 210 }
valeriep@23704 211
igerasim@24630 212 result = pcsc_multi2jstring(env, mszReaders);
duke@2 213 free(mszReaders);
duke@2 214 return result;
duke@2 215 }
duke@2 216
duke@2 217 JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardConnect
duke@2 218 (JNIEnv *env, jclass thisClass, jlong jContext, jstring jReaderName,
duke@2 219 jint jShareMode, jint jPreferredProtocols)
duke@2 220 {
duke@2 221 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 222 LONG rv;
duke@2 223 LPCTSTR readerName;
igerasim@24516 224 SCARDHANDLE card = 0;
igerasim@24516 225 DWORD proto = 0;
duke@2 226
duke@2 227 readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
valeriep@23704 228 if (readerName == NULL) {
valeriep@23704 229 return 0;
valeriep@23704 230 }
duke@2 231 rv = CALL_SCardConnect(context, readerName, jShareMode, jPreferredProtocols, &card, &proto);
duke@2 232 (*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
duke@2 233 dprintf1("-cardhandle: %x\n", card);
duke@2 234 dprintf1("-protocol: %d\n", proto);
duke@2 235 if (handleRV(env, rv)) {
duke@2 236 return 0;
duke@2 237 }
duke@2 238
duke@2 239 return (jlong)card;
duke@2 240 }
duke@2 241
duke@2 242 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardTransmit
duke@2 243 (JNIEnv *env, jclass thisClass, jlong jCard, jint protocol,
duke@2 244 jbyteArray jBuf, jint jOfs, jint jLen)
duke@2 245 {
duke@2 246 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 247 LONG rv;
duke@2 248 SCARD_IO_REQUEST sendPci;
duke@2 249 unsigned char *sbuf;
duke@2 250 unsigned char rbuf[RECEIVE_BUFFER_SIZE];
duke@2 251 DWORD rlen = RECEIVE_BUFFER_SIZE;
duke@2 252 int ofs = (int)jOfs;
duke@2 253 int len = (int)jLen;
duke@2 254 jbyteArray jOut;
duke@2 255
duke@2 256 sendPci.dwProtocol = protocol;
duke@2 257 sendPci.cbPciLength = sizeof(SCARD_IO_REQUEST);
duke@2 258
duke@2 259 sbuf = (unsigned char *) ((*env)->GetByteArrayElements(env, jBuf, NULL));
valeriep@23704 260 if (sbuf == NULL) {
valeriep@23704 261 return NULL;
valeriep@23704 262 }
duke@2 263 rv = CALL_SCardTransmit(card, &sendPci, sbuf + ofs, len, NULL, rbuf, &rlen);
duke@2 264 (*env)->ReleaseByteArrayElements(env, jBuf, (jbyte *)sbuf, JNI_ABORT);
duke@2 265
duke@2 266 if (handleRV(env, rv)) {
duke@2 267 return NULL;
duke@2 268 }
duke@2 269
duke@2 270 jOut = (*env)->NewByteArray(env, rlen);
valeriep@23704 271 if (jOut != NULL) {
valeriep@23704 272 (*env)->SetByteArrayRegion(env, jOut, 0, rlen, (jbyte *)rbuf);
valeriep@23704 273 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 274 return NULL;
valeriep@23704 275 }
valeriep@23704 276 }
duke@2 277 return jOut;
duke@2 278 }
duke@2 279
duke@2 280 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardStatus
duke@2 281 (JNIEnv *env, jclass thisClass, jlong jCard, jbyteArray jStatus)
duke@2 282 {
duke@2 283 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 284 LONG rv;
duke@2 285 char readerName[READERNAME_BUFFER_SIZE];
duke@2 286 DWORD readerLen = READERNAME_BUFFER_SIZE;
duke@2 287 unsigned char atr[ATR_BUFFER_SIZE];
duke@2 288 DWORD atrLen = ATR_BUFFER_SIZE;
igerasim@24516 289 DWORD state = 0;
igerasim@24516 290 DWORD protocol = 0;
duke@2 291 jbyteArray jArray;
valeriep@23704 292 jbyte status[2];
duke@2 293
duke@2 294 rv = CALL_SCardStatus(card, readerName, &readerLen, &state, &protocol, atr, &atrLen);
duke@2 295 if (handleRV(env, rv)) {
duke@2 296 return NULL;
duke@2 297 }
duke@2 298 dprintf1("-reader: %s\n", readerName);
duke@2 299 dprintf1("-status: %d\n", state);
duke@2 300 dprintf1("-protocol: %d\n", protocol);
duke@2 301
duke@2 302 jArray = (*env)->NewByteArray(env, atrLen);
valeriep@23704 303 if (jArray == NULL) {
valeriep@23704 304 return NULL;
valeriep@23704 305 }
duke@2 306 (*env)->SetByteArrayRegion(env, jArray, 0, atrLen, (jbyte *)atr);
valeriep@23704 307 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 308 return NULL;
valeriep@23704 309 }
valeriep@23704 310 status[0] = (jbyte) state;
valeriep@23704 311 status[1] = (jbyte) protocol;
valeriep@23704 312 (*env)->SetByteArrayRegion(env, jStatus, 0, 2, status);
valeriep@23704 313 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 314 return NULL;
valeriep@23704 315 }
duke@2 316 return jArray;
duke@2 317 }
duke@2 318
duke@2 319 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardDisconnect
duke@2 320 (JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
duke@2 321 {
duke@2 322 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 323 LONG rv;
duke@2 324
duke@2 325 rv = CALL_SCardDisconnect(card, jDisposition);
duke@2 326 dprintf1("-disconnect: 0x%X\n", rv);
duke@2 327 handleRV(env, rv);
duke@2 328 return;
duke@2 329 }
duke@2 330
duke@2 331 JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusChange
duke@2 332 (JNIEnv *env, jclass thisClass, jlong jContext, jlong jTimeout,
duke@2 333 jintArray jCurrentState, jobjectArray jReaderNames)
duke@2 334 {
duke@2 335 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 336 LONG rv;
duke@2 337 int readers = (*env)->GetArrayLength(env, jReaderNames);
valeriep@23704 338 SCARD_READERSTATE *readerState;
duke@2 339 int i;
valeriep@23704 340 jintArray jEventState = NULL;
valeriep@23704 341 int *currentState = NULL;
valeriep@23704 342 const char *readerName;
valeriep@23704 343
valeriep@23704 344 readerState = calloc(readers, sizeof(SCARD_READERSTATE));
igerasim@24627 345 if (readerState == NULL && readers > 0) {
valeriep@23704 346 throwOutOfMemoryError(env, NULL);
valeriep@23704 347 return NULL;
valeriep@23704 348 }
valeriep@23704 349
valeriep@23704 350 currentState = (*env)->GetIntArrayElements(env, jCurrentState, NULL);
valeriep@23704 351 if (currentState == NULL) {
valeriep@23704 352 free(readerState);
valeriep@23704 353 return NULL;
valeriep@23704 354 }
duke@2 355
duke@2 356 for (i = 0; i < readers; i++) {
igerasim@24627 357 readerState[i].szReader = NULL;
igerasim@24627 358 }
igerasim@24627 359
igerasim@24627 360 for (i = 0; i < readers; i++) {
duke@2 361 jobject jReaderName = (*env)->GetObjectArrayElement(env, jReaderNames, i);
valeriep@23704 362 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 363 goto cleanup;
valeriep@23704 364 }
valeriep@23704 365 readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
valeriep@23704 366 if (readerName == NULL) {
valeriep@23704 367 goto cleanup;
valeriep@23704 368 }
valeriep@23704 369 readerState[i].szReader = strdup(readerName);
valeriep@23704 370 (*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
valeriep@23704 371 if (readerState[i].szReader == NULL) {
valeriep@23704 372 throwOutOfMemoryError(env, NULL);
valeriep@23704 373 goto cleanup;
valeriep@23704 374 }
duke@2 375 readerState[i].pvUserData = NULL;
duke@2 376 readerState[i].dwCurrentState = currentState[i];
duke@2 377 readerState[i].dwEventState = SCARD_STATE_UNAWARE;
duke@2 378 readerState[i].cbAtr = 0;
valeriep@23704 379 (*env)->DeleteLocalRef(env, jReaderName);
duke@2 380 }
duke@2 381
igerasim@24627 382 if (readers > 0) {
igerasim@24627 383 rv = CALL_SCardGetStatusChange(context, (DWORD)jTimeout, readerState, readers);
igerasim@24627 384 if (handleRV(env, rv)) {
igerasim@24627 385 goto cleanup;
igerasim@24627 386 }
valeriep@23704 387 }
duke@2 388
duke@2 389 jEventState = (*env)->NewIntArray(env, readers);
valeriep@23704 390 if (jEventState == NULL) {
valeriep@23704 391 goto cleanup;
valeriep@23704 392 }
duke@2 393 for (i = 0; i < readers; i++) {
duke@2 394 jint eventStateTmp;
duke@2 395 dprintf3("-reader status %s: 0x%X, 0x%X\n", readerState[i].szReader,
duke@2 396 readerState[i].dwCurrentState, readerState[i].dwEventState);
duke@2 397 eventStateTmp = (jint)readerState[i].dwEventState;
duke@2 398 (*env)->SetIntArrayRegion(env, jEventState, i, 1, &eventStateTmp);
valeriep@23704 399 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 400 jEventState = NULL;
valeriep@23704 401 goto cleanup;
valeriep@23704 402 }
valeriep@23704 403 }
valeriep@23704 404 cleanup:
valeriep@23704 405 (*env)->ReleaseIntArrayElements(env, jCurrentState, currentState, JNI_ABORT);
valeriep@23704 406 for (i = 0; i < readers; i++) {
valeriep@23704 407 free((char *)readerState[i].szReader);
duke@2 408 }
duke@2 409 free(readerState);
duke@2 410 return jEventState;
duke@2 411 }
duke@2 412
duke@2 413 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardBeginTransaction
duke@2 414 (JNIEnv *env, jclass thisClass, jlong jCard)
duke@2 415 {
duke@2 416 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 417 LONG rv;
duke@2 418
duke@2 419 rv = CALL_SCardBeginTransaction(card);
duke@2 420 dprintf1("-beginTransaction: 0x%X\n", rv);
duke@2 421 handleRV(env, rv);
duke@2 422 return;
duke@2 423 }
duke@2 424
duke@2 425 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardEndTransaction
duke@2 426 (JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
duke@2 427 {
duke@2 428 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 429 LONG rv;
duke@2 430
duke@2 431 rv = CALL_SCardEndTransaction(card, jDisposition);
duke@2 432 dprintf1("-endTransaction: 0x%X\n", rv);
duke@2 433 handleRV(env, rv);
duke@2 434 return;
duke@2 435 }
duke@2 436
duke@2 437 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardControl
duke@2 438 (JNIEnv *env, jclass thisClass, jlong jCard, jint jControlCode, jbyteArray jSendBuffer)
duke@2 439 {
duke@2 440 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 441 LONG rv;
valeriep@23704 442 jbyte* sendBuffer;
duke@2 443 jint sendBufferLength = (*env)->GetArrayLength(env, jSendBuffer);
duke@2 444 jbyte receiveBuffer[MAX_STACK_BUFFER_SIZE];
duke@2 445 jint receiveBufferLength = MAX_STACK_BUFFER_SIZE;
duke@2 446 ULONG returnedLength = 0;
duke@2 447 jbyteArray jReceiveBuffer;
duke@2 448
valeriep@23704 449 sendBuffer = (*env)->GetByteArrayElements(env, jSendBuffer, NULL);
valeriep@23704 450 if (sendBuffer == NULL) {
valeriep@23704 451 return NULL;
valeriep@23704 452 }
valeriep@23704 453
duke@2 454 #ifdef J2PCSC_DEBUG
duke@2 455 {
duke@2 456 int k;
duke@2 457 printf("-control: 0x%X\n", jControlCode);
duke@2 458 printf("-send: ");
duke@2 459 for (k = 0; k < sendBufferLength; k++) {
duke@2 460 printf("%02x ", sendBuffer[k]);
duke@2 461 }
duke@2 462 printf("\n");
duke@2 463 }
duke@2 464 #endif
duke@2 465
duke@2 466 rv = CALL_SCardControl(card, jControlCode, sendBuffer, sendBufferLength,
duke@2 467 receiveBuffer, receiveBufferLength, &returnedLength);
duke@2 468
duke@2 469 (*env)->ReleaseByteArrayElements(env, jSendBuffer, sendBuffer, JNI_ABORT);
duke@2 470 if (handleRV(env, rv)) {
duke@2 471 return NULL;
duke@2 472 }
duke@2 473
duke@2 474 #ifdef J2PCSC_DEBUG
duke@2 475 {
duke@2 476 int k;
duke@2 477 printf("-recv: ");
duke@2 478 for (k = 0; k < returnedLength; k++) {
duke@2 479 printf("%02x ", receiveBuffer[k]);
duke@2 480 }
duke@2 481 printf("\n");
duke@2 482 }
duke@2 483 #endif
duke@2 484
duke@2 485 jReceiveBuffer = (*env)->NewByteArray(env, returnedLength);
valeriep@23704 486 if (jReceiveBuffer == NULL) {
valeriep@23704 487 return NULL;
valeriep@23704 488 }
duke@2 489 (*env)->SetByteArrayRegion(env, jReceiveBuffer, 0, returnedLength, receiveBuffer);
valeriep@23704 490 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 491 return NULL;
valeriep@23704 492 }
duke@2 493 return jReceiveBuffer;
duke@2 494 }