21 #include <winpr/config.h>
22 #include <winpr/assert.h>
23 #include <winpr/string.h>
25 #include "../utils/android.h"
29 #define MIN(a, b) (a) < (b) ? (a) : (b)
33 #define TAG WINPR_TAG("unicode")
35 static int convert_int(JNIEnv* env,
const void* data,
size_t size,
void* buffer,
size_t buffersize,
39 WINPR_ASSERT(data || (size == 0));
40 WINPR_ASSERT(buffer || (buffersize == 0));
42 jstring utf8 = (*env)->NewStringUTF(env,
"UTF-8");
43 jstring utf16 = (*env)->NewStringUTF(env,
"UTF-16LE");
44 jclass stringClass = (*env)->FindClass(env,
"java/lang/String");
46 if (!utf8 || !utf16 || !stringClass)
48 WLog_ERR(TAG,
"utf8-%p, utf16=%p, stringClass=%p", utf8, utf16, stringClass);
52 jmethodID constructorID =
53 (*env)->GetMethodID(env, stringClass,
"<init>",
"([BLjava/lang/String;)V");
54 jmethodID getBytesID =
55 (*env)->GetMethodID(env, stringClass,
"getBytes",
"(Ljava/lang/String;)[B");
56 if (!constructorID || !getBytesID)
58 WLog_ERR(TAG,
"constructorID=%p, getBytesID=%p", constructorID, getBytesID);
62 jbyteArray ret = (*env)->NewByteArray(env, size);
65 WLog_ERR(TAG,
"NewByteArray(%" PRIuz
") failed", size);
69 (*env)->SetByteArrayRegion(env, ret, 0, size, data);
71 jobject obj = (*env)->NewObject(env, stringClass, constructorID, ret, toUTF16 ? utf8 : utf16);
74 WLog_ERR(TAG,
"NewObject(String, byteArray, UTF-%d) failed", toUTF16 ? 16 : 8);
78 jbyteArray res = (*env)->CallObjectMethod(env, obj, getBytesID, toUTF16 ? utf16 : utf8);
81 WLog_ERR(TAG,
"CallObjectMethod(String, getBytes, UTF-%d) failed", toUTF16 ? 16 : 8);
85 jsize rlen = (*env)->GetArrayLength(env, res);
88 if (rlen > buffersize)
90 SetLastError(ERROR_INSUFFICIENT_BUFFER);
93 rlen = MIN(rlen, buffersize);
94 (*env)->GetByteArrayRegion(env, res, 0, rlen, buffer);
98 rlen /=
sizeof(WCHAR);
103 static int convert(
const void* data,
size_t size,
void* buffer,
size_t buffersize, BOOL toUTF16)
107 jboolean attached = winpr_jni_attach_thread(&env);
108 rc = convert_int(env, data, size, buffer, buffersize, toUTF16);
110 winpr_jni_detach_thread();
114 int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte,
115 LPWSTR lpWideCharStr,
int cchWideChar)
117 size_t cbCharLen = (size_t)cbMultiByte;
119 WINPR_UNUSED(dwFlags);
122 if ((cbMultiByte == 0) || (cbMultiByte < -1))
130 const size_t len = strlen(lpMultiByteStr);
131 if (len >= INT32_MAX)
133 cbCharLen = (int)len + 1;
136 cbCharLen = cbMultiByte;
138 WINPR_ASSERT(lpMultiByteStr);
146 WLog_ERR(TAG,
"Unsupported encoding %u", CodePage);
150 return convert(lpMultiByteStr, cbCharLen, lpWideCharStr, cchWideChar *
sizeof(WCHAR), TRUE);
153 int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
int cchWideChar,
154 LPSTR lpMultiByteStr,
int cbMultiByte, LPCSTR lpDefaultChar,
155 LPBOOL lpUsedDefaultChar)
157 size_t cbCharLen = (size_t)cchWideChar;
159 WINPR_UNUSED(dwFlags);
161 if ((cchWideChar == 0) || (cchWideChar < -1))
167 WINPR_ASSERT(lpWideCharStr);
169 if (cchWideChar == -1)
171 const size_t len = _wcslen(lpWideCharStr);
172 if (len >= INT32_MAX)
174 cbCharLen = (int)len + 1;
177 cbCharLen = cchWideChar;
183 return convert(lpWideCharStr, cbCharLen *
sizeof(WCHAR), lpMultiByteStr, cbMultiByte, FALSE);