<Sound Dev> 8177951: Charset problem when the name of the sound device contains Chinese character.

CharlieJiang cqjjjzr at 126.com
Sun Jul 30 22:40:15 UTC 2017


Hi Alex,

Thanks for your reply. I'll sign the OCA soon, don't worry about it.
I'm so sorry about the low-level mistake that I made in the code. 
Here's the new patch(just compared to the root repo instead of the previous patch, so you need to revert if the old patch is already applied to the branch):

# HG changeset patch
# User Charlie Jiang<cqjjjzr at 126.com>
# Date 1498382295 -28800
# Node ID 1bfe64cffda51c00fccf48e9c0c2adb533fa7e5c
# Parent  2425838cfb5e63bf798e383492890c25170b91d1
8177951: Charset problem when the name of the sound device contains Chinese character
Summary: Fix the problem by returning the UTF-8 encoded string.
Contributed-by: Charlie Jiang <cqjjjzr at 126.com>

diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
@@ -86,6 +86,28 @@
 static UINT64 g_lastCacheRefreshTime = 0;
 static INT32 g_mixerCount = 0;
 
+/// FIX BUG JDK-8177951: Convert ANSI encoded string to UTF-8 encoded string
+LPCSTR ANSIToUTF8(const LPCSTR& lpAnsiStr)
+{
+    // ANSI -> Unicode
+    DWORD dwAnsiLen = strlen(lpAnsiStr);
+    DWORD dwUnicodeLen = ::MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, NULL, 0);
+    LPWSTR lpUnicodeStr;
+    lpUnicodeStr = new WCHAR[dwUnicodeLen];
+    memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
+
+    // Unicode -> UTF8
+    LPSTR lpUTF8Str;
+    DWORD dwUTF8Len;
+    dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, NULL, 0, NULL, NULL);
+    lpUTF8Str = new CHAR[dwUTF8Len];
+    memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
+    WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, NULL, NULL);
+    delete lpUnicodeStr;
+    return lpUTF8Str;
+}
+
 BOOL DS_lockCache() {
     /* dummy implementation for now, Java does locking */
     return TRUE;
@@ -233,7 +255,13 @@
 
     INT32 cacheIndex = findCacheItemByGUID(lpGuid, g_audioDeviceCache[desc->deviceID].isSource);
     if (cacheIndex == desc->deviceID) {
+#ifndef UNICODE
+        LPCSTR utf8EncodedName = ANSIToUTF8(lpstrDescription);
+        strncpy(desc->name, utf8EncodedName, DAUDIO_STRING_LENGTH);
+        delete utf8EncodedName;
+#else
         strncpy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
+#endif
         //strncpy(desc->description, lpstrModule, DAUDIO_STRING_LENGTH);
         desc->maxSimulLines = -1;
         /* do not continue enumeration */
# HG changeset patch
# User Charlie Jiang<cqjjjzr at 126.com>
# Date 1500538314 -28800
# Node ID c86ae2f3e1022f9b27ad6918fa342c5a4ee309c0
# Parent  1bfe64cffda51c00fccf48e9c0c2adb533fa7e5c
8177951: Charset problem when the name of the sound device contains Chinese character
Summary: Fix issues in the ANSI2UTF-8 function and move it to a seperate file and fix Port Sound and MIDI Sound devices.
Contributed-by: Charlie Jiang <cqjjjzr at 126.com>

diff --git a/make/lib/SoundLibraries.gmk b/make/lib/SoundLibraries.gmk
--- a/make/lib/SoundLibraries.gmk
+++ b/make/lib/SoundLibraries.gmk
@@ -61,6 +61,7 @@
       -DUSE_PLATFORM_MIDI_IN=TRUE \
       -DUSE_PORTS=TRUE
   LIBJSOUND_SRC_FILES += \
+      PLATFORM_API_WinOS_Charset_Util.cpp \
       PLATFORM_API_WinOS_MidiIn.cpp \
       PLATFORM_API_WinOS_MidiOut.c \
       PLATFORM_API_WinOS_Util.c \
@@ -190,6 +191,7 @@
       OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
       SRC := $(LIBJSOUND_SRC_DIRS), \
       INCLUDE_FILES := Utilities.c $(LIBJSOUND_DAUDIOFILES) \
+          PLATFORM_API_WinOS_Charset_Util.cpp \
           PLATFORM_API_WinOS_DirectSound.cpp, \
       OPTIMIZATION := LOW, \
       CFLAGS := $(CFLAGS_JDKLIB) \
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
new file mode 100644
--- /dev/null
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+ 
+#include "PLATFORM_API_WinOS_Charset_Util.h"
+
+#include <cstring>
+
+extern "C" LPSTR ANSIToUTF8(const LPCSTR lpAnsiStr)
+{    
+    // ANSI -> Unicode
+    DWORD dwUnicodeLen = 0;
+    LPWSTR lpUnicodeStr = nullptr;
+    dwUnicodeLen = MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, nullptr, 0);
+    lpUnicodeStr = new WCHAR[dwUnicodeLen];
+    memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
+
+    // Unicode -> UTF8
+    LPSTR lpUTF8Str = nullptr;
+    DWORD dwUTF8Len = 0;
+    dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, nullptr, 0, nullptr, nullptr);
+    lpUTF8Str = new CHAR[dwUTF8Len];
+    memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
+    WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, nullptr, nullptr);
+    delete[] lpUnicodeStr;
+    return lpUTF8Str;
+}
+
+extern "C" void ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength) {
+#ifndef UNICODE
+    LPSTR utf8EncodedName = ANSIToUTF8(src);
+    strncpy(dest, utf8EncodedName, maxLength - 1);
+    delete[] utf8EncodedName;
+#else
+    strncpy(dest, src, maxLength - 1);
+#endif
+    dest[maxLength - 1] = '\0';
+}
+ 
\ No newline at end of file
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
new file mode 100644
--- /dev/null
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef PLATFORM_API_WINOS_CHARSET_UTILS_H
+#define PLATFORM_API_WINOS_CHARSET_UTILS_H
+
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LPSTR _cdecl ANSIToUTF8(const LPCSTR lpAnsiStr);
+
+void _cdecl ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
@@ -52,6 +52,9 @@
 }
 #endif
 
