diff options
author | Robert Müller <robert.mueller@uni-siegen.de> | 2021-11-22 23:25:51 +0100 |
---|---|---|
committer | Robert Müller <robert.mueller@uni-siegen.de> | 2021-11-28 10:48:55 +0100 |
commit | 4f28113abd56ccb47c432078948b402cd31fe0ab (patch) | |
tree | 4458b3bc8e266a15ce121f3eb057ba938d1286c2 | |
parent | be2d79b7614a502dc8334026f3f0bb624d8fd22c (diff) |
fix command line arguments with unicode on windows
Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
-rw-r--r-- | src/base/system.c | 45 | ||||
-rw-r--r-- | src/base/system.h | 26 | ||||
-rw-r--r-- | src/engine/client/client.cpp | 2 | ||||
-rw-r--r-- | src/engine/server/server.cpp | 2 | ||||
-rw-r--r-- | src/mastersrv/mastersrv.cpp | 17 | ||||
-rw-r--r-- | src/test/test.cpp | 9 | ||||
-rw-r--r-- | src/tools/crapnet.cpp | 2 | ||||
-rw-r--r-- | src/tools/fake_server.cpp | 5 | ||||
-rw-r--r-- | src/tools/map_resave.cpp | 40 | ||||
-rw-r--r-- | src/tools/map_version.cpp | 5 | ||||
-rw-r--r-- | src/tools/packetgen.cpp | 2 | ||||
-rw-r--r-- | src/versionsrv/versionsrv.cpp | 7 |
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; } |