Active Directory A device attached to the system is not functioning when creating ad user using jni

Issue

I am trying to create a servlet web application which creates active directory application,
So am calling the native method using java native interface and it produces this error.
The user is created when calling the c++ code but when calling the same c++ code with jni interface am getting A device attached to the system is not functioning error.
C++ code.

#include "atlbase.h"
#include <atlstr.h>

void CreateUserFromADs(LPCWSTR pwszFirstName, LPCWSTR pwszLastName, LPCWSTR pwszSAMAccountName, LPCWSTR pwszInitialPassword);
LPCWSTR jstring2string(JNIEnv* env, jstring jStr) {
    const jclass stringClass = env->GetObjectClass(jStr);
    const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
    const jbyteArray stringJbytes = (jbyteArray)env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8"));

    size_t length = (size_t)env->GetArrayLength(stringJbytes);
    jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);

    std::string ret = std::string((char*)pBytes, length);
    env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);

    env->DeleteLocalRef(stringJbytes);
    env->DeleteLocalRef(stringClass);
    std::wstring converted = std::wstring(ret.begin(), ret.end());
    return converted.c_str();
}


JNIEXPORT void JNICALL Java_Test_createUser
(JNIEnv* env, jobject obj, jstring pwszFirstName, jstring pwszLastName, jstring pwszSAMAccountName, jstring pwszInitialPassword) {
    LPCWSTR convertedFirstname = jstring2string(env, pwszFirstName);
    LPCWSTR convertLastName = jstring2string(env, pwszLastName);
    LPCWSTR convertAccname = jstring2string(env, pwszSAMAccountName);
    LPCWSTR convPassword = jstring2string(env, pwszInitialPassword);
    CreateUserFromADs(convertedFirstname, convertLastName, convertAccname, convPassword);
}
void CreateUserFromADs(LPCWSTR pwszFirstName, LPCWSTR pwszLastName, LPCWSTR pwszSAMAccountName, LPCWSTR pwszInitialPassword)
{
    HRESULT hr;
    CoInitialize(NULL);
    IADsContainer* pUsers = NULL;
    std::cout << "Intially pUsers : " << pUsers << std::endl;
    hr = ADsOpenObject(L"LDAP://WIN-F94H2MP3UJR.Test.local/CN=Users,DC=Test,DC=local", L"Administrator", L"[email protected]",
        ADS_SECURE_AUTHENTICATION, // For secure authentication
        IID_IADsContainer,
        (void**)&pUsers);
    // Here pUser has some values now.
    std::cout << "After :" << pUsers << std::endl;
    if (SUCCEEDED(hr))
    {
        IDispatch* __stdcall pDisp = NULL;
        std::cout << "Initially pdisp:" << pDisp << std::endl;
        CComBSTR sbstrName = "CN=";
        sbstrName += pwszFirstName;
        // Create the new object in the User folder.
        hr = pUsers->Create(CComBSTR("user"), sbstrName, &pDisp);
        std::cout << "After pdisp:" << pDisp << std::endl;
        if (SUCCEEDED(hr))
        {
            IADsUser* padsUser = NULL;
            hr = pDisp->QueryInterface(IID_IADsUser, (void**)&padsUser);
            std::cout << "After padsUser:" << padsUser << std::endl;
            if (SUCCEEDED(hr))
            {
                CComBSTR sbstrProp;
                CComVariant svar;
                //Pre windows 2000 
                svar = pwszSAMAccountName;
                sbstrProp = "sAMAccountName";
                hr = padsUser->Put(sbstrProp, svar);
                hr = padsUser->SetInfo();
                // newer syntax
                sbstrProp = "userPrincipalName";
                hr = padsUser->Put(sbstrProp, svar);
                hr = padsUser->SetInfo();
                //This one sets the firstname.
                hr = padsUser->Put(CComBSTR("givenName"), (CComVariant)pwszFirstName);
                hr = padsUser->SetInfo();

                hr = padsUser->Put(CComBSTR("displayName"), (CComVariant)pwszFirstName);
                hr = padsUser->SetInfo();
                // This one sets the last name here.
                hr = padsUser->Put(CComBSTR("sn"), (CComVariant)pwszLastName);
                hr = padsUser->SetInfo();
                // Set Passoword here.
                hr = padsUser->SetPassword(CComBSTR(pwszInitialPassword));
                svar.Clear();
                sbstrProp = "userAccountControl";
                hr = padsUser->Get(sbstrProp, &svar);
                if (SUCCEEDED(hr))
                {
                    svar = svar.lVal & ~(ADS_UF_ACCOUNTDISABLE |
                        ADS_UF_PASSWD_NOTREQD |
                        ADS_UF_DONT_EXPIRE_PASSWD);
                    hr = padsUser->Put(sbstrProp, svar);
                    hr = padsUser->SetInfo();
                }
                hr = padsUser->put_AccountDisabled(VARIANT_FALSE);
                hr = padsUser->SetInfo();
                padsUser->Release();
            }
            pDisp->Release();
        }
        pUsers->Release();
    }
    CoUninitialize();
    std::string message = std::system_category().message(hr);
    std::cout << message << std::endl;
}

Java code which imports the dll file and call the native method and produces the error.

public class Test {
    static{
        System.loadLibrary("testNativeMethods");
    }
    public native void createUser(String firstName,String lastName,String accountName,String password );
    public static void main(String[] args) {
        Test t = new Test();
        t.createUser("maggi","dsds","maggi01","[email protected]");
    }
}

Solution

Here there is error in converting the jstring to the LPWCSTR .
Use this function to convert jstring to LPWCSTR

LPCWSTR jstring2LPWSTR(JNIEnv* env, jstring jStr) {
    const jclass stringClass = env->GetObjectClass(jStr);
    const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
    const jbyteArray stringJbytes = (jbyteArray)env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8"));

    size_t length = (size_t)env->GetArrayLength(stringJbytes);
    jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);

    std::string ret = std::string((char*)pBytes, length);
    env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);

    env->DeleteLocalRef(stringJbytes);
    env->DeleteLocalRef(stringClass);
    LPWSTR ws = new wchar_t[s.size() + 1]; // +1 for zero at the end
    copy(ret.begin(), ret.end(), ws);
    ws[ret.size()] = 0; // zero at the end
    return ws;
}

Answered By – SI-2493

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published