+/* include to prevent charset problem */
+#include "PLATFORM_API_WinOS_Charset_Util.h"
+
 #ifdef USE_DEBUG_SILENCING
 #define DEBUG_SILENCING0(p) TRACE0(p)
 #define DEBUG_SILENCING1(p1,p2) TRACE1(p1,p2)
@@ -86,28 +89,6 @@
 static UINT64 g_lastCacheRefreshTime = 0;
 static INT32 g_mixerCount = 0;
 
-/// FIX BUG JDK-8177951: Convert ANSI encoded string to UTF-8 encoded string
-LPCSTR ANSIToUTF8(const LPCSTR& lpAnsiStr)
-{
-    // ANSI -> Unicode
-    DWORD dwAnsiLen = strlen(lpAnsiStr);
-    DWORD dwUnicodeLen = ::MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, NULL, 0);
-    LPWSTR lpUnicodeStr;
-    lpUnicodeStr = new WCHAR[dwUnicodeLen];
-    memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
-    MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
-
-    // Unicode -> UTF8
-    LPSTR lpUTF8Str;
-    DWORD dwUTF8Len;
-    dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, NULL, 0, NULL, NULL);
-    lpUTF8Str = new CHAR[dwUTF8Len];
-    memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
-    WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, NULL, NULL);
-    delete lpUnicodeStr;
-    return lpUTF8Str;
-}
-
 BOOL DS_lockCache() {
     /* dummy implementation for now, Java does locking */
     return TRUE;
@@ -255,13 +236,7 @@
 
     INT32 cacheIndex = findCacheItemByGUID(lpGuid, g_audioDeviceCache[desc->deviceID].isSource);
     if (cacheIndex == desc->deviceID) {
-#ifndef UNICODE
-        LPCSTR utf8EncodedName = ANSIToUTF8(lpstrDescription);
-        strncpy(desc->name, utf8EncodedName, DAUDIO_STRING_LENGTH);
-        delete utf8EncodedName;
-#else
-        strncpy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
-#endif
+        ANSIToUTF8IfNeededAndCopy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
         //strncpy(desc->description, lpstrModule, DAUDIO_STRING_LENGTH);
         desc->maxSimulLines = -1;
         /* do not continue enumeration */
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
@@ -31,6 +31,9 @@
 #include "PLATFORM_API_WinOS_Util.h"
 }
 
+/* include to prevent charset problem */
+#include "PLATFORM_API_WinOS_Charset_Util.h"
+
 #if USE_PLATFORM_MIDI_IN == TRUE
 
 #ifdef USE_ERROR
@@ -258,8 +261,7 @@
     INT32 err;
 
     if (getMidiInCaps(deviceID, &midiInCaps, &err)) {
-        strncpy(name, midiInCaps.szPname, nameLength-1);
-        name[nameLength-1] = 0;
+        ANSIToUTF8IfNeededAndCopy(name, midiInCaps.szPname, nameLength);
         return MIDI_SUCCESS;
     }
     MIDIIN_CHECK_ERROR;
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
@@ -28,6 +28,9 @@
 
 #include "PLATFORM_API_WinOS_Util.h"
 
+/* include to prevent charset problem */
+#include "PLATFORM_API_WinOS_Charset_Util.h"
+
 #if USE_PLATFORM_MIDI_OUT == TRUE
 
 
@@ -82,8 +85,7 @@
     INT32 err;
 
     if (getMidiOutCaps(deviceID, &midiOutCaps, &err)) {
-        strncpy(name, midiOutCaps.szPname, nameLength-1);
-        name[nameLength-1] = 0;
+        ANSIToUTF8IfNeededAndCopy(name, midiOutCaps.szPname, nameLength);
         return MIDI_SUCCESS;
     }
     MIDIOUT_CHECK_ERROR;
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
@@ -38,6 +38,9 @@
 #include <mmsystem.h>
 #include "Ports.h"
 
+/* include to prevent charset problem */
+#include "PLATFORM_API_WinOS_Charset_Util.h"
+
 #if USE_PORTS == TRUE
 
 typedef struct tag_PortControlID PortControlID;
@@ -355,8 +358,7 @@
 INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
     MIXERCAPS mixerCaps;
     if (mixerGetDevCaps(mixerIndex, &mixerCaps, sizeof(MIXERCAPS)) == MMSYSERR_NOERROR) {
-        strncpy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH-1);
-        description->name[PORT_STRING_LENGTH-1] = 0;
+        ANSIToUTF8IfNeededAndCopy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH);
         sprintf(description->version, "%d.%d", (mixerCaps.vDriverVersion & 0xFF00) >> 8, mixerCaps.vDriverVersion & 0xFF);
         strncpy(description->description, "Port Mixer", PORT_STRING_LENGTH-1);
         return TRUE;
# HG changeset patch
# User Charlie Jiang<cqjjjzr at 126.com>
# Date 1501430954 -28800
# Node ID 505fc2325a7192103b65fa42920e3cd06a1bdf01
# Parent  c86ae2f3e1022f9b27ad6918fa342c5a4ee309c0
8177951: Charset problem when the name of the sound device contains Chinese character
Summary: See http://mail.openjdk.java.net/pipermail/sound-dev/2017-July/000580.html
Contributed-by: Charlie Jiang <cqjjjzr at 126.com>

diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,35 +27,27 @@
 
 #include <cstring>
 
-extern "C" LPSTR ANSIToUTF8(const LPCSTR lpAnsiStr)
-{    
-    // ANSI -> Unicode
-    DWORD dwUnicodeLen = 0;
-    LPWSTR lpUnicodeStr = nullptr;
-    dwUnicodeLen = MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, nullptr, 0);
-    lpUnicodeStr = new WCHAR[dwUnicodeLen];
-    memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
-    MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-    // Unicode -> UTF8
-    LPSTR lpUTF8Str = nullptr;
-    DWORD dwUTF8Len = 0;
-    dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, nullptr, 0, nullptr, nullptr);
-    lpUTF8Str = new CHAR[dwUTF8Len];
+LPSTR UnicodeToUTF8(const LPCWSTR lpUnicodeStr)
+{
+	DWORD dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, nullptr, 0, nullptr, nullptr);
+    LPSTR lpUTF8Str = new CHAR[dwUTF8Len];
     memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
     WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, nullptr, nullptr);
