fix command line arguments with unicode on windows

Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
Robert Müller 2021-11-21 18:16:14 +01:00
parent d456d4bc26
commit f20443b694
21 changed files with 129 additions and 19 deletions

View file

@ -3556,6 +3556,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
}
PROCESS shell_execute(const char *file)
{
#if defined(CONF_FAMILY_WINDOWS)

View file

@ -2194,6 +2194,32 @@ void uint_to_bytes_be(unsigned char *bytes, unsigned value);
*/
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);
#if defined(CONF_FAMILY_WINDOWS)
typedef void *PROCESS;
#else

View file

@ -4299,14 +4299,15 @@ void CClient::HandleMapPath(const char *pPath)
#if defined(CONF_PLATFORM_MACOS)
extern "C" int TWMain(int argc, const char **argv) // ignore_convention
#elif defined(CONF_PLATFORM_ANDROID)
extern "C" __attribute__((visibility("default"))) int SDL_main(int argc, char *argv[]);
extern "C" __attribute__((visibility("default"))) int SDL_main(int argc, const char *argv[]);
extern "C" void InitAndroid();
int SDL_main(int argc, char *argv[])
int SDL_main(int argc, const char *argv[])
#else
int main(int argc, const char **argv) // ignore_convention
#endif
{
cmdline_fix(&argc, &argv);
bool Silent = false;
bool RandInitFailed = false;
@ -4484,6 +4485,7 @@ int main(int argc, const char **argv) // ignore_convention
delete pKernel;
cmdline_free(argc, argv);
#ifdef CONF_PLATFORM_ANDROID
// properly close this native thread, so globals are destructed
std::exit(0);

View file

@ -3538,6 +3538,7 @@ static CServer *CreateServer() { return new CServer(); }
int main(int argc, const char **argv) // ignore_convention
{
cmdline_fix(&argc, &argv);
bool Silent = false;
for(int i = 1; i < argc; i++) // ignore_convention
@ -3640,6 +3641,7 @@ int main(int argc, const char **argv) // ignore_convention
// free
delete pKernel;
cmdline_free(argc, argv);
return Ret;
}

View file

@ -324,6 +324,8 @@ int main(int argc, const char **argv) // ignore_convention
ServerType Type = SERVERTYPE_INVALID;
NETADDR BindAddr;
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
net_init();

View file

@ -106,14 +106,17 @@ void CTestInfo::DeleteTestStorageFilesOnSuccess()
}
}
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();
if(secure_random_init())
{
fprintf(stderr, "random init failed\n");
return 1;
}
return RUN_ALL_TESTS();
int Result = RUN_ALL_TESTS();
cmdline_free(argc, argv);
return Result;
}

View file

@ -46,6 +46,7 @@ static int ListdirCallback(const char *pItemName, int IsDir, int StorageType, vo
int main(int argc, const char **argv) // NOLINT(misc-definitions-in-headers)
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
IStorage *pStorage = CreateLocalStorage();
if(argc == 1)
@ -64,5 +65,6 @@ int main(int argc, const char **argv) // NOLINT(misc-definitions-in-headers)
{
ProcessItem(argv[i], pStorage);
}
cmdline_free(argc, argv);
return 0;
}

View file

@ -208,10 +208,12 @@ void Run(unsigned short Port, NETADDR Dest)
}
}
int main(int argc, char **argv) // ignore_convention
int main(int argc, const char **argv) // ignore_convention
{
cmdline_fix(&argc, &argv);
NETADDR Addr = {NETTYPE_IPV4, {127, 0, 0, 1}, 8303};
dbg_logger_stdout();
Run(8302, Addr);
cmdline_free(argc, argv);
return 0;
}

View file

@ -73,6 +73,7 @@ int DilateFile(const char *pFilename)
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
if(argc == 1)
{
@ -82,5 +83,6 @@ int main(int argc, const char **argv)
for(int i = 1; i < argc; i++)
DilateFile(argv[i]);
cmdline_free(argc, argv);
return 0;
}

View file

@ -73,8 +73,10 @@ void CreateEmptyMap(IStorage *pStorage)
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_SERVER, argc, argv);
CreateEmptyMap(pStorage);
cmdline_free(argc, argv);
return 0;
}

View file

@ -149,8 +149,9 @@ 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)
@ -219,5 +220,6 @@ int main(int argc, char **argv)
int RunReturn = Run();
delete pNet;
cmdline_free(argc, argv);
return RunReturn;
}

View file

