JNIEXPORT void JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZDBusNativeTests_testThrowException
(JNIEnv *env, jclass peer, jint extype) {
    switch (extype) {
        case 0: throwException(env, "java/lang/Exception", "0"); break;
        case 1: throwException(env, "java/lang/Exception", "1[%s]", "str"); break;
        case 2: throwIOException(env, "2"); break;
        case 3: throwIOException(env, "3[%s]", "str"); break;
        case 4: throwBluetoothStateException(env, "4"); break;
        case 5: throwBluetoothStateException(env, "5[%s]", "str"); break;
        case 6: throwRuntimeException(env, "6"); break;
        case 7: throwBluetoothConnectionException(env, 1, "7"); break;
        case 8: throwBluetoothConnectionException(env, 2, "8[%s]", "str"); break;

        case 22:
            // Throw Exception two times in a row. Second Exception ignored
            throwException(env, "java/lang/Exception", "22.1");
            throwIOException(env, "22.2");
            break;
    }
}
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackWIDCOMM_l2ServerAcceptAndOpenServerConnection
(JNIEnv *env, jobject peer, jlong handle) {
    WIDCOMMStackL2CapServer* srv = validL2CapServerHandle(env, handle);
    if (srv == NULL) {
        return 0;
    }
    if (srv->sdpService == NULL) {
        throwIOException(env, cCONNECTION_CLOSED);
        return 0;
    }
    if (!srv->finalizeSDPRecord(env)) {
        return 0;
    }
    #ifdef BWT_SINCE_SDK_6_0_1
    srv->sdpService->CommitRecord();
    #endif

    EnterCriticalSection(&stack->csCommIf);
    if (stack == NULL) {
        throwInterruptedIOException(env, cSTACK_CLOSED);
    }

    WIDCOMMStackL2CapConn* l2c = stack->createL2CapConn();
    if (l2c == NULL) {
        throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_NO_RESOURCES, "No free connections Objects in Pool");
        LeaveCriticalSection(&stack->csCommIf);
        return 0;
    }
    srv->addClient(l2c);
    l2c->receiveMTU = srv->receiveMTU;
    l2c->transmitMTU = srv->transmitMTU;

    BOOL rc = l2c->Listen(&(srv->l2CapIf));
    if (stack != NULL) {
        LeaveCriticalSection(&stack->csCommIf);
    }

    if (!rc) {
        throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to Listen");
        accept_l2_server_return 0;
    }

    HANDLE hEvents[2];
    hEvents[0] = l2c->hConnectionEvent;
    hEvents[1] = srv->hConnectionEvent;

    debug(("l2s(%i) l2(%i) L2CAP server waits for connection", srv->internalHandle, l2c->internalHandle));
    long incomingConnectionCountWas = incomingL2CAPConnectionCount;
    while ((stack != NULL) && (!srv->isClosing)  && (!l2c->isConnected) && (!l2c->isDisconnected) && (srv->sdpService != NULL)) {
        DWORD  rc = WaitForMultipleObjects(2, hEvents, FALSE, 500);
        if (rc == WAIT_FAILED) {
            throwRuntimeException(env, "WaitForSingleObject");
            accept_l2_server_return 0;
        }
        if ((stack != NULL) && (incomingConnectionCountWas != incomingL2CAPConnectionCount)) {
            debug(("L2CAP server incomingConnectionCount %i", incomingL2CAPConnectionCount));
            incomingConnectionCountWas = incomingL2CAPConnectionCount;
        }
        if (isCurrentThreadInterrupted(env, peer, "accept")) {
            accept_l2_server_return 0;
        }
    }
    if (stack == NULL) {
        throwInterruptedIOException(env, cSTACK_CLOSED);
        return 0;
    }
    if (!l2c->isConnected) {
        if (srv->isClosing || (srv->sdpService == NULL)) {
            throwInterruptedIOException(env, cCONNECTION_CLOSED);
        } else if (l2c->isDisconnected) {
            throwIOException(env, "Connection error");
        } else {
            throwIOException(env, "Failed to connect");
        }
        accept_l2_server_return 0;
    }

    debug(("l2s(%i) l2(%i) L2CAP server connection made", srv->internalHandle, l2c->internalHandle));
    l2c->selectConnectionTransmitMTU(env);
    return l2c->internalHandle;
}
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackWIDCOMM_l2ServerOpenImpl
(JNIEnv *env, jobject, jbyteArray uuidValue, jboolean authenticate, jboolean encrypt, jstring name, jint receiveMTU, jint transmitMTU, jint assignPsm) {
    if (stack == NULL) {
        throwIOException(env, cSTACK_CLOSED);
        return 0;
    }
    EnterCriticalSection(&stack->csCommIf);
    WIDCOMMStackL2CapServer* srv = NULL;
//VC6   __try {
        srv = stack->createL2CapServer();
        if (srv == NULL) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_NO_RESOURCES, "No free connections Objects in Pool");
            open_l2server_return 0;
        }
        debug(("l2s(%i) L2CapConn server handle created", srv->internalHandle));
        if (srv->hConnectionEvent == NULL) {
            throwRuntimeException(env, "fails to CreateEvent");
            open_l2server_return 0;
        }
        srv->transmitMTU = (UINT16)transmitMTU;
        srv->receiveMTU = (UINT16)receiveMTU;

        jbyte *bytes = env->GetByteArrayElements(uuidValue, 0);
        convertUUIDBytesToGUID(bytes, &(srv->service_guid));
        env->ReleaseByteArrayElements(uuidValue, bytes, 0);

        CL2CapIf *l2CapIf;
        l2CapIf = &srv->l2CapIf;

        if (!l2CapIf->AssignPsmValue(&(srv->service_guid), (UINT16)assignPsm)) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_UNKNOWN_PSM, "failed to assign PSM");
            open_l2server_return 0;
        }
        l2CapIf->Register();

        const char *cname = env->GetStringUTFChars(name, 0);
        #ifdef _WIN32_WCE
            swprintf_s((wchar_t*)srv->service_name, BT_MAX_SERVICE_NAME_LEN, L"%s", cname);
        #else // _WIN32_WCE
            sprintf_s(srv->service_name, BT_MAX_SERVICE_NAME_LEN, "%s", cname);
        #endif // #else // _WIN32_WCE
        env->ReleaseStringUTFChars(name, cname);

        srv->service_guids_len = 1;
        srv->service_guids = new GUID[srv->service_guids_len];
        if (srv->service_guids == NULL) {
            throwIOException(env, cOUT_OF_MEMORY);
            open_l2server_return 0;
        }
		memcpy(&(srv->service_guids[0]), &(srv->service_guid), sizeof(GUID));

        srv->proto_num_elem = 1;
        srv->proto_elem_list = new tSDP_PROTOCOL_ELEM[srv->proto_num_elem];
		if (srv->proto_elem_list == NULL) {
            throwIOException(env, cOUT_OF_MEMORY);
            open_l2server_return 0;
        }
		srv->proto_elem_list[0].protocol_uuid = 0x0100; // L2CAP
		srv->proto_elem_list[0].num_params = 1;
		srv->proto_elem_list[0].params[0] = l2CapIf->GetPsm();

        UINT8 sec_level = BTM_SEC_NONE;
        if (authenticate) {
            sec_level = BTM_SEC_IN_AUTHENTICATE;
        }
        if (encrypt) {
            sec_level = sec_level | BTM_SEC_IN_ENCRYPT;
        }
        if (!l2CapIf->SetSecurityLevel(srv->service_name, sec_level, TRUE)) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_SECURITY_BLOCK, "Error setting security level");
            open_l2server_return 0;
        }

        jlong handle = srv->internalHandle;
        srv = NULL;
        open_l2server_return handle;
