MAX_PATH reduction.
authorJay Krell <jaykrell@microsoft.com>
Thu, 29 Aug 2019 13:07:16 +0000 (06:07 -0700)
committerLarry Ewing <lewing@microsoft.com>
Wed, 4 Sep 2019 17:31:13 +0000 (12:31 -0500)
Commit migrated from https://github.com/mono/mono/commit/f8be8c6de73646e7ed636d8ce1c36f997193bd66

src/mono/mono/eglib/glib.h
src/mono/mono/eglib/gmisc-win32.c
src/mono/mono/eglib/gmodule-win32.c
src/mono/mono/eglib/test/module.c
src/mono/mono/metadata/w32process-win32-uwp.c
src/mono/mono/mini/main.c

index cdfbe4d..747576d 100644 (file)
@@ -1433,6 +1433,26 @@ mono_qsort (void* base, size_t num, size_t size, int (*compare)(const void*, con
 #define MONO_DECL_CALLBACK(prefix, ret, name, sig) ret (*name) sig;
 #define MONO_INIT_CALLBACK(prefix, ret, name, sig) prefix ## _ ## name,
 
+// g_free the result
+// No MAX_PATH limit.
+gboolean
+mono_get_module_filename (gpointer mod, gunichar2** pstr, guint32* plength);
+
+// g_free the result
+// No MAX_PATH limit.
+gboolean
+mono_get_module_filename_ex (gpointer process, gpointer mod, gunichar2** pstr, guint32* plength);
+
+// g_free the result
+// No MAX_PATH limit.
+gboolean
+mono_get_module_basename (gpointer process, gpointer mod, gunichar2** pstr, guint32* plength);
+
+// g_free the result
+// No MAX_PATH limit.
+gboolean
+mono_get_current_directory (gunichar2** pstr, guint32* plength);
+
 // For each allocator; i.e. returning gpointer that needs to be cast.
 // Macros do not recurse, so naming function and macro the same is ok.
 // However these are also already macros.
index 4219a39..4efa27f 100644 (file)
@@ -53,7 +53,8 @@ g_getenv(const gchar *variable)
        gint32 buffer_size = 1024;
        gint32 retval;
        var = u8to16(variable); 
-       buffer = g_malloc(buffer_size*sizeof(gunichar2));
+       // FIXME This should loop in case another thread is growing the data.
+       buffer = g_new (gunichar2, buffer_size);
        retval = GetEnvironmentVariableW (var, buffer, buffer_size);
        if (retval != 0) {
                if (retval > buffer_size) {
index d0a1837..b71ec52 100644 (file)
@@ -189,3 +189,139 @@ g_module_build_path (const gchar *directory, const gchar *module_name)
        }
        return g_strdup_printf ("%s%s" LIBSUFFIX, lib_prefix, module_name); 
 }
+
+// This is not about GModule but is still a close fit.
+// This is not named "g_" but that should be ok.
+// g_free the result
+// No MAX_PATH limit.
+gboolean
+mono_get_module_filename (gpointer mod, gunichar2** pstr, guint32* plength)
+{
+       gunichar2* str = NULL;
+       guint32 capacity = 32; // tunable
+       guint32 length = 0;
+       gboolean success = FALSE;
+
+       while (TRUE)
+       {
+               length = 0;
+               capacity *= 2;
+               if (capacity > (1 << 24))
+                       break;
+               str = g_new (gunichar2, capacity);
+               if (!str)
+                       break;
+               length = GetModuleFileNameW ((HMODULE)mod, (PWSTR)str, capacity);
+               success = length && length < (capacity - 1); // This function does not truncate, but - 1 anyway.
+               if (success)
+                       break;
+               g_free (str); // error or too small
+               str = NULL;
+               if (!length) // error
+                       break;
+       }
+       *pstr = str;
+       *plength = length;
+       return success;
+}
+
+// This is not about GModule but is still a close fit.
+// This is not named "g_" but that should be ok.
+// g_free the result
+// No MAX_PATH limit.
+gboolean
+mono_get_module_filename_ex (gpointer process, gpointer mod, gunichar2** pstr, guint32* plength)
+{
+       gunichar2* str = NULL;
+       guint32 capacity = 32; // tunable
+       guint32 length = 0;
+       gboolean success = FALSE;
+
+       while (TRUE)
+       {
+               length = 0;
+               capacity *= 2;
+               if (capacity > (1 << 24))
+                       break;
+               str = g_new (gunichar2, capacity);
+               if (!str)
+                       break;
+               length = GetModuleFileNameExW (process, (HMODULE)mod, str, capacity);
+               success = length && length < (capacity - 1); // This function truncates, thus the - 1.
+               if (success)
+                       break;
+               g_free (str); // error or too small
+               str = NULL;
+               if (!length) // error
+                       break;
+       }
+       *pstr = str;
+       *plength = length;
+       return success;
+}
+
+gboolean
+mono_get_module_basename (gpointer process, gpointer mod, gunichar2** pstr, guint32* plength)
+{
+       gunichar2* str = NULL;
+       guint32 capacity = 32; // tunable
+       guint32 length = 0;
+       gboolean success = FALSE;
+
+       while (TRUE)
+       {
+               length = 0;
+               capacity *= 2;
+               if (capacity > (1 << 24))
+                       break;
+               str = g_new (gunichar2, capacity);
+               if (!str)
+                       break;
+               length = GetModuleBaseNameW (process, (HMODULE)mod, str, capacity);
+               success = length && length < (capacity - 1); // This function truncates, thus the - 1.
+               if (success)
+                       break;
+               g_free (str); // error or too small
+               str = NULL;
+               if (!length) // error
+                       break;
+       }
+       *pstr = str;
+       *plength = length;
+       return success;
+}
+
+// g_free the result
+// No MAX_PATH limit.
+gboolean
+mono_get_current_directory (gunichar2** pstr, guint32* plength)
+{
+       gunichar2* str = NULL;
+       guint32 capacity = 32; // tunable
+       guint32 length = 0;
+       gboolean success = FALSE;
+
+       while (TRUE)
+       {
+               length = 0;
+               capacity *= 2;
+               if (capacity > (1 << 24))
+                       break;
+               str = g_new (gunichar2, capacity);
+               if (!str)
+                       break;
+               // Call in loop, not just twice, in case another thread is changing it.
+               // Result is transient in currentness and validity (can get deleted or become a file).
+               length = GetCurrentDirectoryW (capacity, (PWSTR)str);
+               success = length && length < (capacity - 1);
+               if (success)
+                       break;
+               g_free (str); // error or too small
+               str = NULL;
+               if (!length) // error
+                       break;
+       }
+       *pstr = str;
+       *plength = length;
+       return success;
+}
index 75000c5..39e796c 100644 (file)
 #define EXTERNAL_SYMBOL "system"
 #endif
 
+#if _WIN32
+#include <windows.h>
+#include <wchar.h>
+#include <psapi.h>
+#endif
+
 void G_MODULE_EXPORT
 dummy_test_export (void);
 
@@ -57,8 +63,100 @@ test_module_symbol_null (void)
        return OK;
 }
 
+static RESULT
+test_module_get_module_filename (void)
+{
+#if _WIN32
+       const HMODULE mods [ ] = {NULL, LoadLibraryW (L"msvcrt.dll"), (HMODULE)(gssize)-1 };
+
+       for (int i = 0; i < 2; ++i) {
+               for (int j = 0; j <= 2; ++j) {
+                       const HMODULE mod = mods [i];
+                       wchar_t* str = { 0 };
+                       guint32 length = { 0 };
+                       wchar_t buf2 [999] = { 0 };
+                       wchar_t buf3 [2] = { 0 };
+                       gboolean success = { 0 };
+                       guint32 length2 = { 0 };
+                       gboolean success2 = { 0 };
+                       guint32 length3 = { 0 };
+                       gboolean success3 = { 0 };
+
+                       switch (j) {
+                       case 0:
+                               success = mono_get_module_filename (mod, &str, &length);
+                               length2 = GetModuleFileNameW (mod, buf2, G_N_ELEMENTS (buf2)); // large buf
+                               length3 = GetModuleFileNameW (mod, buf3, 1); // small buf
+                               break;
+                       case 1:
+                               success = mono_get_module_filename_ex (GetCurrentProcess (), mods [i], &str, &length);
+                               length2 = GetModuleFileNameExW (GetCurrentProcess (), mod, buf2, G_N_ELEMENTS (buf2)); // large buf
+                               length3 = GetModuleFileNameExW (GetCurrentProcess (), mod, buf3, 1); // small buf
+                               break;
+                       case 2:
+                               success = mono_get_module_basename (GetCurrentProcess (), mod, &str, &length);
+                               length2 = GetModuleBaseNameW (GetCurrentProcess (), mod, buf2, G_N_ELEMENTS (buf2)); // large buf
+                               length3 = GetModuleBaseNameW (GetCurrentProcess (), mod, buf3, 1); // small buf
+                               break;
+                       }
+                       success2 = length2 && length2 < G_N_ELEMENTS (buf2);
+                       success3 = length3 == 1;
+                       printf ("j:%d s:%X s2:%X s3:%X l:%u l2:%u l3:%u str:%X b2:%X b3:%X\n",
+                               j,
+                               success, success2, success3,
+                               length, length2, length3,
+                               str ? str [0] : 0, buf2 [0], buf3 [0]);
+                       g_assert (success == success2);
+                       g_assert (success == success3 || j > 0);
+                       g_assert (!success || str [0] == buf2 [0]);
+                       //g_assert (!success || str [0] == buf3 [0]);
+                       g_assert (length3 == 0 || length3 == 1);
+                       g_assert (length == (success2 ? wcslen (buf2) :0));
+                       g_assert (!success || !wcscmp (str, buf2));
+                       g_assert (!success || str);
+                       if (success)
+                               printf ("%p %ls %ls %d %d\n", mod, str, buf2, length, length2);
+                       else
+                               printf ("!%p %u\n", str, (guint)length);
+                       g_free (str);
+               }
+       }
+#endif
+       return OK;
+}
+
+static RESULT
+test_get_current_directory (void)
+{
+#if _WIN32
+       wchar_t* str = { 0 };
+       guint32 length = { 0 };
+       gboolean success = mono_get_current_directory (&str, &length);
+       wchar_t buf2 [999] = { 0 };
+       const int length2 = GetCurrentDirectoryW (G_N_ELEMENTS (buf2), buf2);
+       const gboolean success2 = length2 && length2 < G_N_ELEMENTS (buf2);
+       wchar_t buf3 [2] = { 0 };
+       const int length3 = GetCurrentDirectoryW (G_N_ELEMENTS (buf3), buf3);
+       const gboolean success3 = length3 > 0;
+       printf ("s:%X s2:%X s3:%X str:%X b2:%X b3:%X\n", success, success2, success3, str ? str [0] : 0, buf2 [0], buf3 [0]);
+       g_assert (length == length2);
+       g_assert (success == success2);
+       g_assert (success == success3);
+       g_assert (!success || !wcscmp (str, buf2));
+       g_assert (!success || str);
+       if (success)
+               printf ("%ls\n%ls\n", str, buf2);
+       else
+               printf ("!%p %u\n", str, (guint)length);
+       g_free (str);
+#endif
+       return OK;
+}
+
 static Test module_tests [] = {
        {"g_module_symbol_null", test_module_symbol_null},
+       {"module_get_module_filename", test_module_get_module_filename},
+       {"get_current_directory", test_get_current_directory},
        {NULL, NULL}
 };
 
index 0b19dd9..73b7cca 100644 (file)
@@ -71,11 +71,14 @@ ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStar
 MonoStringHandle
 ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process, MonoError *error)
 {
-       gunichar2 name [MAX_PATH]; // FIXME MAX_PATH
-       const guint32 len = GetModuleFileNameW (NULL, name, G_N_ELEMENTS (name));
-       if (len == 0)
+       gunichar2* name = NULL;
+       guint32 len = 0;
+       // FIXME give allocator to mono_get_module_file_name to avoid copies, here and many other
+       if (!mono_get_module_file_name (NULL, &name, &len))
                return NULL_HANDLE_STRING;
-       return mono_string_new_utf16_handle (mono_domain_get (), name, len, error);
+       MonoStringHandle res = mono_string_new_utf16_handle (mono_domain_get (), name, len, error);
+       g_free (name);
+       return res;
 }
 
 MonoBoolean