@ -135,6 +135,7 @@ void *ReplaceImageItem(void *pItem, int Type, CMapItemImage *pNewImgItem)
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
@ -253,5 +254,6 @@ int main(int argc, const char **argv)
g_DataReader.Close();
g_DataWriter.Finish();
cmdline_free(argc, argv);
return Success ? 0 : -1;
}

View file

@ -6,7 +6,7 @@
#include <pnglite.h>
bool Process(IStorage *pStorage, char **pMapNames)
bool Process(IStorage *pStorage, const char **pMapNames)
{
CDataFileReader Maps[2];
@ -98,20 +98,20 @@ bool Process(IStorage *pStorage, char **pMapNames)
return true;
}
int main(int argc, char *argv[])
int main(int argc, const char *argv[])
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
dbg_logger_file("map_diff.txt");
IStorage *pStorage = CreateLocalStorage();
if(argc == 3)
{
return Process(pStorage, &argv[1]) ? 0 : 1;
}
else
if(argc != 3)
{
dbg_msg("usage", "%s map1 map2", argv[0]);
return -1;
}
int Result = Process(pStorage, &argv[1]) ? 0 : 1;
cmdline_free(argc, argv);
return Result;
}

View file

@ -93,8 +93,9 @@ bool Process(IStorage *pStorage, const char *pMapName, const char *pPathSave)
return Map.Close();
}
int main(int argc, char *argv[])
int main(int argc, const char *argv[])
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
char aMap[512];
@ -126,5 +127,7 @@ int main(int argc, char *argv[])
png_init(0, 0);
return Process(pStorage, aMap, aDir) ? 0 : 1;
int Result = Process(pStorage, aMap, aDir) ? 0 : 1;
cmdline_free(argc, argv);
return Result;
}

View file

@ -78,6 +78,7 @@ void GetImageSHA256(uint8_t *pImgBuff, int ImgSize, int Width, int Height, char
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
@ -324,5 +325,6 @@ int main(int argc, const char **argv)
DataFile.Close();
df.Finish();
cmdline_free(argc, argv);
return 0;
}

View file

@ -110,6 +110,7 @@ void *ReplaceImageItem(void *pItem, int Type, const char *pImgName, const char *
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
@ -205,5 +206,6 @@ int main(int argc, const char **argv)
g_DataWriter.Finish();
dbg_msg("map_replace_image", "image '%s' replaced", pImageName);
cmdline_free(argc, argv);
return 0;
}

View file

@ -6,6 +6,7 @@
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
int Index, ID = 0, Type = 0, Size;
void *pPtr;
@ -48,5 +49,6 @@ int main(int argc, const char **argv)
DataFile.Close();
df.Finish();
cmdline_free(argc, argv);
return 0;
}

View file

@ -31,9 +31,11 @@ void Run(NETADDR Dest)
}
}
int main(int argc, char **argv)
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
NETADDR Dest = {NETTYPE_IPV4, {127, 0, 0, 1}, 8303};
Run(Dest);
cmdline_free(argc, argv);
return 0;
}

View file

@ -2,6 +2,7 @@
int main(int argc, const char **argv) // ignore_convention
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
if(argc < 1 + 2)
{
@ -9,5 +10,6 @@ int main(int argc, const char **argv) // ignore_convention
return -1;
}
dbg_msg("conf", "not_confusable=%d", str_utf8_comp_confusable(argv[1], argv[2]));
cmdline_free(argc, argv);
return 0;
}

View file

@ -1,6 +1,7 @@
#include <engine/shared/uuid_manager.h>
int main(int argc, char **argv)
int main(int argc, const char **argv)
{
cmdline_fix(&argc, &argv);
dbg_logger_stdout();
if(argc != 2)
{
@ -11,4 +12,6 @@ int main(int argc, char **argv)
char aBuf[UUID_MAXSTRSIZE];
FormatUuid(Uuid, aBuf, sizeof(aBuf));
dbg_msg("uuid", "%s", aBuf);
cmdline_free(argc, argv);
return 0;
}

View file

@ -7,8 +7,9 @@
static CNetClient g_NetOp; // main
int main(int argc, char **argv) // ignore_convention
int main(int argc, const char **argv) // ignore_convention
{
cmdline_fix(&argc, &argv);
NETADDR BindAddr;
mem_zero(&BindAddr, sizeof(BindAddr));
BindAddr.type = NETTYPE_ALL;
@ -68,4 +69,6 @@ int main(int argc, char **argv) // ignore_convention
printf("%g ms\n", (double)(endTime - startTime) / time_freq() * 1000);
}
}
cmdline_free(argc, argv);
return 0;
}