-    delete[] lpUnicodeStr;
     return lpUTF8Str;
 }
 
-extern "C" void ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength) {
-#ifndef UNICODE
-    LPSTR utf8EncodedName = ANSIToUTF8(src);
+void UnicodeToUTF8AndCopy(LPSTR dest, LPCWSTR src, SIZE_T maxLength) {
+	LPSTR utf8EncodedName = UnicodeToUTF8(src);
     strncpy(dest, utf8EncodedName, maxLength - 1);
     delete[] utf8EncodedName;
-#else
-    strncpy(dest, src, maxLength - 1);
-#endif
     dest[maxLength - 1] = '\0';
 }
+
+#ifdef __cplusplus
+}
+#endif
  
\ No newline at end of file
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,9 +32,9 @@
 extern "C" {
 #endif
 
-LPSTR _cdecl ANSIToUTF8(const LPCSTR lpAnsiStr);
+LPSTR _cdecl UnicodeToUTF8(const LPCWSTR lpAnsiStr);
 
-void _cdecl ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength);
+void _cdecl UnicodeToUTF8AndCopy(LPSTR dest, LPCWSTR src, SIZE_T maxLength);
 
 #ifdef __cplusplus
 }
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
@@ -230,13 +230,13 @@
 }
 
 BOOL CALLBACK DS_GetDescEnum(LPGUID lpGuid,
-                             LPCSTR lpstrDescription,
-                             LPCSTR lpstrModule,
+                             LPCWSTR lpstrDescription,
+                             LPCWSTR lpstrModule,
                              DirectAudioDeviceDescription* desc) {
 
     INT32 cacheIndex = findCacheItemByGUID(lpGuid, g_audioDeviceCache[desc->deviceID].isSource);
     if (cacheIndex == desc->deviceID) {
-        ANSIToUTF8IfNeededAndCopy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
+        UnicodeToUTF8AndCopy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
         //strncpy(desc->description, lpstrModule, DAUDIO_STRING_LENGTH);
         desc->maxSimulLines = -1;
         /* do not continue enumeration */
@@ -260,10 +260,10 @@
     }
     desc->maxSimulLines = 0;
     if (g_audioDeviceCache[desc->deviceID].isSource) {
-        DirectSoundEnumerate((LPDSENUMCALLBACK) DS_GetDescEnum, desc);
+        DirectSoundEnumerateW((LPDSENUMCALLBACKW) DS_GetDescEnum, desc);
         strncpy(desc->description, "DirectSound Playback", DAUDIO_STRING_LENGTH);
     } else {
-        DirectSoundCaptureEnumerate((LPDSENUMCALLBACK) DS_GetDescEnum, desc);
+        DirectSoundCaptureEnumerateW((LPDSENUMCALLBACKW) DS_GetDescEnum, desc);
         strncpy(desc->description, "DirectSound Capture", DAUDIO_STRING_LENGTH);
     }
 
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
@@ -251,17 +251,17 @@
     return (INT32) midiInGetNumDevs();
 }
 
