1 /* 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. 3 */ 4 5 /* Copyright (c) 2002 Graz University of Technology. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * 3. The end-user documentation included with the redistribution, if any, must 18 * include the following acknowledgment: 19 * 20 * "This product includes software developed by IAIK of Graz University of 21 * Technology." 22 * 23 * Alternately, this acknowledgment may appear in the software itself, if 24 * and wherever such third-party acknowledgments normally appear. 25 * 26 * 4. The names "Graz University of Technology" and "IAIK of Graz University of 27 * Technology" must not be used to endorse or promote products derived from 28 * this software without prior written permission. 29 * 30 * 5. Products derived from this software may not be called 31 * "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior 32 * written permission of Graz University of Technology. 33 * 34 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 35 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 36 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 37 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE 38 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 39 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 40 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 41 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 42 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 43 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 45 * POSSIBILITY OF SUCH DAMAGE. 46 */ 47 48 #include "pkcs11wrapper.h" 49 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <assert.h> 54 55 #include "sun_security_pkcs11_wrapper_PKCS11.h" 56 57 /* The initArgs that enable the application to do custom mutex-handling */ 58 #ifndef NO_CALLBACKS 59 jobject jInitArgsObject; 60 CK_C_INITIALIZE_ARGS_PTR ckpGlobalInitArgs; 61 #endif /* NO_CALLBACKS */ 62 63 /* ************************************************************************** */ 64 /* Now come the functions for mutex handling and notification callbacks */ 65 /* ************************************************************************** */ 66 67 /* 68 * converts the InitArgs object to a CK_C_INITIALIZE_ARGS structure and sets the functions 69 * that will call the right Java mutex functions 70 * 71 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields 72 * @param pInitArgs - the InitArgs object with the Java mutex functions to call 73 * @return - the pointer to the CK_C_INITIALIZE_ARGS structure with the functions that will call 74 * the corresponding Java functions 75 */ 76 CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs) 77 { 78 CK_C_INITIALIZE_ARGS_PTR ckpInitArgs; 79 jclass jInitArgsClass; 80 jfieldID fieldID; 81 jlong jFlags; 82 jobject jReserved; 83 CK_ULONG ckReservedLength; 84 #ifndef NO_CALLBACKS 85 jobject jMutexHandler; 86 #endif /* NO_CALLBACKS */ 87 88 if(jInitArgs == NULL) { 89 return NULL_PTR; 90 } 91 92 /* convert the Java InitArgs object to a pointer to a CK_C_INITIALIZE_ARGS structure */ 93 ckpInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS)); 94 if (ckpInitArgs == NULL) { 95 throwOutOfMemoryError(env, 0); 96 return NULL_PTR; 97 } 98 99 /* Set the mutex functions that will call the Java mutex functions, but 100 * only set it, if the field is not null. 101 */ 102 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); 103 if (jInitArgsClass == NULL) { 104 free(ckpInitArgs); 105 return NULL; 106 } 107 108 #ifdef NO_CALLBACKS 109 ckpInitArgs->CreateMutex = NULL_PTR; 110 ckpInitArgs->DestroyMutex = NULL_PTR; 111 ckpInitArgs->LockMutex = NULL_PTR; 112 ckpInitArgs->UnlockMutex = NULL_PTR; 113 #else 114 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;"); 115 if (fieldID == NULL) { 116 free(ckpInitArgs); 117 return NULL; 118 } 119 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); 120 ckpInitArgs->CreateMutex = (jMutexHandler != NULL) ? &callJCreateMutex : NULL_PTR; 121 122 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;"); 123 if (fieldID == NULL) { 124 free(ckpInitArgs); 125 return NULL; 126 } 127 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); 128 ckpInitArgs->DestroyMutex = (jMutexHandler != NULL) ? &callJDestroyMutex : NULL_PTR; 129 130 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;"); 131 if (fieldID == NULL) { 132 free(ckpInitArgs); 133 return NULL; 134 } 135 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); 136 ckpInitArgs->LockMutex = (jMutexHandler != NULL) ? &callJLockMutex : NULL_PTR; 137 138 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;"); 139 if (fieldID == NULL) { 140 free(ckpInitArgs); 141 return NULL; 142 } 143 jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); 144 ckpInitArgs->UnlockMutex = (jMutexHandler != NULL) ? &callJUnlockMutex : NULL_PTR; 145 146 if ((ckpInitArgs->CreateMutex != NULL_PTR) 147 || (ckpInitArgs->DestroyMutex != NULL_PTR) 148 || (ckpInitArgs->LockMutex != NULL_PTR) 149 || (ckpInitArgs->UnlockMutex != NULL_PTR)) { 150 /* we only need to keep a global copy, if we need callbacks */ 151 /* set the global object jInitArgs so that the right Java mutex functions will be called */ 152 jInitArgsObject = (*env)->NewGlobalRef(env, jInitArgs); 153 ckpGlobalInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS)); 154 if (ckpGlobalInitArgs == NULL) { 155 free(ckpInitArgs); 156 throwOutOfMemoryError(env, 0); 157 return NULL_PTR; 158 } 159 160 memcpy(ckpGlobalInitArgs, ckpInitArgs, sizeof(CK_C_INITIALIZE_ARGS)); 161 } 162 #endif /* NO_CALLBACKS */ 163 164 /* convert and set the flags field */ 165 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "flags", "J"); 166 if (fieldID == NULL) { 167 free(ckpInitArgs); 168 return NULL; 169 } 170 jFlags = (*env)->GetLongField(env, jInitArgs, fieldID); 171 ckpInitArgs->flags = jLongToCKULong(jFlags); 172 173 /* pReserved should be NULL_PTR in this version */ 174 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "pReserved", "Ljava/lang/Object;"); 175 if (fieldID == NULL) { 176 free(ckpInitArgs); 177 return NULL; 178 } 179 jReserved = (*env)->GetObjectField(env, jInitArgs, fieldID); 180 181 /* we try to convert the reserved parameter also */ 182 jObjectToPrimitiveCKObjectPtrPtr(env, jReserved, &(ckpInitArgs->pReserved), &ckReservedLength); 183 184 return ckpInitArgs ; 185 } 186 187 #ifndef NO_CALLBACKS 188 189 /* 190 * is the function that gets called by PKCS#11 to create a mutex and calls the Java 191 * CreateMutex function 192 * 193 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields 194 * @param ppMutex - the new created mutex 195 * @return - should return CKR_OK if the mutex creation was ok 196 */ 197 CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex) 198 { 199 extern JavaVM *jvm; 200 JNIEnv *env; 201 jint returnValue; 202 jthrowable pkcs11Exception; 203 jclass pkcs11ExceptionClass; 204 jlong errorCode; 205 CK_RV rv = CKR_OK; 206 int wasAttached = 1; 207 jclass jCreateMutexClass; 208 jclass jInitArgsClass; 209 jmethodID methodID; 210 jfieldID fieldID; 211 jobject jCreateMutex; 212 jobject jMutex; 213 214 215 /* Get the currently running Java VM */ 216 if (jvm == NULL) { return rv ;} /* there is no VM running */ 217 218 /* Determine, if current thread is already attached */ 219 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); 220 if (returnValue == JNI_EDETACHED) { 221 /* thread detached, so attach it */ 222 wasAttached = 0; 223 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 224 } else if (returnValue == JNI_EVERSION) { 225 /* this version of JNI is not supported, so just try to attach */ 226 /* we assume it was attached to ensure that this thread is not detached 227 * afterwards even though it should not 228 */ 229 wasAttached = 1; 230 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 231 } else { 232 /* attached */ 233 wasAttached = 1; 234 } 235 236 jCreateMutexClass = (*env)->FindClass(env, CLASS_CREATEMUTEX); 237 if (jCreateMutexClass == NULL) { return rv; } 238 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); 239 if (jInitArgsClass == NULL) { return rv; } 240 241 /* get the CreateMutex object out of the jInitArgs object */ 242 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;"); 243 if (fieldID == NULL) { return rv; } 244 jCreateMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); 245 assert(jCreateMutex != 0); 246 247 /* call the CK_CREATEMUTEX function of the CreateMutex object */ 248 /* and get the new Java mutex object */ 249 methodID = (*env)->GetMethodID(env, jCreateMutexClass, "CK_CREATEMUTEX", "()Ljava/lang/Object;"); 250 if (methodID == NULL) { return rv; } 251 jMutex = (*env)->CallObjectMethod(env, jCreateMutex, methodID); 252 253 /* set a global reference on the Java mutex */ 254 jMutex = (*env)->NewGlobalRef(env, jMutex); 255 /* convert the Java mutex to a CK mutex */ 256 *ppMutex = jObjectToCKVoidPtr(jMutex); 257 258 259 /* check, if callback threw an exception */ 260 pkcs11Exception = (*env)->ExceptionOccurred(env); 261 262 if (pkcs11Exception != NULL) { 263 /* TBD: clear the pending exception with ExceptionClear? */ 264 /* The was an exception thrown, now we get the error-code from it */ 265 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); 266 if (pkcs11ExceptionClass == NULL) { return rv; } 267 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J"); 268 if (methodID == NULL) { return rv; } 269 270 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); 271 rv = jLongToCKULong(errorCode); 272 } 273 274 /* if we attached this thread to the VM just for callback, we detach it now */ 275 if (wasAttached) { 276 returnValue = (*jvm)->DetachCurrentThread(jvm); 277 } 278 279 return rv ; 280 } 281 282 /* 283 * is the function that gets called by PKCS#11 to destroy a mutex and calls the Java 284 * DestroyMutex function 285 * 286 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields 287 * @param pMutex - the mutex to destroy 288 * @return - should return CKR_OK if the mutex was destroyed 289 */ 290 CK_RV callJDestroyMutex(CK_VOID_PTR pMutex) 291 { 292 extern JavaVM *jvm; 293 JNIEnv *env; 294 jint returnValue; 295 jthrowable pkcs11Exception; 296 jclass pkcs11ExceptionClass; 297 jlong errorCode; 298 CK_RV rv = CKR_OK; 299 int wasAttached = 1; 300 jclass jDestroyMutexClass; 301 jclass jInitArgsClass; 302 jmethodID methodID; 303 jfieldID fieldID; 304 jobject jDestroyMutex; 305 jobject jMutex; 306 307 308 /* Get the currently running Java VM */ 309 if (jvm == NULL) { return rv ; } /* there is no VM running */ 310 311 /* Determine, if current thread is already attached */ 312 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); 313 if (returnValue == JNI_EDETACHED) { 314 /* thread detached, so attach it */ 315 wasAttached = 0; 316 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 317 } else if (returnValue == JNI_EVERSION) { 318 /* this version of JNI is not supported, so just try to attach */ 319 /* we assume it was attached to ensure that this thread is not detached 320 * afterwards even though it should not 321 */ 322 wasAttached = 1; 323 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 324 } else { 325 /* attached */ 326 wasAttached = 1; 327 } 328 329 jDestroyMutexClass = (*env)->FindClass(env, CLASS_DESTROYMUTEX); 330 if (jDestroyMutexClass == NULL) { return rv; } 331 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); 332 if (jInitArgsClass == NULL) { return rv; } 333 334 /* convert the CK mutex to a Java mutex */ 335 jMutex = ckVoidPtrToJObject(pMutex); 336 337 /* get the DestroyMutex object out of the jInitArgs object */ 338 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;"); 339 if (fieldID == NULL) { return rv; } 340 jDestroyMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); 341 assert(jDestroyMutex != 0); 342 343 /* call the CK_DESTROYMUTEX method of the DestroyMutex object */ 344 methodID = (*env)->GetMethodID(env, jDestroyMutexClass, "CK_DESTROYMUTEX", "(Ljava/lang/Object;)V"); 345 if (methodID == NULL) { return rv; } 346 (*env)->CallVoidMethod(env, jDestroyMutex, methodID, jMutex); 347 348 /* delete the global reference on the Java mutex */ 349 (*env)->DeleteGlobalRef(env, jMutex); 350 351 352 /* check, if callback threw an exception */ 353 pkcs11Exception = (*env)->ExceptionOccurred(env); 354 355 if (pkcs11Exception != NULL) { 356 /* TBD: clear the pending exception with ExceptionClear? */ 357 /* The was an exception thrown, now we get the error-code from it */ 358 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); 359 if (pkcs11ExceptionClass == NULL) { return rv; } 360 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J"); 361 if (methodID == NULL) { return rv; } 362 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); 363 rv = jLongToCKULong(errorCode); 364 } 365 366 /* if we attached this thread to the VM just for callback, we detach it now */ 367 if (wasAttached) { 368 returnValue = (*jvm)->DetachCurrentThread(jvm); 369 } 370 371 return rv ; 372 } 373 374 /* 375 * is the function that gets called by PKCS#11 to lock a mutex and calls the Java 376 * LockMutex function 377 * 378 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields 379 * @param pMutex - the mutex to lock 380 * @return - should return CKR_OK if the mutex was not locked already 381 */ 382 CK_RV callJLockMutex(CK_VOID_PTR pMutex) 383 { 384 extern JavaVM *jvm; 385 JNIEnv *env; 386 jint returnValue; 387 jthrowable pkcs11Exception; 388 jclass pkcs11ExceptionClass; 389 jlong errorCode; 390 CK_RV rv = CKR_OK; 391 int wasAttached = 1; 392 jclass jLockMutexClass; 393 jclass jInitArgsClass; 394 jmethodID methodID; 395 jfieldID fieldID; 396 jobject jLockMutex; 397 jobject jMutex; 398 399 400 /* Get the currently running Java VM */ 401 if (jvm == NULL) { return rv ; } /* there is no VM running */ 402 403 /* Determine, if current thread is already attached */ 404 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); 405 if (returnValue == JNI_EDETACHED) { 406 /* thread detached, so attach it */ 407 wasAttached = 0; 408 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 409 } else if (returnValue == JNI_EVERSION) { 410 /* this version of JNI is not supported, so just try to attach */ 411 /* we assume it was attached to ensure that this thread is not detached 412 * afterwards even though it should not 413 */ 414 wasAttached = 1; 415 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 416 } else { 417 /* attached */ 418 wasAttached = 1; 419 } 420 421 jLockMutexClass = (*env)->FindClass(env, CLASS_LOCKMUTEX); 422 if (jLockMutexClass == NULL) { return rv; } 423 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); 424 if (jInitArgsClass == NULL) { return rv; } 425 426 /* convert the CK mutex to a Java mutex */ 427 jMutex = ckVoidPtrToJObject(pMutex); 428 429 /* get the LockMutex object out of the jInitArgs object */ 430 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;"); 431 if (fieldID == NULL) { return rv; } 432 jLockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); 433 assert(jLockMutex != 0); 434 435 /* call the CK_LOCKMUTEX method of the LockMutex object */ 436 methodID = (*env)->GetMethodID(env, jLockMutexClass, "CK_LOCKMUTEX", "(Ljava/lang/Object;)V"); 437 if (methodID == NULL) { return rv; } 438 (*env)->CallVoidMethod(env, jLockMutex, methodID, jMutex); 439 440 /* check, if callback threw an exception */ 441 pkcs11Exception = (*env)->ExceptionOccurred(env); 442 443 if (pkcs11Exception != NULL) { 444 /* TBD: clear the pending exception with ExceptionClear? */ 445 /* The was an exception thrown, now we get the error-code from it */ 446 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); 447 if (pkcs11ExceptionClass == NULL) { return rv; } 448 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J"); 449 if (methodID == NULL) { return rv; } 450 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); 451 rv = jLongToCKULong(errorCode); 452 } 453 454 /* if we attached this thread to the VM just for callback, we detach it now */ 455 if (wasAttached) { 456 returnValue = (*jvm)->DetachCurrentThread(jvm); 457 } 458 459 return rv ; 460 } 461 462 /* 463 * is the function that gets called by PKCS#11 to unlock a mutex and calls the Java 464 * UnlockMutex function 465 * 466 * @param env - used to call JNI funktions to get the Java classes, objects, methods and fields 467 * @param pMutex - the mutex to unlock 468 * @return - should return CKR_OK if the mutex was not unlocked already 469 */ 470 CK_RV callJUnlockMutex(CK_VOID_PTR pMutex) 471 { 472 extern JavaVM *jvm; 473 JNIEnv *env; 474 jint returnValue; 475 jthrowable pkcs11Exception; 476 jclass pkcs11ExceptionClass; 477 jlong errorCode; 478 CK_RV rv = CKR_OK; 479 int wasAttached = 1; 480 jclass jUnlockMutexClass; 481 jclass jInitArgsClass; 482 jmethodID methodID; 483 jfieldID fieldID; 484 jobject jUnlockMutex; 485 jobject jMutex; 486 487 488 /* Get the currently running Java VM */ 489 if (jvm == NULL) { return rv ; } /* there is no VM running */ 490 491 /* Determine, if current thread is already attached */ 492 returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); 493 if (returnValue == JNI_EDETACHED) { 494 /* thread detached, so attach it */ 495 wasAttached = 0; 496 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 497 } else if (returnValue == JNI_EVERSION) { 498 /* this version of JNI is not supported, so just try to attach */ 499 /* we assume it was attached to ensure that this thread is not detached 500 * afterwards even though it should not 501 */ 502 wasAttached = 1; 503 returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); 504 } else { 505 /* attached */ 506 wasAttached = 1; 507 } 508 509 jUnlockMutexClass = (*env)->FindClass(env, CLASS_UNLOCKMUTEX); 510 if (jUnlockMutexClass == NULL) { return rv; } 511 jInitArgsClass = (*env)->FindClass(env, CLASS_C_INITIALIZE_ARGS); 512 if (jInitArgsClass == NULL) { return rv; } 513 514 /* convert the CK-type mutex to a Java mutex */ 515 jMutex = ckVoidPtrToJObject(pMutex); 516 517 /* get the UnlockMutex object out of the jInitArgs object */ 518 fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;"); 519 if (fieldID == NULL) { return rv; } 520 jUnlockMutex = (*env)->GetObjectField(env, jInitArgsObject, fieldID); 521 assert(jUnlockMutex != 0); 522 523 /* call the CK_UNLOCKMUTEX method of the UnLockMutex object */ 524 methodID = (*env)->GetMethodID(env, jUnlockMutexClass, "CK_UNLOCKMUTEX", "(Ljava/lang/Object;)V"); 525 if (methodID == NULL) { return rv; } 526 (*env)->CallVoidMethod(env, jUnlockMutex, methodID, jMutex); 527 528 /* check, if callback threw an exception */ 529 pkcs11Exception = (*env)->ExceptionOccurred(env); 530 531 if (pkcs11Exception != NULL) { 532 /* TBD: clear the pending exception with ExceptionClear? */ 533 /* The was an exception thrown, now we get the error-code from it */ 534 pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); 535 if (pkcs11ExceptionClass == NULL) { return rv; } 536 methodID = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J"); 537 if (methodID == NULL) { return rv; } 538 errorCode = (*env)->CallLongMethod(env, pkcs11Exception, methodID); 539 rv = jLongToCKULong(errorCode); 540 } 541 542 /* if we attached this thread to the VM just for callback, we detach it now */ 543 if (wasAttached) { 544 returnValue = (*jvm)->DetachCurrentThread(jvm); 545 } 546 547 return rv ; 548 } 549 550 #endif /* NO_CALLBACKS */