From a770935404928e564362c61b5b1a9a7831a3114e Mon Sep 17 00:00:00 2001 From: hedgecrw85 Date: Sun, 1 Apr 2018 15:27:10 -0500 Subject: [PATCH] Make Unicode-compliant --- src/main/c/Windows/Makefile | 2 +- src/main/c/Windows/SerialPort_Windows.c | 133 ++++++++++++++------ src/main/c/Windows/WindowsHelperFunctions.c | 24 ++-- src/main/c/Windows/WindowsHelperFunctions.h | 8 +- 4 files changed, 109 insertions(+), 58 deletions(-) diff --git a/src/main/c/Windows/Makefile b/src/main/c/Windows/Makefile index 21bf8d7..3dd7962 100644 --- a/src/main/c/Windows/Makefile +++ b/src/main/c/Windows/Makefile @@ -4,7 +4,7 @@ LINK = link CFLAGS = /c /O2 /GF /GL /MT /EHsc /fp:precise /J /nologo /TP LDFLAGS = /DLL /LTCG /NOASSEMBLY /NOLOGO INCLUDES = /I"$(JDK_HOME)/include" /I"$(JDK_HOME)/include/win32" -LIBRARIES = Advapi32.lib +LIBRARIES = Advapi32.lib SetupAPI.lib DELETE = @del /q /f RMDIR = @rd /q /s MKDIR = @md diff --git a/src/main/c/Windows/SerialPort_Windows.c b/src/main/c/Windows/SerialPort_Windows.c index 4495bf0..8894f49 100644 --- a/src/main/c/Windows/SerialPort_Windows.c +++ b/src/main/c/Windows/SerialPort_Windows.c @@ -64,15 +64,15 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP DWORD subKeyLength1, subKeyLength2, subKeyLength3, friendlyNameLength; // Enumerate serial ports on machine - charTupleVector serialCommPorts = { (char**)malloc(1), (char**)malloc(1), (char**)malloc(1), 0 }; - if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &keyHandle1) == ERROR_SUCCESS) && - (RegQueryInfoKey(keyHandle1, NULL, NULL, NULL, NULL, NULL, NULL, &numValues, &maxValueLength, &maxComPortLength, NULL, NULL) == ERROR_SUCCESS)) + charTupleVector serialCommPorts = { (wchar_t**)malloc(sizeof(wchar_t*)), (wchar_t**)malloc(sizeof(wchar_t*)), (wchar_t**)malloc(sizeof(wchar_t*)), 0 }; + if ((RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &keyHandle1) == ERROR_SUCCESS) && + (RegQueryInfoKeyW(keyHandle1, NULL, NULL, NULL, NULL, NULL, NULL, &numValues, &maxValueLength, &maxComPortLength, NULL, NULL) == ERROR_SUCCESS)) { // Allocate memory ++maxValueLength; ++maxComPortLength; - CHAR *valueName = (CHAR*)malloc(maxValueLength); - CHAR *comPort = (CHAR*)malloc(maxComPortLength); + WCHAR *valueName = (WCHAR*)malloc(maxValueLength*sizeof(WCHAR)); + WCHAR *comPort = (WCHAR*)malloc(maxComPortLength*sizeof(WCHAR)); // Iterate through all COM ports for (DWORD i = 0; i < numValues; ++i) @@ -80,13 +80,13 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP // Get serial port name and COM value valueLength = maxValueLength; comPortLength = maxComPortLength; - memset(valueName, 0, valueLength); - memset(comPort, 0, comPortLength); - if ((RegEnumValue(keyHandle1, i, valueName, &valueLength, NULL, &keyType, (BYTE*)comPort, &comPortLength) == ERROR_SUCCESS) && (keyType == REG_SZ)) + memset(valueName, 0, valueLength*sizeof(WCHAR)); + memset(comPort, 0, comPortLength*sizeof(WCHAR)); + if ((RegEnumValueW(keyHandle1, i, valueName, &valueLength, NULL, &keyType, (BYTE*)comPort, &comPortLength) == ERROR_SUCCESS) && (keyType == REG_SZ)) { // Set port name and description - char* comPortString = (comPort[0] == '\\') ? (strrchr(comPort, '\\') + 1) : comPort; - char* descriptionString = strrchr(valueName, '\\') ? (strrchr(valueName, '\\') + 1) : valueName; + wchar_t* comPortString = (comPort[0] == L'\\') ? (wcsrchr(comPort, L'\\') + 1) : comPort; + wchar_t* descriptionString = wcsrchr(valueName, L'\\') ? (wcsrchr(valueName, L'\\') + 1) : valueName; // Add new SerialComm object to vector push_back(&serialCommPorts, comPortString, descriptionString, descriptionString); @@ -100,72 +100,72 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP RegCloseKey(keyHandle1); // Enumerate all devices on machine - if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum", 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle1) == ERROR_SUCCESS) && - (RegQueryInfoKey(keyHandle1, NULL, NULL, NULL, &numSubKeys1, &maxSubKeyLength1, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)) + if ((RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum", 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle1) == ERROR_SUCCESS) && + (RegQueryInfoKeyW(keyHandle1, NULL, NULL, NULL, &numSubKeys1, &maxSubKeyLength1, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)) { // Allocate memory ++maxSubKeyLength1; - CHAR *subKeyName1 = (CHAR*)malloc(maxSubKeyLength1); + WCHAR *subKeyName1 = (WCHAR*)malloc(maxSubKeyLength1*sizeof(WCHAR)); // Enumerate sub-keys for (DWORD i1 = 0; i1 < numSubKeys1; ++i1) { subKeyLength1 = maxSubKeyLength1; - if ((RegEnumKeyEx(keyHandle1, i1, subKeyName1, &subKeyLength1, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && - (RegOpenKeyEx(keyHandle1, subKeyName1, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle2) == ERROR_SUCCESS) && - (RegQueryInfoKey(keyHandle2, NULL, NULL, NULL, &numSubKeys2, &maxSubKeyLength2, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)) + if ((RegEnumKeyExW(keyHandle1, i1, subKeyName1, &subKeyLength1, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && + (RegOpenKeyExW(keyHandle1, subKeyName1, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle2) == ERROR_SUCCESS) && + (RegQueryInfoKeyW(keyHandle2, NULL, NULL, NULL, &numSubKeys2, &maxSubKeyLength2, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)) { // Allocate memory ++maxSubKeyLength2; - CHAR *subKeyName2 = (CHAR*)malloc(maxSubKeyLength2); + WCHAR *subKeyName2 = (WCHAR*)malloc(maxSubKeyLength2*sizeof(WCHAR)); // Enumerate sub-keys for (DWORD i2 = 0; i2 < numSubKeys2; ++i2) { subKeyLength2 = maxSubKeyLength2; - if ((RegEnumKeyEx(keyHandle2, i2, subKeyName2, &subKeyLength2, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && - (RegOpenKeyEx(keyHandle2, subKeyName2, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle3) == ERROR_SUCCESS) && - (RegQueryInfoKey(keyHandle3, NULL, NULL, NULL, &numSubKeys3, &maxSubKeyLength3, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)) + if ((RegEnumKeyExW(keyHandle2, i2, subKeyName2, &subKeyLength2, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && + (RegOpenKeyExW(keyHandle2, subKeyName2, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle3) == ERROR_SUCCESS) && + (RegQueryInfoKeyW(keyHandle3, NULL, NULL, NULL, &numSubKeys3, &maxSubKeyLength3, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)) { // Allocate memory ++maxSubKeyLength3; - CHAR *subKeyName3 = (CHAR*)malloc(maxSubKeyLength3); + WCHAR *subKeyName3 = (WCHAR*)malloc(maxSubKeyLength3*sizeof(WCHAR)); // Enumerate sub-keys for (DWORD i3 = 0; i3 < numSubKeys3; ++i3) { subKeyLength3 = maxSubKeyLength3; - if ((RegEnumKeyEx(keyHandle3, i3, subKeyName3, &subKeyLength3, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && - (RegOpenKeyEx(keyHandle3, subKeyName3, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle4) == ERROR_SUCCESS) && - (RegQueryInfoKey(keyHandle4, NULL, NULL, NULL, NULL, NULL, NULL, &numValues, NULL, &valueLength, NULL, NULL) == ERROR_SUCCESS)) + if ((RegEnumKeyExW(keyHandle3, i3, subKeyName3, &subKeyLength3, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && + (RegOpenKeyExW(keyHandle3, subKeyName3, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &keyHandle4) == ERROR_SUCCESS) && + (RegQueryInfoKeyW(keyHandle4, NULL, NULL, NULL, NULL, NULL, NULL, &numValues, NULL, &valueLength, NULL, NULL) == ERROR_SUCCESS)) { // Allocate memory friendlyNameLength = valueLength + 1; - CHAR *friendlyName = (CHAR*)malloc(friendlyNameLength); + WCHAR *friendlyName = (WCHAR*)malloc(friendlyNameLength*sizeof(WCHAR)); - if ((RegOpenKeyEx(keyHandle4, "Device Parameters", 0, KEY_QUERY_VALUE, &keyHandle5) == ERROR_SUCCESS) && - (RegQueryInfoKey(keyHandle5, NULL, NULL, NULL, NULL, NULL, NULL, &numValues, NULL, &valueLength, NULL, NULL) == ERROR_SUCCESS)) + if ((RegOpenKeyExW(keyHandle4, L"Device Parameters", 0, KEY_QUERY_VALUE, &keyHandle5) == ERROR_SUCCESS) && + (RegQueryInfoKeyW(keyHandle5, NULL, NULL, NULL, NULL, NULL, NULL, &numValues, NULL, &valueLength, NULL, NULL) == ERROR_SUCCESS)) { // Allocate memory comPortLength = valueLength + 1; - CHAR *comPort = (CHAR*)malloc(comPortLength); + WCHAR *comPort = (WCHAR*)malloc(comPortLength*sizeof(WCHAR)); // Attempt to get COM value and friendly port name - if ((RegQueryValueEx(keyHandle5, "PortName", NULL, &keyType, (BYTE*)comPort, &comPortLength) == ERROR_SUCCESS) && (keyType == REG_SZ) && - (RegQueryValueEx(keyHandle4, "FriendlyName", NULL, &keyType, (BYTE*)friendlyName, &friendlyNameLength) == ERROR_SUCCESS) && (keyType == REG_SZ)) + if ((RegQueryValueExW(keyHandle5, L"PortName", NULL, &keyType, (BYTE*)comPort, &comPortLength) == ERROR_SUCCESS) && (keyType == REG_SZ) && + (RegQueryValueExW(keyHandle4, L"FriendlyName", NULL, &keyType, (BYTE*)friendlyName, &friendlyNameLength) == ERROR_SUCCESS) && (keyType == REG_SZ)) { // Set port name and description - char* comPortString = (comPort[0] == '\\') ? (strrchr(comPort, '\\') + 1) : comPort; - char* descriptionString = friendlyName; + wchar_t* comPortString = (comPort[0] == L'\\') ? (wcsrchr(comPort, L'\\') + 1) : comPort; + wchar_t* descriptionString = friendlyName; // Update friendly name if COM port is actually connected and present in the port list int i; for (i = 0; i < serialCommPorts.length; ++i) - if (strcmp(serialCommPorts.first[i], comPortString) == 0) + if (wcscmp(serialCommPorts.first[i], comPortString) == 0) { free(serialCommPorts.second[i]); - serialCommPorts.second[i] = (char*)malloc(strlen(descriptionString)+1); - strcpy(serialCommPorts.second[i], descriptionString); + serialCommPorts.second[i] = (wchar_t*)malloc((wcslen(descriptionString)+1)*sizeof(wchar_t)); + wcscpy(serialCommPorts.second[i], descriptionString); break; } } @@ -200,19 +200,70 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP free(subKeyName1); } + // Attempt to locate any device-specified port descriptions + HDEVINFO devList = SetupDiGetClassDevsW(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT); + if (devList != INVALID_HANDLE_VALUE) + { + // Iterate through all USB-connected devices + DWORD devInterfaceIndex = 0; + DEVPROPTYPE devInfoPropType; + SP_DEVINFO_DATA devInfoData; + devInfoData.cbSize = sizeof(devInfoData); + WCHAR comPort[128]; + while (SetupDiEnumDeviceInfo(devList, devInterfaceIndex++, &devInfoData)) + { + // Fetch the corresponding COM port for this device + wchar_t* comPortString = NULL; + comPortLength = sizeof(comPort) / sizeof(WCHAR); + keyHandle5 = SetupDiOpenDevRegKey(devList, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); + if ((keyHandle5 != INVALID_HANDLE_VALUE) && (RegQueryValueExW(keyHandle5, L"PortName", NULL, &keyType, (BYTE*)comPort, &comPortLength) == ERROR_SUCCESS) && (keyType == REG_SZ)) + comPortString = (comPort[0] == L'\\') ? (wcsrchr(comPort, L'\\') + 1) : comPort; + if (keyHandle5 != INVALID_HANDLE_VALUE) + RegCloseKey(keyHandle5); + + // Fetch the length of the "Bus-Reported Device Description" + if (comPortString && !SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &devInfoPropType, NULL, 0, &valueLength, 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) + { + // Allocate memory + ++valueLength; + WCHAR *portDescription = (WCHAR*)malloc(valueLength); + + // Retrieve the "Bus-Reported Device Description" + if (SetupDiGetDevicePropertyW(devList, &devInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &devInfoPropType, (BYTE*)portDescription, valueLength, NULL, 0)) + { + // Update port description if COM port is actually connected and present in the port list + int i; + for (i = 0; i < serialCommPorts.length; ++i) + if (wcscmp(serialCommPorts.first[i], comPortString) == 0) + { + free(serialCommPorts.third[i]); + serialCommPorts.third[i] = (wchar_t*)malloc((wcslen(portDescription)+1)*sizeof(wchar_t)); + wcscpy(serialCommPorts.third[i], portDescription); + break; + } + } + + // Clean up memory + free(portDescription); + } + devInfoData.cbSize = sizeof(devInfoData); + } + SetupDiDestroyDeviceInfoList(devList); + } + // Get relevant SerialComm methods and fill in com port array jobjectArray arrayObject = env->NewObjectArray(serialCommPorts.length, serialCommClass, 0); - char systemPortName[128]; + wchar_t systemPortName[128]; int i; for (i = 0; i < serialCommPorts.length; ++i) { // Create new SerialComm object containing the enumerated values jobject serialCommObject = env->NewObject(serialCommClass, serialCommConstructor); - strcpy(systemPortName, "\\\\.\\"); - strcat(systemPortName, serialCommPorts.first[i]); - env->SetObjectField(serialCommObject, comPortField, env->NewStringUTF(systemPortName)); - env->SetObjectField(serialCommObject, friendlyNameField, env->NewStringUTF(serialCommPorts.second[i])); - env->SetObjectField(serialCommObject, portDescriptionField, env->NewStringUTF(serialCommPorts.third[i])); + wcscpy(systemPortName, L"\\\\.\\"); + wcscat(systemPortName, serialCommPorts.first[i]); + env->SetObjectField(serialCommObject, comPortField, env->NewString((jchar*)systemPortName, wcslen(systemPortName))); + env->SetObjectField(serialCommObject, friendlyNameField, env->NewString((jchar*)serialCommPorts.second[i], wcslen(serialCommPorts.second[i]))); + env->SetObjectField(serialCommObject, portDescriptionField, env->NewString((jchar*)serialCommPorts.third[i], wcslen(serialCommPorts.third[i]))); free(serialCommPorts.first[i]); free(serialCommPorts.second[i]); free(serialCommPorts.third[i]); diff --git a/src/main/c/Windows/WindowsHelperFunctions.c b/src/main/c/Windows/WindowsHelperFunctions.c index e5277f3..9524cde 100644 --- a/src/main/c/Windows/WindowsHelperFunctions.c +++ b/src/main/c/Windows/WindowsHelperFunctions.c @@ -28,34 +28,34 @@ #include #include "WindowsHelperFunctions.h" -void push_back(struct charTupleVector* vector, const char* firstString, const char* secondString, const char* thirdString) +void push_back(struct charTupleVector* vector, const wchar_t* firstString, const wchar_t* secondString, const wchar_t* thirdString) { // Allocate memory for new string storage vector->length++; - char** newMemory = (char**)realloc(vector->first, vector->length*sizeof(char*)); + wchar_t** newMemory = (wchar_t**)realloc(vector->first, vector->length*sizeof(wchar_t*)); if (newMemory) vector->first = newMemory; - newMemory = (char**)realloc(vector->second, vector->length*sizeof(char*)); + newMemory = (wchar_t**)realloc(vector->second, vector->length*sizeof(wchar_t*)); if (newMemory) vector->second = newMemory; - newMemory = (char**)realloc(vector->third, vector->length*sizeof(char*)); + newMemory = (wchar_t**)realloc(vector->third, vector->length*sizeof(wchar_t*)); if (newMemory) vector->third = newMemory; // Store new strings - vector->first[vector->length-1] = (char*)malloc(strlen(firstString)+1); - vector->second[vector->length-1] = (char*)malloc(strlen(secondString)+1); - vector->third[vector->length-1] = (char*)malloc(strlen(thirdString)+1); - strcpy(vector->first[vector->length-1], firstString); - strcpy(vector->second[vector->length-1], secondString); - strcpy(vector->third[vector->length-1], thirdString); + vector->first[vector->length-1] = (wchar_t*)malloc((wcslen(firstString)+1)*sizeof(wchar_t)); + vector->second[vector->length-1] = (wchar_t*)malloc((wcslen(secondString)+1)*sizeof(wchar_t)); + vector->third[vector->length-1] = (wchar_t*)malloc((wcslen(thirdString)+1)*sizeof(wchar_t)); + wcscpy(vector->first[vector->length-1], firstString); + wcscpy(vector->second[vector->length-1], secondString); + wcscpy(vector->third[vector->length-1], thirdString); } -char keyExists(struct charTupleVector* vector, const char* key) +char keyExists(struct charTupleVector* vector, const wchar_t* key) { size_t i; for (i = 0; i < vector->length; ++i) - if (strcmp(key, vector->first[i]) == 0) + if (wcscmp(key, vector->first[i]) == 0) return 1; return 0; } diff --git a/src/main/c/Windows/WindowsHelperFunctions.h b/src/main/c/Windows/WindowsHelperFunctions.h index 476e0a6..0ae2099 100644 --- a/src/main/c/Windows/WindowsHelperFunctions.h +++ b/src/main/c/Windows/WindowsHelperFunctions.h @@ -2,7 +2,7 @@ * WindowsHelperFunctions.h * * Created on: May 05, 2015 - * Last Updated on: Mar 25, 2016 + * Last Updated on: Apr 01, 2018 * Author: Will Hedgecock * * Copyright (C) 2012-2018 Fazecast, Inc. @@ -28,10 +28,10 @@ typedef struct charTupleVector { - char **first, **second, **third; + wchar_t **first, **second, **third; size_t length; } charTupleVector; -void push_back(struct charTupleVector* vector, const char* firstString, const char* secondString, const char* thirdString); -char keyExists(struct charTupleVector* vector, const char* key); +void push_back(struct charTupleVector* vector, const wchar_t* firstString, const wchar_t* secondString, const wchar_t* thirdString); +char keyExists(struct charTupleVector* vector, const wchar_t* key); #endif // #ifndef __WINDOWS_HELPER_FUNCTIONS_HEADER_H__