-INT32 getMidiInCaps(INT32 deviceID, MIDIINCAPS* caps, INT32* err) {
-    (*err) = midiInGetDevCaps(deviceID, caps, sizeof(MIDIINCAPS));
+INT32 getMidiInCaps(INT32 deviceID, MIDIINCAPSW* caps, INT32* err) {
+    (*err) = midiInGetDevCapsW(deviceID, caps, sizeof(MIDIINCAPS));
     return ((*err) == MMSYSERR_NOERROR);
 }
 
 INT32 MIDI_IN_GetDeviceName(INT32 deviceID, char *name, UINT32 nameLength) {
-    MIDIINCAPS midiInCaps;
+    MIDIINCAPSW midiInCaps;
     INT32 err;
 
     if (getMidiInCaps(deviceID, &midiInCaps, &err)) {
-        ANSIToUTF8IfNeededAndCopy(name, midiInCaps.szPname, nameLength);
+        UnicodeToUTF8AndCopy(name, midiInCaps.szPname, nameLength);
         return MIDI_SUCCESS;
     }
     MIDIIN_CHECK_ERROR;
@@ -281,7 +281,7 @@
 
 
 INT32 MIDI_IN_GetDeviceVersion(INT32 deviceID, char *name, UINT32 nameLength) {
-    MIDIINCAPS midiInCaps;
+    MIDIINCAPSW midiInCaps;
     INT32 err = MIDI_NOT_SUPPORTED;
 
     if (getMidiInCaps(deviceID, &midiInCaps, &err) && (nameLength>7)) {
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
@@ -69,23 +69,23 @@
 }
 
 
-INT32 getMidiOutCaps(INT32 deviceID, MIDIOUTCAPS* caps, INT32* err) {
+INT32 getMidiOutCaps(INT32 deviceID, MIDIOUTCAPSW* caps, INT32* err) {
     if (deviceID == 0) {
         deviceID = MIDI_MAPPER;
     } else {
         deviceID--;
     }
-    (*err) = (INT32) midiOutGetDevCaps(deviceID, caps, sizeof(MIDIOUTCAPS));
+    (*err) = (INT32) midiOutGetDevCapsW(deviceID, caps, sizeof(MIDIOUTCAPS));
     return ((*err) == MMSYSERR_NOERROR);
 }
 
 
 INT32 MIDI_OUT_GetDeviceName(INT32 deviceID, char *name, UINT32 nameLength) {
-    MIDIOUTCAPS midiOutCaps;
+    MIDIOUTCAPSW midiOutCaps;
     INT32 err;
 
     if (getMidiOutCaps(deviceID, &midiOutCaps, &err)) {
-        ANSIToUTF8IfNeededAndCopy(name, midiOutCaps.szPname, nameLength);
+        UnicodeToUTF8AndCopy(name, midiOutCaps.szPname, nameLength);
         return MIDI_SUCCESS;
     }
     MIDIOUT_CHECK_ERROR;
@@ -99,7 +99,7 @@
 
 
 INT32 MIDI_OUT_GetDeviceDescription(INT32 deviceID, char *name, UINT32 nameLength) {
-    MIDIOUTCAPS midiOutCaps;
+    MIDIOUTCAPSW midiOutCaps;
     char *desc;
     INT32 err;
 
@@ -136,7 +136,7 @@
 
 
 INT32 MIDI_OUT_GetDeviceVersion(INT32 deviceID, char *name, UINT32 nameLength) {
-    MIDIOUTCAPS midiOutCaps;
+    MIDIOUTCAPSW midiOutCaps;
     INT32 err;
 
     if (getMidiOutCaps(deviceID, &midiOutCaps, &err) && nameLength>7) {
diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
--- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
+++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
@@ -356,9 +356,9 @@
 ///// implemented functions of Ports.h
 
 INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
-    MIXERCAPS mixerCaps;
-    if (mixerGetDevCaps(mixerIndex, &mixerCaps, sizeof(MIXERCAPS)) == MMSYSERR_NOERROR) {
-        ANSIToUTF8IfNeededAndCopy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH);
+    MIXERCAPSW mixerCaps;
+    if (mixerGetDevCapsW(mixerIndex, &mixerCaps, sizeof(MIXERCAPS)) == MMSYSERR_NOERROR) {
+        UnicodeToUTF8AndCopy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH);
         sprintf(description->version, "%d.%d", (mixerCaps.vDriverVersion & 0xFF00) >> 8, mixerCaps.vDriverVersion & 0xFF);
         strncpy(description->description, "Port Mixer", PORT_STRING_LENGTH-1);
         return TRUE;


At 2017-07-29 05:16:12, "Alex Menkov" <alexey.menkov at oracle.com> wrote:
>Hi Charlie,
>
>First of all - you have to sign OSA so Oracle may use your code.
>
>About the proposed fix:
>- copyright headers contains wrong years (1999, 2012).
>should be
>  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
>
>- do you really need 'extern "C"' stuff? Have you got some linkage 
>errors without it?
>
>- as I see in the code, javasound libraries cannot be compiled with 
>UNICODE, so code in "#ifdef UNICODE" doesn't make sense.
>
>- it would be better to define and initialize variables at the same time:
>     // ANSI -> Unicode
>     DWORD dwUnicodeLen = MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, 
>nullptr, 0);
>     LPWSTR lpUnicodeStr = new WCHAR[dwUnicodeLen];
>...
>     // Unicode -> UTF8
>     DWORD dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, 
>nullptr, 0, nullptr, nullptr);
>     LPSTR lpUTF8Str = new CHAR[dwUTF8Len];
>
>BTW it's not ANSI, it's ACP (Active Code Page) encoding.
>
>
>- I think it would be better (and simpler) to request system to get 
>Unicode strings (by calling Unicode versions of the functions), then 
>only a single conversion (Unicode -> utf8) is required:
>void copyUnicodeToUtf8(LPSTR dst, LPCWSTR src, size_t dstMaxSize);
>
>For DirectSound:
>convert DS_GetDescEnum to LPDSENUMCALLBACKW type:
>
>BOOL CALLBACK DS_GetDescEnum(LPGUID lpGuid,
>                              LPCWSTR lpstrDescription,
>                              LPCWSTR lpstrModule,
>                              DirectAudioDeviceDescription* desc)
>...
>-        strncpy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
>+        copyUnicodeToUtf8(desc->name, lpstrDescription, 
>DAUDIO_STRING_LENGTH);
>
>and in DAUDIO_GetDirectAudioDeviceDescription call
>DirectSoundEnumerateW/DirectSoundCaptureEnumerateW
>instead of DirectSoundEnumerate/DirectSoundCaptureEnumerate
>
>For MidiOut:
>Use MIDIOUTCAPSW instead MIDIOUTCAPS, midiOutGetDevCapsW instead 
>midiOutGetDevCaps
>
>Similar changes in other files.
>
>--alex
>
>On 07/20/2017 08:50, CharlieJiang wrote:
>> Hi Sergey,
>>
>> I finished writing the new patch according to your suggestions.
>> I wrote a new source file and a header file to handle the charset problem.
>> And I fixed this problem in all Direct devices, Ports and MIDI devices.
>> But I don't have debugging environment of MIDI devices.
>> So it will be very nice if somebody can test MIDI devices for me.
>> here's the new patch, the parent changeset is the previous patch(the direct-devices only commit):
>>
>>
>> # HG changeset patch
>> # User Charlie Jiang<cqjjjzr at 126.com>
>> # Date 1500538314 -28800
>> # Node ID c86ae2f3e1022f9b27ad6918fa342c5a4ee309c0
>> # Parent  1bfe64cffda51c00fccf48e9c0c2adb533fa7e5c
>> 8177951: Charset problem when the name of the sound device contains Chinese character
>> Summary: Fix issues in the ANSI2UTF-8 function and move it to a seperate file and fix Port Sound and MIDI Sound devices.
>> Contributed-by: Charlie Jiang <cqjjjzr at 126.com>
>>
>> diff --git a/make/lib/SoundLibraries.gmk b/make/lib/SoundLibraries.gmk
>> --- a/make/lib/SoundLibraries.gmk
>> +++ b/make/lib/SoundLibraries.gmk
>> @@ -61,6 +61,7 @@
>>        -DUSE_PLATFORM_MIDI_IN=TRUE \
>>        -DUSE_PORTS=TRUE
>>    LIBJSOUND_SRC_FILES += \
>> +      PLATFORM_API_WinOS_Charset_Util.cpp \
>>        PLATFORM_API_WinOS_MidiIn.cpp \
>>        PLATFORM_API_WinOS_MidiOut.c \
>>        PLATFORM_API_WinOS_Util.c \
>> @@ -190,6 +191,7 @@
>>        OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
>>        SRC := $(LIBJSOUND_SRC_DIRS), \
>>        INCLUDE_FILES := Utilities.c $(LIBJSOUND_DAUDIOFILES) \
>> +          PLATFORM_API_WinOS_Charset_Util.cpp \
>>            PLATFORM_API_WinOS_DirectSound.cpp, \
>>        OPTIMIZATION := LOW, \
>>        CFLAGS := $(CFLAGS_JDKLIB) \
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
>> new file mode 100644
>> --- /dev/null
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
>> @@ -0,0 +1,61 @@
>> +/*
>> + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
>> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 only, as
>> + * published by the Free Software Foundation.  Oracle designates this
>> + * particular file as subject to the "Classpath" exception as provided
>> + * by Oracle in the LICENSE file that accompanied this code.
>> + *
>> + * This code is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> + * version 2 for more details (a copy is included in the LICENSE file that
>> + * accompanied this code).
>> + *
>> + * You should have received a copy of the GNU General Public License version
>> + * 2 along with this work; if not, write to the Free Software Foundation,
>> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
>> + *
>> + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
>> + * or visit www.oracle.com if you need additional information or have any
>> + * questions.
>> + */
>> +
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>> +#include <cstring>
>> +
>> +extern "C" LPSTR ANSIToUTF8(const LPCSTR lpAnsiStr)
>> +{
>> +    // ANSI -> Unicode
>> +    DWORD dwUnicodeLen = 0;
>> +    LPWSTR lpUnicodeStr = nullptr;
>> +    dwUnicodeLen = MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, nullptr, 0);
>> +    lpUnicodeStr = new WCHAR[dwUnicodeLen];
>> +    memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
>> +    MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
>> +
>> +    // Unicode -> UTF8
>> +    LPSTR lpUTF8Str = nullptr;
>> +    DWORD dwUTF8Len = 0;
>> +    dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, nullptr, 0, nullptr, nullptr);
>> +    lpUTF8Str = new CHAR[dwUTF8Len];
>> +    memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
>> +    WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, nullptr, nullptr);
>> +    delete[] lpUnicodeStr;
>> +    return lpUTF8Str;
>> +}
>> +
>> +extern "C" void ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength) {
>> +#ifndef UNICODE
>> +    LPSTR utf8EncodedName = ANSIToUTF8(src);
>> +    strncpy(dest, utf8EncodedName, maxLength - 1);
>> +    delete[] utf8EncodedName;
>> +#else
>> +    strncpy(dest, src, maxLength - 1);
>> +#endif
>> +    dest[maxLength - 1] = '\0';
>> +}
>> +
>> \ No newline at end of file
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
>> new file mode 100644
>> --- /dev/null
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
>> @@ -0,0 +1,43 @@
>> +/*
>> + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
>> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 only, as
>> + * published by the Free Software Foundation.  Oracle designates this
>> + * particular file as subject to the "Classpath" exception as provided
>> + * by Oracle in the LICENSE file that accompanied this code.
>> + *
>> + * This code is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> + * version 2 for more details (a copy is included in the LICENSE file that
>> + * accompanied this code).
>> + *
>> + * You should have received a copy of the GNU General Public License version
>> + * 2 along with this work; if not, write to the Free Software Foundation,
>> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
>> + *
>> + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
>> + * or visit www.oracle.com if you need additional information or have any
>> + * questions.
>> + */
>> +
>> +#ifndef PLATFORM_API_WINOS_CHARSET_UTILS_H
>> +#define PLATFORM_API_WINOS_CHARSET_UTILS_H
>> +
>> +#include <windows.h>
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +LPSTR _cdecl ANSIToUTF8(const LPCSTR lpAnsiStr);
>> +
>> +void _cdecl ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
>> @@ -52,6 +52,9 @@
>>  }
>>  #endif
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #ifdef USE_DEBUG_SILENCING
>>  #define DEBUG_SILENCING0(p) TRACE0(p)
>>  #define DEBUG_SILENCING1(p1,p2) TRACE1(p1,p2)
>> @@ -86,28 +89,6 @@
>>  static UINT64 g_lastCacheRefreshTime = 0;
>>  static INT32 g_mixerCount = 0;
>>
>> -/// FIX BUG JDK-8177951: Convert ANSI encoded string to UTF-8 encoded string
>> -LPCSTR ANSIToUTF8(const LPCSTR& lpAnsiStr)
>> -{
>> -    // ANSI -> Unicode
>> -    DWORD dwAnsiLen = strlen(lpAnsiStr);
>> -    DWORD dwUnicodeLen = ::MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, NULL, 0);
>> -    LPWSTR lpUnicodeStr;
>> -    lpUnicodeStr = new WCHAR[dwUnicodeLen];
>> -    memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
>> -    MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
>> -
>> -    // Unicode -> UTF8
>> -    LPSTR lpUTF8Str;
>> -    DWORD dwUTF8Len;
>> -    dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, NULL, 0, NULL, NULL);
>> -    lpUTF8Str = new CHAR[dwUTF8Len];
>> -    memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
>> -    WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, NULL, NULL);
>> -    delete lpUnicodeStr;
>> -    return lpUTF8Str;
>> -}
>> -
>>  BOOL DS_lockCache() {
>>      /* dummy implementation for now, Java does locking */
>>      return TRUE;
>> @@ -255,13 +236,7 @@
>>
>>      INT32 cacheIndex = findCacheItemByGUID(lpGuid, g_audioDeviceCache[desc->deviceID].isSource);
>>      if (cacheIndex == desc->deviceID) {
>> -#ifndef UNICODE
>> -        LPCSTR utf8EncodedName = ANSIToUTF8(lpstrDescription);
>> -        strncpy(desc->name, utf8EncodedName, DAUDIO_STRING_LENGTH);
>> -        delete utf8EncodedName;
>> -#else
>> -        strncpy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
>> -#endif
>> +        ANSIToUTF8IfNeededAndCopy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
>>          //strncpy(desc->description, lpstrModule, DAUDIO_STRING_LENGTH);
>>          desc->maxSimulLines = -1;
>>          /* do not continue enumeration */
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
>> @@ -31,6 +31,9 @@
>>  #include "PLATFORM_API_WinOS_Util.h"
>>  }
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #if USE_PLATFORM_MIDI_IN == TRUE
>>
>>  #ifdef USE_ERROR
>> @@ -258,8 +261,7 @@
>>      INT32 err;
>>
>>      if (getMidiInCaps(deviceID, &midiInCaps, &err)) {
>> -        strncpy(name, midiInCaps.szPname, nameLength-1);
>> -        name[nameLength-1] = 0;
>> +        ANSIToUTF8IfNeededAndCopy(name, midiInCaps.szPname, nameLength);
>>          return MIDI_SUCCESS;
>>      }
>>      MIDIIN_CHECK_ERROR;
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
>> @@ -28,6 +28,9 @@
>>
>>  #include "PLATFORM_API_WinOS_Util.h"
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #if USE_PLATFORM_MIDI_OUT == TRUE
>>
>>
>> @@ -82,8 +85,7 @@
>>      INT32 err;
>>
>>      if (getMidiOutCaps(deviceID, &midiOutCaps, &err)) {
>> -        strncpy(name, midiOutCaps.szPname, nameLength-1);
>> -        name[nameLength-1] = 0;
>> +        ANSIToUTF8IfNeededAndCopy(name, midiOutCaps.szPname, nameLength);
>>          return MIDI_SUCCESS;
>>      }
>>      MIDIOUT_CHECK_ERROR;
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
>> @@ -38,6 +38,9 @@
>>  #include <mmsystem.h>
>>  #include "Ports.h"
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #if USE_PORTS == TRUE
>>
>>  typedef struct tag_PortControlID PortControlID;
>> @@ -355,8 +358,7 @@
>>  INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
>>      MIXERCAPS mixerCaps;
>>      if (mixerGetDevCaps(mixerIndex, &mixerCaps, sizeof(MIXERCAPS)) == MMSYSERR_NOERROR) {
>> -        strncpy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH-1);
>> -        description->name[PORT_STRING_LENGTH-1] = 0;
>> +        ANSIToUTF8IfNeededAndCopy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH);
>>          sprintf(description->version, "%d.%d", (mixerCaps.vDriverVersion & 0xFF00) >> 8, mixerCaps.vDriverVersion & 0xFF);
>>          strncpy(description->description, "Port Mixer", PORT_STRING_LENGTH-1);
>>          return TRUE;
>>
>>
>> ===================================================================================================
>> =================================EOF===============================================================
>> ===================================================================================================
>>
>>
>> And if you need a patch that can be directly applied to the root repo, then use this:
>>
>>
>> diff --git a/make/lib/SoundLibraries.gmk b/make/lib/SoundLibraries.gmk
>> --- a/make/lib/SoundLibraries.gmk
>> +++ b/make/lib/SoundLibraries.gmk
>> @@ -61,6 +61,7 @@
>>        -DUSE_PLATFORM_MIDI_IN=TRUE \
>>        -DUSE_PORTS=TRUE
>>    LIBJSOUND_SRC_FILES += \
>> +      PLATFORM_API_WinOS_Charset_Util.cpp \
>>        PLATFORM_API_WinOS_MidiIn.cpp \
>>        PLATFORM_API_WinOS_MidiOut.c \
>>        PLATFORM_API_WinOS_Util.c \
>> @@ -190,6 +191,7 @@
>>        OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
>>        SRC := $(LIBJSOUND_SRC_DIRS), \
>>        INCLUDE_FILES := Utilities.c $(LIBJSOUND_DAUDIOFILES) \
>> +          PLATFORM_API_WinOS_Charset_Util.cpp \
>>            PLATFORM_API_WinOS_DirectSound.cpp, \
>>        OPTIMIZATION := LOW, \
>>        CFLAGS := $(CFLAGS_JDKLIB) \
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
>> new file mode 100644
>> --- /dev/null
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.cpp
>> @@ -0,0 +1,61 @@
>> +/*
>> + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
>> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 only, as
>> + * published by the Free Software Foundation.  Oracle designates this
>> + * particular file as subject to the "Classpath" exception as provided
>> + * by Oracle in the LICENSE file that accompanied this code.
>> + *
>> + * This code is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> + * version 2 for more details (a copy is included in the LICENSE file that
>> + * accompanied this code).
>> + *
>> + * You should have received a copy of the GNU General Public License version
>> + * 2 along with this work; if not, write to the Free Software Foundation,
>> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
>> + *
>> + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
>> + * or visit www.oracle.com if you need additional information or have any
>> + * questions.
>> + */
>> +
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>> +#include <cstring>
>> +
>> +extern "C" LPSTR ANSIToUTF8(const LPCSTR lpAnsiStr)
>> +{
>> +    // ANSI -> Unicode
>> +    DWORD dwUnicodeLen = 0;
>> +    LPWSTR lpUnicodeStr = nullptr;
>> +    dwUnicodeLen = MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, nullptr, 0);
>> +    lpUnicodeStr = new WCHAR[dwUnicodeLen];
>> +    memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
>> +    MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
>> +
>> +    // Unicode -> UTF8
>> +    LPSTR lpUTF8Str = nullptr;
>> +    DWORD dwUTF8Len = 0;
>> +    dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, nullptr, 0, nullptr, nullptr);
>> +    lpUTF8Str = new CHAR[dwUTF8Len];
>> +    memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
>> +    WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, nullptr, nullptr);
>> +    delete[] lpUnicodeStr;
>> +    return lpUTF8Str;
>> +}
>> +
>> +extern "C" void ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength) {
>> +#ifndef UNICODE
>> +    LPSTR utf8EncodedName = ANSIToUTF8(src);
>> +    strncpy(dest, utf8EncodedName, maxLength - 1);
>> +    delete[] utf8EncodedName;
>> +#else
>> +    strncpy(dest, src, maxLength - 1);
>> +#endif
>> +    dest[maxLength - 1] = '\0';
>> +}
>> +
>> \ No newline at end of file
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
>> new file mode 100644
>> --- /dev/null
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Charset_Util.h
>> @@ -0,0 +1,43 @@
>> +/*
>> + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
>> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 only, as
>> + * published by the Free Software Foundation.  Oracle designates this
>> + * particular file as subject to the "Classpath" exception as provided
>> + * by Oracle in the LICENSE file that accompanied this code.
>> + *
>> + * This code is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> + * version 2 for more details (a copy is included in the LICENSE file that
>> + * accompanied this code).
>> + *
>> + * You should have received a copy of the GNU General Public License version
>> + * 2 along with this work; if not, write to the Free Software Foundation,
>> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
>> + *
>> + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
>> + * or visit www.oracle.com if you need additional information or have any
>> + * questions.
>> + */
>> +
>> +#ifndef PLATFORM_API_WINOS_CHARSET_UTILS_H
>> +#define PLATFORM_API_WINOS_CHARSET_UTILS_H
>> +
>> +#include <windows.h>
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +LPSTR _cdecl ANSIToUTF8(const LPCSTR lpAnsiStr);
>> +
>> +void _cdecl ANSIToUTF8IfNeededAndCopy(LPSTR dest, LPCSTR src, SIZE_T maxLength);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
>> @@ -52,6 +52,9 @@
>>  }
>>  #endif
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #ifdef USE_DEBUG_SILENCING
>>  #define DEBUG_SILENCING0(p) TRACE0(p)
>>  #define DEBUG_SILENCING1(p1,p2) TRACE1(p1,p2)
>> @@ -233,7 +236,7 @@
>>
>>      INT32 cacheIndex = findCacheItemByGUID(lpGuid, g_audioDeviceCache[desc->deviceID].isSource);
>>      if (cacheIndex == desc->deviceID) {
>> -        strncpy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
>> +        ANSIToUTF8IfNeededAndCopy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
>>          //strncpy(desc->description, lpstrModule, DAUDIO_STRING_LENGTH);
>>          desc->maxSimulLines = -1;
>>          /* do not continue enumeration */
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp
>> @@ -31,6 +31,9 @@
>>  #include "PLATFORM_API_WinOS_Util.h"
>>  }
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #if USE_PLATFORM_MIDI_IN == TRUE
>>
>>  #ifdef USE_ERROR
>> @@ -258,8 +261,7 @@
>>      INT32 err;
>>
>>      if (getMidiInCaps(deviceID, &midiInCaps, &err)) {
>> -        strncpy(name, midiInCaps.szPname, nameLength-1);
>> -        name[nameLength-1] = 0;
>> +        ANSIToUTF8IfNeededAndCopy(name, midiInCaps.szPname, nameLength);
>>          return MIDI_SUCCESS;
>>      }
>>      MIDIIN_CHECK_ERROR;
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c
>> @@ -28,6 +28,9 @@
>>
>>  #include "PLATFORM_API_WinOS_Util.h"
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #if USE_PLATFORM_MIDI_OUT == TRUE
>>
>>
>> @@ -82,8 +85,7 @@
>>      INT32 err;
>>
>>      if (getMidiOutCaps(deviceID, &midiOutCaps, &err)) {
>> -        strncpy(name, midiOutCaps.szPname, nameLength-1);
>> -        name[nameLength-1] = 0;
>> +        ANSIToUTF8IfNeededAndCopy(name, midiOutCaps.szPname, nameLength);
>>          return MIDI_SUCCESS;
>>      }
>>      MIDIOUT_CHECK_ERROR;
>> diff --git a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
>> --- a/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
>> +++ b/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Ports.c
>> @@ -38,6 +38,9 @@
>>  #include <mmsystem.h>
>>  #include "Ports.h"
>>
>> +/* include to prevent charset problem */
>> +#include "PLATFORM_API_WinOS_Charset_Util.h"
>> +
>>  #if USE_PORTS == TRUE
>>
>>  typedef struct tag_PortControlID PortControlID;
>> @@ -355,8 +358,7 @@
>>  INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
>>      MIXERCAPS mixerCaps;
>>      if (mixerGetDevCaps(mixerIndex, &mixerCaps, sizeof(MIXERCAPS)) == MMSYSERR_NOERROR) {
>> -        strncpy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH-1);
>> -        description->name[PORT_STRING_LENGTH-1] = 0;
>> +        ANSIToUTF8IfNeededAndCopy(description->name, mixerCaps.szPname, PORT_STRING_LENGTH);
>>          sprintf(description->version, "%d.%d", (mixerCaps.vDriverVersion & 0xFF00) >> 8, mixerCaps.vDriverVersion & 0xFF);
>>          strncpy(description->description, "Port Mixer", PORT_STRING_LENGTH-1);
>>          return TRUE;
>>
>>
>> About the issue of the OCA, because actually I won't often push code to the OpenJDK repo,
>> so I think it's unnecessary to join the OCB now, and the steps to join it is pretty complex.
>>
>> Cheers,
>> Charlie Jiang
>> 2017-7-20
>>
>> PS: a picture of the effect of the new patch:
>> http://imgur.com/a/SjlAU
>>
>> ===================================================================================================
>> =================================EOF===============================================================
>> ===================================================================================================
>>
>>
>> At 2017-07-18 08:38:15, "Sergey Bylokhov" <sergey.bylokhov at oracle.com> wrote:
>>
>> p { margin: 0; }
>> Hello.
>> I uploaded the current patch to cr.openjdk:
>> http://cr.openjdk.java.net/~serb/8177951/webrev.00
>>
>> I have tested the patch and here is my observation:
>>  - The patch works for direct devices, but it looks like the same bug exists in Ports(also reproduced by your testcase), did you have a chance to look into this issue as well?
>>  - jdk uses "warning-as-error" policy during the build, so currently there is a build failure, because of this warning:
>>         PLATFORM_API_WinOS_DirectSound.cpp(93) : warning C4267: 'initializing' : conversion from 'size_t' to 'DWORD', possible loss of data
>>  - Note that the memory which is allocated by "new[]" should be deallocated by the "delete[]", but current fix use simple "delete".
>>  - Can you please sign and submit the OCA[1], which will allow you to contribute to the openjdk?
>>
>> [1] http://www.oracle.com/technetwork/community/oca-486395.html
>>
>>
>> ----- cqjjjzr at 126.com wrote:
>>
>>>
>>>
>> Hello,
>> Please review this bug report: https://bugs.openjdk.java.net/browse/JDK-8177951
>>
>>>
>> A brief description of the issue:
>> In non-English Windows, the DirectAudioDeviceProvider can't work properly, AudioSystem.getMixerInfo()[0].getName() (or any other index, as long as the name of mixer contains non-ASCII characters)will return a corrupted string (all non-ASCII chars become messy codes).
>> The main reason is in native codes, we get a string in ANSI(platform-dependent) charset. But in the code the string is just processed as a UTF-8 string. So the JVM encodes ANSI string by UTF-8 encoding.
>>
>>>
>> Detailed description:
>> The performace of the bug is contained in the link above, I'll talk about the reason of the issue. All research below are based on OpenJDK 9, but I think OpenJDK 8 is also applicable.
>>
>>>
>> In jdk/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp, Function DS_GetDesc_Enum, Line 236, the name of the device is gotten(called by function DirectSoundDeviceEnumerate) from the OS, in ANSI charset, in a LPCSTR. And you just copy the ANSI encoded string to the DirectAudioDeviceDescription struct. So let's look at the jdk/src/java.desktop/share/native/libjsound/DirectAudioDeviceProvider.c, Function getDirectAudioDeviceDescription and Java_com_sun_media_sound_DirectAudioDeviceProvider_nNewDirectAudioDeviceInfo, Line 48 and 98, you called NewStringUTF function with a ANSI encoded string. So we got a UTF-8 encoded ANSI string. But obviously we need a UTF-8 encoded Unicode String.
>>
>>>
>> I wrote to Oracle but they can't reproduce the issue, so I went on fixing the bug by myself. I wrote a function to convert ANSI string to UTF-8 encoded Unicode string.
>>
>>>
>> And I found a problem: In Multi-Byte compiling mode, DirectSoundDeviceEnumerate will call DirectSoundDeviceEnumerateA and it will present a ANSI string as the argument, but in Unicode mode, DirectSoundDeviceEnumerate calls DirectSoundDeviceEnumerateW which presents a UTF-8 encoded Unicode string! So I think it's necessary to check if the compiler is in Unicode mode(by checking UNICODE macro), and only convert the string when it's in Multi-Byte mode.
>>
>>>
>> But, I don't have the debugging environment, I have problem configuring the compiler of OpenJDK. LINK : error LNK2001: unresolved external symbol _mainCRTStartup when executing ./configure script. So I can't test the validness of the patch. I'll be grateful if someone can help solve the configuring problem or test the patch for me. Even if you can compile the JDK with the patch is OK.
>> If you'd like to test the patch, you can test it with the first device from DirectSoundDeviceEnumerate, 'Primary Sound Driver'. Maybe you don't have Chinese font, I'll attach a picture to the correct output.
>>
>>>
>> The patch is below and attached with the E-Mail. It's applicable for OpenJDK9, maybe 8 if you change it.
>> https://imgur.com/a/6kgeU
>> The code in the picture is just for generate a output, in the Unicode mode, so it's not applicable for JDK.
>>
>>>
>>
>> *** old/jdk/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp	2017-06-21 03:57:42.000000000 +0800
>> --- new/jdk/src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp	2017-06-24 16:26:57.232247800 +0800
>> ***************
>> *** 86,91 ****
>> --- 86,113 ----
>>   static UINT64 g_lastCacheRefreshTime = 0;
>>   static INT32 g_mixerCount = 0;
>>
>> + /// FIX BUG JDK-8177951: Convert ANSI encoded string to UTF-8 encoded string
>> + LPCSTR ANSIToUTF8(const LPCSTR& lpAnsiStr)
>> + {
>> +     // ANSI -> Unicode
>> +     DWORD dwAnsiLen = strlen(lpAnsiStr);
>> +     DWORD dwUnicodeLen = ::MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, NULL, 0);
>> +     LPWSTR lpUnicodeStr;
>> +     lpUnicodeStr = new WCHAR[dwUnicodeLen];
>> +     memset(lpUnicodeStr, 0, (dwUnicodeLen) * sizeof(WCHAR));
>> +     MultiByteToWideChar(CP_ACP, 0, lpAnsiStr, -1, lpUnicodeStr, dwUnicodeLen);
>> +
>> +     // Unicode -> UTF8
>> +     LPSTR lpUTF8Str;
>> +     DWORD dwUTF8Len;
>> +     dwUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, NULL, 0, NULL, NULL);
>> +     lpUTF8Str = new CHAR[dwUTF8Len];
>> +     memset(lpUTF8Str, 0, sizeof(CHAR) * (dwUTF8Len));
>> +     WideCharToMultiByte(CP_UTF8, 0, lpUnicodeStr, -1, lpUTF8Str, dwUTF8Len, NULL, NULL);
>> +     delete lpUnicodeStr;
>> +     return lpUTF8Str;
>> + }
>> +
>>   BOOL DS_lockCache() {
>>       /* dummy implementation for now, Java does locking */
>>       return TRUE;
>> ***************
>> *** 233,239 ****
>> --- 255,267 ----
>>
>>       INT32 cacheIndex = findCacheItemByGUID(lpGuid, g_audioDeviceCache[desc->deviceID].isSource);
>>       if (cacheIndex == desc->deviceID) {
>> + #ifndef UNICODE
>> +         LPCSTR utf8EncodedName = ANSIToUTF8(lpstrDescription);
>> +         strncpy(desc->name, utf8EncodedName, DAUDIO_STRING_LENGTH);
>> +         delete utf8EncodedName;
>> + #else
>>           strncpy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
>> + #endif
>>           //strncpy(desc->description, lpstrModule, DAUDIO_STRING_LENGTH);
>>           desc->maxSimulLines = -1;
>>           /* do not continue enumeration */
>>
>>>
>>
>>>
>> Cheers,
>> Charlie Jiang
>>>
>>>
>>
>>


More information about the sound-dev mailing list