/*VC6} __finally { } */
}
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackWIDCOMM_l2OpenClientConnectionImpl
(JNIEnv *env, jobject peer, jlong address, jint channel, jboolean authenticate, jboolean encrypt, jint receiveMTU, jint transmitMTU, jint timeout) {
    BD_ADDR bda;
    LongToBcAddr(address, bda);

    WIDCOMMStackL2CapConn* l2c = NULL;
    EnterCriticalSection(&stack->csCommIf);
    //vc6 __try {
        l2c = stack->createL2CapConn();
        if (l2c == NULL) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_NO_RESOURCES, "No free connections Objects in Pool");
            open_l2client_return 0;
        }
        debug(("l2(%i) L2CapConn handle created", l2c->internalHandle));
        if ((l2c->hConnectionEvent == NULL) || (l2c->hDataReceivedEvent == NULL)) {
            throwRuntimeException(env, "fails to CreateEvent");
            open_l2client_return 0;
        }
        debug(("L2CapConn channel 0x%X", channel));
        //debug(("AssignPsmValue");

        CL2CapIf *l2CapIf = new CL2CapIf();
        l2c->pL2CapIf = l2CapIf;

        if (!l2CapIf->AssignPsmValue(&(l2c->service_guid), (UINT16)channel)) {
            // What GUID do we need in call to CL2CapIf.AssignPsmValue() if we don't have any?
            // NEED This for stack version 3.0.1.905
            // TODO test on  v5.0.1.2800 and v4.0.1.2900
            GUID any_client_service_guid = {2970356705 , 4369, 4369, {17 , 17, 17 , 17, 17, 17 , 0, 1}};
            memcpy(&(l2c->service_guid), &any_client_service_guid, sizeof(GUID));

            if (!l2CapIf->AssignPsmValue(&(l2c->service_guid), (UINT16)channel)) {
                throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_UNKNOWN_PSM, "failed to assign PSM 0x%X", (UINT16)channel);
                open_l2client_return 0;
            }
        }
        l2CapIf->Register();

        UINT8 sec_level = BTM_SEC_NONE;
        if (authenticate) {
            sec_level = BTM_SEC_OUT_AUTHENTICATE;
        }
        if (encrypt) {
            sec_level = sec_level | BTM_SEC_OUT_ENCRYPT;
        }

        BT_CHAR *p_service_name;
        #ifdef _WIN32_WCE
            p_service_name = (BT_CHAR*)L"bluecovesrv";
        #else // _WIN32_WCE
            p_service_name = "bluecovesrv";
        #endif // #else // _WIN32_WCE

        if (!l2CapIf->SetSecurityLevel(p_service_name, sec_level, FALSE)) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_SECURITY_BLOCK, "Error setting security level");
            open_l2client_return 0;
        }

        //debug(("OpenL2CAPClient"));
        l2c->transmitMTU = (UINT16)transmitMTU;
        l2c->receiveMTU = (UINT16)receiveMTU;
        BOOL rc = l2c->Connect(l2CapIf, bda, l2c->receiveMTU);
        if (!rc) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to Connect");
            open_l2client_return 0;
        }

        //debug(("waitFor Connection signal");
        DWORD waitStart = GetTickCount();
        while ((stack != NULL) && (!l2c->isConnected) && (!l2c->isDisconnected)) {
            DWORD  rc = WaitForSingleObject(l2c->hConnectionEvent, 500);
            if (rc == WAIT_FAILED) {
                throwRuntimeException(env, "WaitForSingleObject");
                open_l2client_return 0;
            }
            if (isCurrentThreadInterrupted(env, peer, "connect")) {
                open_l2client_return 0;
            }
            if ((timeout > 0) && ((GetTickCount() - waitStart)  > (DWORD)timeout)) {
                throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_TIMEOUT, "Connection timeout");
                open_l2client_return 0;
            }
        }
        if (stack == NULL) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to connect");
            open_l2client_return 0;
        }
        if (!l2c->isConnected) {
            throwBluetoothConnectionException(env, BT_CONNECTION_ERROR_FAILED_NOINFO, "Failed to connect");
            open_l2client_return 0;
        }

        debug(("l2(%i) l2Client connected", l2c->internalHandle));
        l2c->selectConnectionTransmitMTU(env);
        jlong handle = l2c->internalHandle;
        l2c = NULL;
        open_l2client_return handle;
    /* vc6 } __finally {} */
}