summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Müller <robert.mueller@uni-siegen.de>2021-11-22 23:25:51 +0100
committerRobert Müller <robert.mueller@uni-siegen.de>2021-11-28 10:48:55 +0100
commit4f28113abd56ccb47c432078948b402cd31fe0ab (patch)
tree4458b3bc8e266a15ce121f3eb057ba938d1286c2
parentbe2d79b7614a502dc8334026f3f0bb624d8fd22c (diff)
fix command line arguments with unicode on windows
Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
-rw-r--r--src/base/system.c45
-rw-r--r--src/base/system.h26
-rw-r--r--src/engine/client/client.cpp2
-rw-r--r--src/engine/server/server.cpp2
-rw-r--r--src/mastersrv/mastersrv.cpp17
-rw-r--r--src/test/test.cpp9
-rw-r--r--src/tools/crapnet.cpp2
-rw-r--r--src/tools/fake_server.cpp5
-rw-r--r--src/tools/map_resave.cpp40
-rw-r--r--src/tools/map_version.cpp5
-rw-r--r--src/tools/packetgen.cpp2
-rw-r--r--src/versionsrv/versionsrv.cpp7
12 files changed, 124 insertions, 38 deletions
diff --git a/src/base/system.c b/src/base/system.c
index ad128b137..091a11034 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -43,6 +43,7 @@
#include <process.h>
#include <wincrypt.h>
#include <share.h>
+ #include <shellapi.h>
#else
#error NOT IMPLEMENTED
#endif
@@ -2858,6 +2859,50 @@ int pid()
#endif
}
+void cmdline_fix(int *argc, const char ***argv)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+ int wide_argc = 0;
+ WCHAR **wide_argv = CommandLineToArgvW(GetCommandLineW(), &wide_argc);
+ dbg_assert(wide_argv != NULL, "CommandLineToArgvW failure");
+
+ int total_size = 0;
+
+ for(int i = 0; i < wide_argc; i++)
+ {
+ int size = WideCharToMultiByte(CP_UTF8, 0, wide_argv[i], -1, NULL, 0, NULL, NULL);
+ dbg_assert(size != 0, "WideCharToMultiByte failure");
+ total_size += size;
+ }
+
+ char **new_argv = (char **)malloc((wide_argc + 1) * sizeof(*new_argv));
+ new_argv[0] = (char *)malloc(total_size);
+ mem_zero(new_argv[0], total_size);
+
+ int remaining_size = total_size;
+ for(int i = 0; i < wide_argc; i++)
+ {
+ int size = WideCharToMultiByte(CP_UTF8, 0, wide_argv[i], -1, new_argv[i], remaining_size, NULL, NULL);
+ dbg_assert(size != 0, "WideCharToMultiByte failure");
+
+ remaining_size -= size;
+ new_argv[i + 1] = new_argv[i] + size;
+ }
+
+ new_argv[wide_argc] = 0;
+ *argc = wide_argc;
+ *argv = (const char **)new_argv;
+#endif
+}
+
+void cmdline_free(int argc, const char **argv)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+ free((void *)*argv);
+ free((char **)argv);
+#endif
+}
+
unsigned bytes_be_to_uint(const unsigned char *bytes)
{
return (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<<8) | bytes[3];
diff --git a/src/base/system.h b/src/base/system.h
index 7b6a224a8..1f5d7fd43 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -1785,6 +1785,32 @@ void secure_random_fill(void *bytes, unsigned length);
int pid();
/*
+ Function: cmdline_fix
+ Fixes the command line arguments to be encoded in UTF-8 on all
+ systems.
+
+ Parameters:
+ argc - A pointer to the argc parameter that was passed to the main function.
+ argv - A pointer to the argv parameter that was passed to the main function.
+
+ Remarks:
+ - You need to call cmdline_free once you're no longer using the
+ results.
+*/
+void cmdline_fix(int *argc, const char ***argv);
+
+/*
+ Function: cmdline_free
+ Frees memory that was allocated by cmdline_fix.
+
+ Parameters:
+ argc - The argc obtained from cmdline_fix.
+ argv - The argv obtained from cmdline_fix.
+
+*/
+void cmdline_free(int argc, const char **argv);
+
+/*
Function: bytes_be_to_uint
Packs 4 big endian bytes into an unsigned
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index b9a2e0142..ad046c184 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -2559,6 +2559,7 @@ extern "C" int TWMain(int argc, const char **argv) // ignore_convention
int main(int argc, const char **argv) // ignore_convention
#endif
{
+ cmdline_fix(&argc, &argv);
#if defined(CONF_FAMILY_WINDOWS)
bool QuickEditMode = false;
for(int i = 1; i < argc; i++) // ignore_convention
@@ -2723,5 +2724,6 @@ int main(int argc, const char **argv) // ignore_convention
delete pEngineMap;
delete pEngineMasterServer;
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index d3375782e..2f170fc9c 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -1819,6 +1819,7 @@ void HandleSigInt(int Param)
int main(int argc, const char **argv) // ignore_convention
{
+ cmdline_fix(&argc, &argv);
#if defined(CONF_FAMILY_WINDOWS)
for(int i = 1; i < argc; i++) // ignore_convention
{
@@ -1923,5 +1924,6 @@ int main(int argc, const char **argv) // ignore_convention
delete pStorage;
delete pConfigManager;
+ cmdline_free(argc, argv);
return Ret;
}
diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp
index 624a9f3fe..e19672313 100644
--- a/src/mastersrv/mastersrv.cpp
+++ b/src/mastersrv/mastersrv.cpp
@@ -280,14 +280,11 @@ void ReloadBans()
m_pConsole->ExecuteFile("master.cfg");
}
-int main(int argc, const char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
- int64 LastBuild = 0, LastBanReload = 0;
- ServerType Type = SERVERTYPE_INVALID;
- NETADDR BindAddr;
-
dbg_logger_stdout();
-
+ cmdline_fix(&argc, &argv);
+
mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
int FlagMask = CFGFLAG_MASTER;
@@ -307,9 +304,10 @@ int main(int argc, const char **argv) // ignore_convention
pConfigManager->Init(FlagMask);
m_pConsole->Init();
m_NetBan.Init(m_pConsole, pStorage);
- if(argc > 1) // ignore_convention
- m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
+ if(argc > 1)
+ m_pConsole->ParseArguments(argc-1, &argv[1]);
+ NETADDR BindAddr;
if(pConfig->m_Bindaddr[0] && net_host_lookup(pConfig->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// got bindaddr
@@ -345,6 +343,8 @@ int main(int argc, const char **argv) // ignore_convention
dbg_msg("mastersrv", "started");
+ int64 LastBuild = 0, LastBanReload = 0;
+ ServerType Type = SERVERTYPE_INVALID;
while(1)
{
m_NetOp.Update();
@@ -460,5 +460,6 @@ int main(int argc, const char **argv) // ignore_convention
thread_sleep(1);
}
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/test/test.cpp b/src/test/test.cpp
index c14df1dd3..ccef77b33 100644
--- a/src/test/test.cpp
+++ b/src/test/test.cpp
@@ -17,9 +17,12 @@ void CTestInfo::Filename(char *pBuffer, int BufferLength, const char *pSuffix)
str_format(pBuffer, BufferLength, "%s%s", m_aFilenamePrefix, pSuffix);
}
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
- ::testing::InitGoogleTest(&argc, argv);
+ cmdline_fix(&argc, &argv);
+ ::testing::InitGoogleTest(&argc, const_cast<char **>(argv));
net_init();
- return RUN_ALL_TESTS();
+ int Result = RUN_ALL_TESTS();
+ cmdline_free(argc, argv);
+ return Result;
}
diff --git a/src/tools/crapnet.cpp b/src/tools/crapnet.cpp
index 20cea2bde..146f1fb48 100644
--- a/src/tools/crapnet.cpp
+++ b/src/tools/crapnet.cpp
@@ -206,7 +206,7 @@ void Run(unsigned short Port, NETADDR Dest)
}
}
-int main(int argc, char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
NETADDR Addr = {NETTYPE_IPV4, {127,0,0,1},8303};
dbg_logger_stdout();
diff --git a/src/tools/fake_server.cpp b/src/tools/fake_server.cpp
index 81bb1cebb..0e1e481a8 100644
--- a/src/tools/fake_server.cpp
+++ b/src/tools/fake_server.cpp
@@ -148,8 +148,10 @@ static int Run()
}
}
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
+ cmdline_fix(&argc, &argv);
+
pNet = new CNetServer;
while(argc)
@@ -214,6 +216,7 @@ int main(int argc, char **argv)
int RunReturn = Run();
delete pNet;
+ cmdline_free(argc, argv);
return RunReturn;
}
diff --git a/src/tools/map_resave.cpp b/src/tools/map_resave.cpp
index 0a624b0f4..45d025e39 100644
--- a/src/tools/map_resave.cpp
+++ b/src/tools/map_resave.cpp
@@ -6,40 +6,40 @@
int main(int argc, const char **argv)
{
- IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
- int Index, ID = 0, Type = 0, Size;
- void *pPtr;
- char aFileName[1024];
- CDataFileReader DataFile;
- CDataFileWriter df;
+ cmdline_fix(&argc, &argv);
+ IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
if(!pStorage || argc != 3)
return -1;
- str_format(aFileName, sizeof(aFileName), "%s", argv[2]);
-
- if(!DataFile.Open(pStorage, argv[1], IStorage::TYPE_ALL))
+ CDataFileReader Reader;
+ if(!Reader.Open(pStorage, argv[1], IStorage::TYPE_ALL))
return -1;
- if(!df.Open(pStorage, aFileName))
+
+ CDataFileWriter Writer;
+ if(!Writer.Open(pStorage, argv[2]))
return -1;
// add all items
- for(Index = 0; Index < DataFile.NumItems(); Index++)
+ for(int Index = 0; Index < Reader.NumItems(); Index++)
{
- pPtr = DataFile.GetItem(Index, &Type, &ID);
- Size = DataFile.GetItemSize(Index);
- df.AddItem(Type, ID, Size, pPtr);
+ int Type, ID;
+ void *pPtr = Reader.GetItem(Index, &Type, &ID);
+ int Size = Reader.GetItemSize(Index);
+ Writer.AddItem(Type, ID, Size, pPtr);
}
// add all data
- for(Index = 0; Index < DataFile.NumData(); Index++)
+ for(int Index = 0; Index < Reader.NumData(); Index++)
{
- pPtr = DataFile.GetData(Index);
- Size = DataFile.GetDataSize(Index);
- df.AddData(Size, pPtr);
+ void *pPtr = Reader.GetData(Index);
+ int Size = Reader.GetDataSize(Index);
+ Writer.AddData(Size, pPtr);
}
- DataFile.Close();
- df.Finish();
+ Reader.Close();
+ Writer.Finish();
+
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/tools/map_version.cpp b/src/tools/map_version.cpp
index fbeb27d74..55b28c3a4 100644
--- a/src/tools/map_version.cpp
+++ b/src/tools/map_version.cpp
@@ -46,8 +46,10 @@ io_write(s_File, aBuf, str_length(aBuf));
return 0;
}
-int main(int argc, const char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
+ cmdline_fix(&argc, &argv);
+
IKernel *pKernel = IKernel::Create();
s_pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
s_pEngineMap = CreateEngineMap();
@@ -67,5 +69,6 @@ int main(int argc, const char **argv) // ignore_convention
io_close(s_File);
}
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/tools/packetgen.cpp b/src/tools/packetgen.cpp
index 0d3f5c0e2..25fa7ebf8 100644
--- a/src/tools/packetgen.cpp
+++ b/src/tools/packetgen.cpp
@@ -28,7 +28,7 @@ void Run(NETADDR Dest)
}
}
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
NETADDR Dest = {NETTYPE_IPV4, {127,0,0,1}, 8303};
Run(Dest);
diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp
index 698251060..1413d8baa 100644
--- a/src/versionsrv/versionsrv.cpp
+++ b/src/versionsrv/versionsrv.cpp
@@ -79,11 +79,10 @@ void SendVer(NETADDR *pAddr, TOKEN ResponseToken)
g_NetOp.Send(&p, ResponseToken);
}
-int main(int argc, const char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
- NETADDR BindAddr;
-
dbg_logger_stdout();
+ cmdline_fix(&argc, &argv);
int FlagMask = 0;
IKernel *pKernel = IKernel::Create();
@@ -100,6 +99,7 @@ int main(int argc, const char **argv) // ignore_convention
pConfigManager->Init(FlagMask);
pConsole->Init();
+ NETADDR BindAddr;
mem_zero(&BindAddr, sizeof(BindAddr));
BindAddr.type = NETTYPE_ALL;
BindAddr.port = VERSIONSRV_PORT;
@@ -155,5 +155,6 @@ int main(int argc, const char **argv) // ignore_convention
thread_sleep(1);
}
+ cmdline_free(argc, argv);
return 0;
}