index 3c5fa17..c647bbe 100644 (file)
@@ -387,14 +387,14 @@ ICALL_EXPORT int ves_icall_Interop_Sys_DoubleToString (double, char*, char*, int
 int
 main (void)
 {
-       TCHAR szFileName[MAX_PATH];
+       gunichar2* module_file_name;
+       guint32 length;
        int argc;
        gunichar2** argvw;
        gchar** argv;
        int i;
-       DWORD count;
-       
-       argvw = CommandLineToArgvW (GetCommandLine (), &argc);
+
+       argvw = CommandLineToArgvW (GetCommandLineW (), &argc);
        argv = g_new0 (gchar*, argc + 1);
        for (i = 0; i < argc; i++)
                argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
@@ -402,8 +402,11 @@ main (void)
 
        LocalFree (argvw);
 
-       if ((count = GetModuleFileName (NULL, szFileName, MAX_PATH)) != 0){
-               char *entry = g_utf16_to_utf8 (szFileName, count, NULL, NULL, NULL);
+       if (mono_get_module_file_nae (NULL, &szFileName, NULL))
+
+       if ((mono_get_module_filename (NULL, &module_file_name, &length))) {
+               char *entry = g_utf16_to_utf8 (module_file_name, length, NULL, NULL, NULL);
+               g_free (module_file_name);
                probe_embedded (entry, &argc, &argv);
        }