Skip to content

Commit 123b6d7

Browse files
refactor(win32): force CP_UTF8 to get rid of all wchar use except CommandLineToArgvW
See https://learn.microsoft.com/en-us/windows/apps/design/globalizing/use-utf8-code-page But Windows doesn't provide CommandLineToArgvA() because in non-Unicode codepage environment, the encoding conversion is lossy and it may case security issue, so they said: > To avoid this problem, use the GetCommandLineW function to receive the > Unicode command line, or use an application manifest (on Windows Version 1903 > or later) to set UTF-8 as the process code page. > https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinea#security-remarks So Windows seems provide two solutions: one for legacy encoding, another for modern Unicode encoding. It's great, right? No!!! Windows actually only provide ONE solution! They never provide CommandLineToArgvA() at all. So altrought I can get UTF-8 version arguments from GetCommandLineA() but I can convert it into argv[] with UTF-8 encoding. I must pass it into CommandLineToArgvW() to get UTF-16LE version argv[], and convert it into UTF-8 with a annoying loop and WideCharToMultiByte(). It's crazy!!! Signed-off-by: Coelacanthus <uwu@coelacanthus.name>
1 parent 22dcc49 commit 123b6d7

3 files changed

Lines changed: 22 additions & 21 deletions

File tree

driver/apdu/at_win32.c

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,40 +35,35 @@ static void enumerate_com_ports(cJSON *data) {
3535
SP_DEVINFO_DATA devInfoData;
3636
DWORD i;
3737

38-
hDevInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_PORTS, 0, 0, DIGCF_PRESENT);
38+
hDevInfo = SetupDiGetClassDevsA(&GUID_DEVCLASS_PORTS, 0, 0, DIGCF_PRESENT);
3939
if (hDevInfo == INVALID_HANDLE_VALUE)
4040
return;
4141

4242
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
4343
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData); i++) {
44-
wchar_t portName[256] = {0};
45-
wchar_t friendlyName[256] = {0};
46-
char portNameMB[256] = {0};
47-
char friendlyNameMB[256] = {0};
44+
char portName[256] = {0};
45+
char friendlyName[256] = {0};
4846
DWORD size = sizeof(portName);
4947

5048
HKEY hKey = SetupDiOpenDevRegKey(hDevInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
5149
if (hKey != INVALID_HANDLE_VALUE) {
5250
DWORD type;
53-
if (RegQueryValueExW(hKey, L"PortName", NULL, &type, (LPBYTE)portName, &size) != ERROR_SUCCESS
51+
if (RegQueryValueExA(hKey, "PortName", NULL, &type, (LPBYTE)portName, &size) != ERROR_SUCCESS
5452
|| type != REG_SZ) {
5553
portName[0] = L'\0';
5654
}
5755
}
5856

59-
if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)friendlyName,
57+
if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)friendlyName,
6058
sizeof(friendlyName), NULL)) {
6159
friendlyName[0] = L'\0';
6260
}
6361

64-
WideCharToMultiByte(CP_UTF8, 0, portName, -1, portNameMB, sizeof(portNameMB), NULL, NULL);
65-
WideCharToMultiByte(CP_UTF8, 0, friendlyName, -1, friendlyNameMB, sizeof(friendlyNameMB), NULL, NULL);
66-
67-
if (starts_with(portNameMB, "COM")) {
62+
if (starts_with(portName, "COM")) {
6863
cJSON *item = cJSON_CreateObject();
6964
if (item) {
70-
cJSON_AddStringToObject(item, "env", portNameMB);
71-
cJSON_AddStringToObject(item, "name", friendlyNameMB[0] ? friendlyNameMB : portNameMB);
65+
cJSON_AddStringToObject(item, "env", portName);
66+
cJSON_AddStringToObject(item, "name", friendlyName[0] ? friendlyName : portName);
7267
cJSON_AddItemToArray(data, item);
7368
} else {
7469
cJSON_Delete(item);
@@ -171,16 +166,13 @@ static int apdu_interface_connect(struct euicc_ctx *ctx) {
171166

172167
logic_channel = 0;
173168

174-
char dev_ascii[64];
175-
snprintf(dev_ascii, sizeof(dev_ascii), "\\\\.\\%s", device);
176-
177-
wchar_t devname[64];
178-
mbstowcs(devname, dev_ascii, sizeof(devname) / sizeof(wchar_t));
169+
char devname[64];
170+
snprintf(devname, sizeof(devname), "\\\\.\\%s", device);
179171

180-
hComm = CreateFileW(devname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
172+
hComm = CreateFile(devname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
181173

182174
if (hComm == INVALID_HANDLE_VALUE) {
183-
fprintf(stderr, "Failed to open device: %s, error: %lu\n", dev_ascii, GetLastError());
175+
fprintf(stderr, "Failed to open device: %s, error: %lu\n", devname, GetLastError());
184176
return -1;
185177
}
186178

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/applet/chip DIR_LPAC_SRCS)
1111
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/applet/notification DIR_LPAC_SRCS)
1212
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/applet/profile DIR_LPAC_SRCS)
1313

14-
add_executable(lpac ${DIR_LPAC_SRCS})
14+
add_executable(lpac ${DIR_LPAC_SRCS} lpac.manifest)
1515
target_link_libraries(lpac euicc-drivers lpac-utils)
1616
target_include_directories(lpac PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
1717

src/lpac.manifest

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
3+
<assemblyIdentity type="win32" name="me.estk.lpac" version="6.0.0.0"/>
4+
<application>
5+
<windowsSettings>
6+
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
7+
</windowsSettings>
8+
</application>
9+
</assembly>

0 commit comments

Comments
 (0)