winmain: Don't use SDL_malloc (or SDL_stack_alloc, which might be malloc).
authorRyan C. Gordon <icculus@icculus.org>
Mon, 29 Oct 2018 20:00:03 -0400
changeset 1236968c87b40b434
parent 12368 9bb50edccc46
child 12370 86e097182d16
winmain: Don't use SDL_malloc (or SDL_stack_alloc, which might be malloc).

Otherwise, we are using the allocator before the app can set up its own hooks.

Now we use VirtualAlloc, and WideCharToMultiByte (because SDL_iconv uses
SDL_malloc, too!) to get ready to call into SDL_main.

This also makes console_wmain() call into the same routines as everything
else, so we don't have to deal with those allocations, too. Hopefully we
end up with the same results from GetCommandLine() as we do in wargv.

Fixes Bugzilla #4340.
src/main/windows/SDL_windows_main.c
     1.1 --- a/src/main/windows/SDL_windows_main.c	Mon Oct 29 15:51:38 2018 -0400
     1.2 +++ b/src/main/windows/SDL_windows_main.c	Mon Oct 29 20:00:03 2018 -0400
     1.3 @@ -116,50 +116,65 @@
     1.4  # endif
     1.5  #endif
     1.6  
     1.7 -/* WinMain, main, and wmain eventually call into here. */
     1.8 -static int
     1.9 -main_utf8(int argc, char *argv[])
    1.10 -{
    1.11 -    SDL_SetMainReady();
    1.12 -
    1.13 -    /* Run the application main() code */
    1.14 -    return SDL_main(argc, argv);
    1.15 -}
    1.16 -
    1.17  /* Gets the arguments with GetCommandLine, converts them to argc and argv
    1.18 -   and calls main_utf8 */
    1.19 +   and calls SDL_main */
    1.20  static int
    1.21  main_getcmdline()
    1.22  {
    1.23      char **argv;
    1.24      int argc;
    1.25 -    char *cmdline;
    1.26 +    char *cmdline = NULL;
    1.27      int retval = 0;
    1.28 +    int cmdalloc = 0;
    1.29 +    const TCHAR *text = GetCommandLine();
    1.30 +    const TCHAR *ptr;
    1.31 +    int argc_guess = 2;  /* space for NULL and initial argument. */
    1.32 +    int rc;
    1.33  
    1.34 -    /* Grab the command line */
    1.35 -    TCHAR *text = GetCommandLine();
    1.36 +    /* make a rough guess of command line arguments. Overestimates if there
    1.37 +       are quoted things. */
    1.38 +    for (ptr = text; *ptr; ptr++) {
    1.39 +        if ((*ptr == ' ') || (*ptr == '\t')) {
    1.40 +            argc_guess++;
    1.41 +        }
    1.42 +    }
    1.43 +
    1.44  #if UNICODE
    1.45 -    cmdline = WIN_StringToUTF8(text);
    1.46 +    rc = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
    1.47 +    if (rc > 0) {
    1.48 +        cmdalloc = rc + (sizeof (char *) * argc_guess);
    1.49 +        argv = (char **) VirtualAlloc(NULL, cmdalloc, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
    1.50 +        if (argv) {
    1.51 +            cmdline = (char *) (argv + argc_guess);
    1.52 +            const int rc2 = WideCharToMultiByte(CP_UTF8, 0, text, -1, cmdline, rc, NULL, NULL);
    1.53 +            SDL_assert(rc2 == rc);
    1.54 +        }
    1.55 +    }
    1.56  #else
    1.57      /* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */
    1.58 -    cmdline = SDL_strdup(text);
    1.59 +    rc = ((int) SDL_strlen(text)) + 1;
    1.60 +    cmdalloc = rc + (sizeof (char *) * argc_guess);
    1.61 +    argv = (char **) VirtualAlloc(NULL, cmdalloc, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
    1.62 +    if (argv) {
    1.63 +        cmdline = (char *) (argv + argc_guess);
    1.64 +        SDL_strcpy(cmdline, text);
    1.65 +    }
    1.66  #endif
    1.67      if (cmdline == NULL) {
    1.68          return OutOfMemory();
    1.69      }
    1.70  
    1.71      /* Parse it into argv and argc */
    1.72 -    argc = ParseCommandLine(cmdline, NULL);
    1.73 -    argv = SDL_stack_alloc(char *, argc + 1);
    1.74 -    if (argv == NULL) {
    1.75 -        return OutOfMemory();
    1.76 -    }
    1.77 -    ParseCommandLine(cmdline, argv);
    1.78 +    SDL_assert(ParseCommandLine(cmdline, NULL) <= argc_guess);
    1.79 +    argc = ParseCommandLine(cmdline, argv);
    1.80  
    1.81 -    retval = main_utf8(argc, argv);
    1.82 +    SDL_SetMainReady();
    1.83  
    1.84 -    SDL_stack_free(argv);
    1.85 -    SDL_free(cmdline);
    1.86 +    /* Run the application main() code */
    1.87 +    retval = SDL_main(argc, argv);
    1.88 +
    1.89 +    VirtualFree(argv, cmdalloc, MEM_DECOMMIT);
    1.90 +    VirtualFree(argv, 0, MEM_RELEASE);
    1.91  
    1.92      return retval;
    1.93  }
    1.94 @@ -177,21 +192,7 @@
    1.95  int
    1.96  console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
    1.97  {
    1.98 -    int retval = 0;
    1.99 -    char **argv = SDL_stack_alloc(char*, argc + 1);
   1.100 -    int i;
   1.101 -
   1.102 -    for (i = 0; i < argc; ++i) {
   1.103 -        argv[i] = WIN_StringToUTF8(wargv[i]);
   1.104 -    }
   1.105 -    argv[argc] = NULL;
   1.106 -
   1.107 -    retval = main_utf8(argc, argv);
   1.108 -
   1.109 -    /* !!! FIXME: we are leaking all the elements of argv we allocated. */
   1.110 -    SDL_stack_free(argv);
   1.111 -
   1.112 -    return retval;
   1.113 +    return main_getcmdline();
   1.114  }
   1.115  #endif
   1.116