annotate jdk/src/share/native/sun/security/smartcardio/pcsc.c @ 23709:9f7652fb03b2

8039118: Windows build failure (j2pcsc.dll : fatal error unresolved external symbol throwByName) Reviewed-by: mullan, mchung, alanb
author chegar
date Wed, 02 Apr 2014 23:23:00 +0100
parents c174349fcd4b
children 9e5ba0f3ce68
rev   line source
duke@2 1 /*
valeriep@23704 2 * Copyright (c) 2005, 2014, 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
duke@2 58 #define MAX_STACK_BUFFER_SIZE 8192
duke@2 59
duke@2 60 // make the buffers larger than what should be necessary, just in case
duke@2 61 #define ATR_BUFFER_SIZE 128
duke@2 62 #define READERNAME_BUFFER_SIZE 128
duke@2 63 #define RECEIVE_BUFFER_SIZE MAX_STACK_BUFFER_SIZE
duke@2 64
duke@2 65 #define J2PCSC_EXCEPTION_NAME "sun/security/smartcardio/PCSCException"
duke@2 66
chegar@23709 67 void throwOutOfMemoryError(JNIEnv *env, const char *msg) {
chegar@23709 68 jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
valeriep@23704 69
chegar@23709 70 if (cls != NULL) /* Otherwise an exception has already been thrown */
chegar@23709 71 (*env)->ThrowNew(env, cls, msg);
chegar@23709 72
valeriep@23704 73 }
valeriep@23704 74
duke@2 75 void throwPCSCException(JNIEnv* env, LONG code) {
duke@2 76 jclass pcscClass;
duke@2 77 jmethodID constructor;
duke@2 78 jthrowable pcscException;
duke@2 79
duke@2 80 pcscClass = (*env)->FindClass(env, J2PCSC_EXCEPTION_NAME);
valeriep@23704 81 if (pcscClass == NULL) {
valeriep@23704 82 return;
valeriep@23704 83 }
duke@2 84 constructor = (*env)->GetMethodID(env, pcscClass, "<init>", "(I)V");
valeriep@23704 85 if (constructor == NULL) {
valeriep@23704 86 return;
valeriep@23704 87 }
valeriep@23704 88 pcscException = (jthrowable) (*env)->NewObject(env, pcscClass,
valeriep@23704 89 constructor, (jint)code);
valeriep@23704 90 if (pcscException != NULL) {
valeriep@23704 91 (*env)->Throw(env, pcscException);
valeriep@23704 92 }
duke@2 93 }
duke@2 94
duke@2 95 jboolean handleRV(JNIEnv* env, LONG code) {
duke@2 96 if (code == SCARD_S_SUCCESS) {
duke@2 97 return JNI_FALSE;
duke@2 98 } else {
duke@2 99 throwPCSCException(env, code);
duke@2 100 return JNI_TRUE;
duke@2 101 }
duke@2 102 }
duke@2 103
duke@2 104 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
duke@2 105 return JNI_VERSION_1_4;
duke@2 106 }
duke@2 107
duke@2 108 JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardEstablishContext
duke@2 109 (JNIEnv *env, jclass thisClass, jint dwScope)
duke@2 110 {
duke@2 111 SCARDCONTEXT context;
duke@2 112 LONG rv;
duke@2 113 dprintf("-establishContext\n");
duke@2 114 rv = CALL_SCardEstablishContext(dwScope, NULL, NULL, &context);
duke@2 115 if (handleRV(env, rv)) {
duke@2 116 return 0;
duke@2 117 }
duke@2 118 // note: SCARDCONTEXT is typedef'd as long, so this works
duke@2 119 return (jlong)context;
duke@2 120 }
duke@2 121
duke@2 122 /**
duke@2 123 * Convert a multi string to a java string array,
duke@2 124 */
duke@2 125 jobjectArray pcsc_multi2jstring(JNIEnv *env, char *spec) {
duke@2 126 jobjectArray result;
duke@2 127 jclass stringClass;
duke@2 128 char *cp, **tab;
duke@2 129 jstring js;
duke@2 130 int cnt = 0;
duke@2 131
duke@2 132 cp = spec;
duke@2 133 while (*cp != 0) {
duke@2 134 cp += (strlen(cp) + 1);
duke@2 135 ++cnt;
duke@2 136 }
duke@2 137
duke@2 138 tab = (char **)malloc(cnt * sizeof(char *));
valeriep@23704 139 if (tab == NULL) {
valeriep@23704 140 throwOutOfMemoryError(env, NULL);
valeriep@23704 141 return NULL;
valeriep@23704 142 }
duke@2 143
duke@2 144 cnt = 0;
duke@2 145 cp = spec;
duke@2 146 while (*cp != 0) {
duke@2 147 tab[cnt++] = cp;
duke@2 148 cp += (strlen(cp) + 1);
duke@2 149 }
duke@2 150
duke@2 151 stringClass = (*env)->FindClass(env, "java/lang/String");
valeriep@23704 152 if (stringClass == NULL) {
valeriep@23704 153 free(tab);
valeriep@23704 154 return NULL;
valeriep@23704 155 }
duke@2 156
duke@2 157 result = (*env)->NewObjectArray(env, cnt, stringClass, NULL);
valeriep@23704 158 if (result != NULL) {
valeriep@23704 159 while (cnt-- > 0) {
valeriep@23704 160 js = (*env)->NewStringUTF(env, tab[cnt]);
valeriep@23704 161 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 162 free(tab);
valeriep@23704 163 return NULL;
valeriep@23704 164 }
valeriep@23704 165 (*env)->SetObjectArrayElement(env, result, cnt, js);
valeriep@23704 166 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 167 free(tab);
valeriep@23704 168 return NULL;
valeriep@23704 169 }
valeriep@23704 170 (*env)->DeleteLocalRef(env, js);
valeriep@23704 171 }
duke@2 172 }
duke@2 173 free(tab);
duke@2 174 return result;
duke@2 175 }
duke@2 176
duke@2 177 JNIEXPORT jobjectArray JNICALL Java_sun_security_smartcardio_PCSC_SCardListReaders
duke@2 178 (JNIEnv *env, jclass thisClass, jlong jContext)
duke@2 179 {
duke@2 180 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 181 LONG rv;
duke@2 182 LPTSTR mszReaders;
duke@2 183 DWORD size;
duke@2 184 jobjectArray result;
duke@2 185
duke@2 186 dprintf1("-context: %x\n", context);
duke@2 187 rv = CALL_SCardListReaders(context, NULL, NULL, &size);
duke@2 188 if (handleRV(env, rv)) {
duke@2 189 return NULL;
duke@2 190 }
duke@2 191 dprintf1("-size: %d\n", size);
duke@2 192
duke@2 193 mszReaders = malloc(size);
valeriep@23704 194 if (mszReaders == NULL) {
valeriep@23704 195 throwOutOfMemoryError(env, NULL);
valeriep@23704 196 return NULL;
valeriep@23704 197 }
valeriep@23704 198
duke@2 199 rv = CALL_SCardListReaders(context, NULL, mszReaders, &size);
duke@2 200 if (handleRV(env, rv)) {
duke@2 201 free(mszReaders);
duke@2 202 return NULL;
duke@2 203 }
duke@2 204 dprintf1("-String: %s\n", mszReaders);
duke@2 205
duke@2 206 result = pcsc_multi2jstring(env, mszReaders);
duke@2 207 free(mszReaders);
duke@2 208 return result;
duke@2 209 }
duke@2 210
duke@2 211 JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardConnect
duke@2 212 (JNIEnv *env, jclass thisClass, jlong jContext, jstring jReaderName,
duke@2 213 jint jShareMode, jint jPreferredProtocols)
duke@2 214 {
duke@2 215 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 216 LONG rv;
duke@2 217 LPCTSTR readerName;
duke@2 218 SCARDHANDLE card;
duke@2 219 DWORD proto;
duke@2 220
duke@2 221 readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
valeriep@23704 222 if (readerName == NULL) {
valeriep@23704 223 return 0;
valeriep@23704 224 }
duke@2 225 rv = CALL_SCardConnect(context, readerName, jShareMode, jPreferredProtocols, &card, &proto);
duke@2 226 (*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
duke@2 227 dprintf1("-cardhandle: %x\n", card);
duke@2 228 dprintf1("-protocol: %d\n", proto);
duke@2 229 if (handleRV(env, rv)) {
duke@2 230 return 0;
duke@2 231 }
duke@2 232
duke@2 233 return (jlong)card;
duke@2 234 }
duke@2 235
duke@2 236 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardTransmit
duke@2 237 (JNIEnv *env, jclass thisClass, jlong jCard, jint protocol,
duke@2 238 jbyteArray jBuf, jint jOfs, jint jLen)
duke@2 239 {
duke@2 240 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 241 LONG rv;
duke@2 242 SCARD_IO_REQUEST sendPci;
duke@2 243 unsigned char *sbuf;
duke@2 244 unsigned char rbuf[RECEIVE_BUFFER_SIZE];
duke@2 245 DWORD rlen = RECEIVE_BUFFER_SIZE;
duke@2 246 int ofs = (int)jOfs;
duke@2 247 int len = (int)jLen;
duke@2 248 jbyteArray jOut;
duke@2 249
duke@2 250 sendPci.dwProtocol = protocol;
duke@2 251 sendPci.cbPciLength = sizeof(SCARD_IO_REQUEST);
duke@2 252
duke@2 253 sbuf = (unsigned char *) ((*env)->GetByteArrayElements(env, jBuf, NULL));
valeriep@23704 254 if (sbuf == NULL) {
valeriep@23704 255 return NULL;
valeriep@23704 256 }
duke@2 257 rv = CALL_SCardTransmit(card, &sendPci, sbuf + ofs, len, NULL, rbuf, &rlen);
duke@2 258 (*env)->ReleaseByteArrayElements(env, jBuf, (jbyte *)sbuf, JNI_ABORT);
duke@2 259
duke@2 260 if (handleRV(env, rv)) {
duke@2 261 return NULL;
duke@2 262 }
duke@2 263
duke@2 264 jOut = (*env)->NewByteArray(env, rlen);
valeriep@23704 265 if (jOut != NULL) {
valeriep@23704 266 (*env)->SetByteArrayRegion(env, jOut, 0, rlen, (jbyte *)rbuf);
valeriep@23704 267 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 268 return NULL;
valeriep@23704 269 }
valeriep@23704 270 }
duke@2 271 return jOut;
duke@2 272 }
duke@2 273
duke@2 274 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardStatus
duke@2 275 (JNIEnv *env, jclass thisClass, jlong jCard, jbyteArray jStatus)
duke@2 276 {
duke@2 277 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 278 LONG rv;
duke@2 279 char readerName[READERNAME_BUFFER_SIZE];
duke@2 280 DWORD readerLen = READERNAME_BUFFER_SIZE;
duke@2 281 unsigned char atr[ATR_BUFFER_SIZE];
duke@2 282 DWORD atrLen = ATR_BUFFER_SIZE;
duke@2 283 DWORD state;
duke@2 284 DWORD protocol;
duke@2 285 jbyteArray jArray;
valeriep@23704 286 jbyte status[2];
duke@2 287
duke@2 288 rv = CALL_SCardStatus(card, readerName, &readerLen, &state, &protocol, atr, &atrLen);
duke@2 289 if (handleRV(env, rv)) {
duke@2 290 return NULL;
duke@2 291 }
duke@2 292 dprintf1("-reader: %s\n", readerName);
duke@2 293 dprintf1("-status: %d\n", state);
duke@2 294 dprintf1("-protocol: %d\n", protocol);
duke@2 295
duke@2 296 jArray = (*env)->NewByteArray(env, atrLen);
valeriep@23704 297 if (jArray == NULL) {
valeriep@23704 298 return NULL;
valeriep@23704 299 }
duke@2 300 (*env)->SetByteArrayRegion(env, jArray, 0, atrLen, (jbyte *)atr);
valeriep@23704 301 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 302 return NULL;
valeriep@23704 303 }
valeriep@23704 304 status[0] = (jbyte) state;
valeriep@23704 305 status[1] = (jbyte) protocol;
valeriep@23704 306 (*env)->SetByteArrayRegion(env, jStatus, 0, 2, status);
valeriep@23704 307 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 308 return NULL;
valeriep@23704 309 }
duke@2 310 return jArray;
duke@2 311 }
duke@2 312
duke@2 313 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardDisconnect
duke@2 314 (JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
duke@2 315 {
duke@2 316 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 317 LONG rv;
duke@2 318
duke@2 319 rv = CALL_SCardDisconnect(card, jDisposition);
duke@2 320 dprintf1("-disconnect: 0x%X\n", rv);
duke@2 321 handleRV(env, rv);
duke@2 322 return;
duke@2 323 }
duke@2 324
duke@2 325 JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusChange
duke@2 326 (JNIEnv *env, jclass thisClass, jlong jContext, jlong jTimeout,
duke@2 327 jintArray jCurrentState, jobjectArray jReaderNames)
duke@2 328 {
duke@2 329 SCARDCONTEXT context = (SCARDCONTEXT)jContext;
duke@2 330 LONG rv;
duke@2 331 int readers = (*env)->GetArrayLength(env, jReaderNames);
valeriep@23704 332 SCARD_READERSTATE *readerState;
duke@2 333 int i;
valeriep@23704 334 jintArray jEventState = NULL;
valeriep@23704 335 int *currentState = NULL;
valeriep@23704 336 const char *readerName;
valeriep@23704 337
valeriep@23704 338 readerState = calloc(readers, sizeof(SCARD_READERSTATE));
valeriep@23704 339 if (readerState == NULL) {
valeriep@23704 340 throwOutOfMemoryError(env, NULL);
valeriep@23704 341 return NULL;
valeriep@23704 342 }
valeriep@23704 343
valeriep@23704 344 currentState = (*env)->GetIntArrayElements(env, jCurrentState, NULL);
valeriep@23704 345 if (currentState == NULL) {
valeriep@23704 346 free(readerState);
valeriep@23704 347 return NULL;
valeriep@23704 348 }
duke@2 349
duke@2 350 for (i = 0; i < readers; i++) {
duke@2 351 jobject jReaderName = (*env)->GetObjectArrayElement(env, jReaderNames, i);
valeriep@23704 352 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 353 goto cleanup;
valeriep@23704 354 }
valeriep@23704 355 readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);
valeriep@23704 356 if (readerName == NULL) {
valeriep@23704 357 goto cleanup;
valeriep@23704 358 }
valeriep@23704 359 readerState[i].szReader = strdup(readerName);
valeriep@23704 360 (*env)->ReleaseStringUTFChars(env, jReaderName, readerName);
valeriep@23704 361 if (readerState[i].szReader == NULL) {
valeriep@23704 362 throwOutOfMemoryError(env, NULL);
valeriep@23704 363 goto cleanup;
valeriep@23704 364 }
duke@2 365 readerState[i].pvUserData = NULL;
duke@2 366 readerState[i].dwCurrentState = currentState[i];
duke@2 367 readerState[i].dwEventState = SCARD_STATE_UNAWARE;
duke@2 368 readerState[i].cbAtr = 0;
valeriep@23704 369 (*env)->DeleteLocalRef(env, jReaderName);
duke@2 370 }
duke@2 371
duke@2 372 rv = CALL_SCardGetStatusChange(context, (DWORD)jTimeout, readerState, readers);
valeriep@23704 373 if (handleRV(env, rv)) {
valeriep@23704 374 goto cleanup;
valeriep@23704 375 }
duke@2 376
duke@2 377 jEventState = (*env)->NewIntArray(env, readers);
valeriep@23704 378 if (jEventState == NULL) {
valeriep@23704 379 goto cleanup;
valeriep@23704 380 }
duke@2 381 for (i = 0; i < readers; i++) {
duke@2 382 jint eventStateTmp;
duke@2 383 dprintf3("-reader status %s: 0x%X, 0x%X\n", readerState[i].szReader,
duke@2 384 readerState[i].dwCurrentState, readerState[i].dwEventState);
duke@2 385 eventStateTmp = (jint)readerState[i].dwEventState;
duke@2 386 (*env)->SetIntArrayRegion(env, jEventState, i, 1, &eventStateTmp);
valeriep@23704 387 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 388 jEventState = NULL;
valeriep@23704 389 goto cleanup;
valeriep@23704 390 }
valeriep@23704 391 }
valeriep@23704 392 cleanup:
valeriep@23704 393 (*env)->ReleaseIntArrayElements(env, jCurrentState, currentState, JNI_ABORT);
valeriep@23704 394 for (i = 0; i < readers; i++) {
valeriep@23704 395 free((char *)readerState[i].szReader);
duke@2 396 }
duke@2 397 free(readerState);
duke@2 398 return jEventState;
duke@2 399 }
duke@2 400
duke@2 401 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardBeginTransaction
duke@2 402 (JNIEnv *env, jclass thisClass, jlong jCard)
duke@2 403 {
duke@2 404 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 405 LONG rv;
duke@2 406
duke@2 407 rv = CALL_SCardBeginTransaction(card);
duke@2 408 dprintf1("-beginTransaction: 0x%X\n", rv);
duke@2 409 handleRV(env, rv);
duke@2 410 return;
duke@2 411 }
duke@2 412
duke@2 413 JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardEndTransaction
duke@2 414 (JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)
duke@2 415 {
duke@2 416 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 417 LONG rv;
duke@2 418
duke@2 419 rv = CALL_SCardEndTransaction(card, jDisposition);
duke@2 420 dprintf1("-endTransaction: 0x%X\n", rv);
duke@2 421 handleRV(env, rv);
duke@2 422 return;
duke@2 423 }
duke@2 424
duke@2 425 JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardControl
duke@2 426 (JNIEnv *env, jclass thisClass, jlong jCard, jint jControlCode, jbyteArray jSendBuffer)
duke@2 427 {
duke@2 428 SCARDHANDLE card = (SCARDHANDLE)jCard;
duke@2 429 LONG rv;
valeriep@23704 430 jbyte* sendBuffer;
duke@2 431 jint sendBufferLength = (*env)->GetArrayLength(env, jSendBuffer);
duke@2 432 jbyte receiveBuffer[MAX_STACK_BUFFER_SIZE];
duke@2 433 jint receiveBufferLength = MAX_STACK_BUFFER_SIZE;
duke@2 434 ULONG returnedLength = 0;
duke@2 435 jbyteArray jReceiveBuffer;
duke@2 436
valeriep@23704 437 sendBuffer = (*env)->GetByteArrayElements(env, jSendBuffer, NULL);
valeriep@23704 438 if (sendBuffer == NULL) {
valeriep@23704 439 return NULL;
valeriep@23704 440 }
valeriep@23704 441
duke@2 442 #ifdef J2PCSC_DEBUG
duke@2 443 {
duke@2 444 int k;
duke@2 445 printf("-control: 0x%X\n", jControlCode);
duke@2 446 printf("-send: ");
duke@2 447 for (k = 0; k < sendBufferLength; k++) {
duke@2 448 printf("%02x ", sendBuffer[k]);
duke@2 449 }
duke@2 450 printf("\n");
duke@2 451 }
duke@2 452 #endif
duke@2 453
duke@2 454 rv = CALL_SCardControl(card, jControlCode, sendBuffer, sendBufferLength,
duke@2 455 receiveBuffer, receiveBufferLength, &returnedLength);
duke@2 456
duke@2 457 (*env)->ReleaseByteArrayElements(env, jSendBuffer, sendBuffer, JNI_ABORT);
duke@2 458 if (handleRV(env, rv)) {
duke@2 459 return NULL;
duke@2 460 }
duke@2 461
duke@2 462 #ifdef J2PCSC_DEBUG
duke@2 463 {
duke@2 464 int k;
duke@2 465 printf("-recv: ");
duke@2 466 for (k = 0; k < returnedLength; k++) {
duke@2 467 printf("%02x ", receiveBuffer[k]);
duke@2 468 }
duke@2 469 printf("\n");
duke@2 470 }
duke@2 471 #endif
duke@2 472
duke@2 473 jReceiveBuffer = (*env)->NewByteArray(env, returnedLength);
valeriep@23704 474 if (jReceiveBuffer == NULL) {
valeriep@23704 475 return NULL;
valeriep@23704 476 }
duke@2 477 (*env)->SetByteArrayRegion(env, jReceiveBuffer, 0, returnedLength, receiveBuffer);
valeriep@23704 478 if ((*env)->ExceptionCheck(env)) {
valeriep@23704 479 return NULL;
valeriep@23704 480 }
duke@2 481 return jReceiveBuffer;
duke@2 482 }