Alexandre Julliard : winecrt0: Rebuild the argv array instead of getting it from libwine.
Alexandre Julliard
julliard at winehq.org
Wed Apr 8 15:48:32 CDT 2020
Module: wine
Branch: master
Commit: 036f4dca3c7f9ee8964bb4ae0c4bcd106a347c7b
URL: https://source.winehq.org/git/wine.git/?a=commit;h=036f4dca3c7f9ee8964bb4ae0c4bcd106a347c7b
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Apr 8 15:09:00 2020 +0200
winecrt0: Rebuild the argv array instead of getting it from libwine.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/winecrt0/exe_entry.c | 78 +++++++++++++++++++++++++++++++++++-----------
dlls/winecrt0/exe_wentry.c | 68 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 125 insertions(+), 21 deletions(-)
diff --git a/dlls/winecrt0/exe_entry.c b/dlls/winecrt0/exe_entry.c
index 9ae45f9f04..803d56e10e 100644
--- a/dlls/winecrt0/exe_entry.c
+++ b/dlls/winecrt0/exe_entry.c
@@ -25,43 +25,83 @@
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
-#include "winnls.h"
#include "winternl.h"
-#include "wine/library.h"
#include "crt0_private.h"
extern int __cdecl main( int argc, char *argv[] );
-static char **build_argv( WCHAR **wargv )
+static char **build_argv( const char *src, int *ret_argc )
{
- int argc;
- char *p, **argv;
- DWORD total = 0;
-
- for (argc = 0; wargv[argc]; argc++)
- total += WideCharToMultiByte( CP_ACP, 0, wargv[argc], -1, NULL, 0, NULL, NULL );
+ char **argv, *arg, *dst;
+ int argc, in_quotes = 0, bcount = 0, len = strlen(src) + 1;
- argv = HeapAlloc( GetProcessHeap(), 0, total + (argc + 1) * sizeof(*argv) );
- p = (char *)(argv + argc + 1);
- for (argc = 0; wargv[argc]; argc++)
+ argc = 2 + len / 2;
+ argv = HeapAlloc( GetProcessHeap(), 0, argc * sizeof(*argv) + len );
+ arg = dst = (char *)(argv + argc);
+ argc = 0;
+ while (*src)
{
- DWORD reslen = WideCharToMultiByte( CP_ACP, 0, wargv[argc], -1, p, total, NULL, NULL );
- argv[argc] = p;
- p += reslen;
- total -= reslen;
+ if ((*src == ' ' || *src == '\t') && !in_quotes)
+ {
+ /* skip the remaining spaces */
+ while (*src == ' ' || *src == '\t') src++;
+ if (!*src) break;
+ /* close the argument and copy it */
+ *dst++ = 0;
+ argv[argc++] = arg;
+ /* start with a new argument */
+ arg = dst;
+ bcount = 0;
+ }
+ else if (*src == '\\')
+ {
+ *dst++ = *src++;
+ bcount++;
+ }
+ else if (*src == '"')
+ {
+ if ((bcount & 1) == 0)
+ {
+ /* Preceded by an even number of '\', this is half that
+ * number of '\', plus a '"' which we discard.
+ */
+ dst -= bcount / 2;
+ src++;
+ if (in_quotes && *src == '"') *dst++ = *src++;
+ else in_quotes = !in_quotes;
+ }
+ else
+ {
+ /* Preceded by an odd number of '\', this is half that
+ * number of '\' followed by a '"'
+ */
+ dst -= bcount / 2 + 1;
+ *dst++ = *src++;
+ }
+ bcount = 0;
+ }
+ else /* a regular character */
+ {
+ *dst++ = *src++;
+ bcount = 0;
+ }
}
+ *dst = 0;
+ argv[argc++] = arg;
argv[argc] = NULL;
+ *ret_argc = argc;
return argv;
}
DWORD WINAPI DECLSPEC_HIDDEN __wine_spec_exe_entry( PEB *peb )
{
+ int argc;
BOOL needs_init = (__wine_spec_init_state != CONSTRUCTORS_DONE);
- char **argv = build_argv( __wine_main_wargv );
+ char **argv = build_argv( GetCommandLineA(), &argc );
DWORD ret;
- if (needs_init) _init( __wine_main_argc, argv, NULL );
- ret = main( __wine_main_argc, argv );
+ if (needs_init) _init( argc, argv, NULL );
+ ret = main( argc, argv );
if (needs_init) _fini();
ExitProcess( ret );
}
diff --git a/dlls/winecrt0/exe_wentry.c b/dlls/winecrt0/exe_wentry.c
index b889e5a102..b01bfd6210 100644
--- a/dlls/winecrt0/exe_wentry.c
+++ b/dlls/winecrt0/exe_wentry.c
@@ -26,18 +26,82 @@
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
-#include "wine/library.h"
#include "crt0_private.h"
extern int __cdecl wmain( int argc, WCHAR *argv[] );
+static WCHAR **build_argv( const WCHAR *src, int *ret_argc )
+{
+ WCHAR **argv, *arg, *dst;
+ int argc, in_quotes = 0, bcount = 0, len = lstrlenW(src) + 1;
+
+ argc = 2 + len / 2;
+ argv = HeapAlloc( GetProcessHeap(), 0, argc * sizeof(*argv) + len * sizeof(WCHAR) );
+ arg = dst = (WCHAR *)(argv + argc);
+ argc = 0;
+ while (*src)
+ {
+ if ((*src == ' ' || *src == '\t') && !in_quotes)
+ {
+ /* skip the remaining spaces */
+ while (*src == ' ' || *src == '\t') src++;
+ if (!*src) break;
+ /* close the argument and copy it */
+ *dst++ = 0;
+ argv[argc++] = arg;
+ /* start with a new argument */
+ arg = dst;
+ bcount = 0;
+ }
+ else if (*src == '\\')
+ {
+ *dst++ = *src++;
+ bcount++;
+ }
+ else if (*src == '"')
+ {
+ if ((bcount & 1) == 0)
+ {
+ /* Preceded by an even number of '\', this is half that
+ * number of '\', plus a '"' which we discard.
+ */
+ dst -= bcount / 2;
+ src++;
+ if (in_quotes && *src == '"') *dst++ = *src++;
+ else in_quotes = !in_quotes;
+ }
+ else
+ {
+ /* Preceded by an odd number of '\', this is half that
+ * number of '\' followed by a '"'
+ */
+ dst -= bcount / 2 + 1;
+ *dst++ = *src++;
+ }
+ bcount = 0;
+ }
+ else /* a regular character */
+ {
+ *dst++ = *src++;
+ bcount = 0;
+ }
+ }
+ *dst = 0;
+ argv[argc++] = arg;
+ argv[argc] = NULL;
+ *ret_argc = argc;
+ return argv;
+}
+
DWORD WINAPI DECLSPEC_HIDDEN __wine_spec_exe_wentry( PEB *peb )
{
+ int argc;
BOOL needs_init = (__wine_spec_init_state != CONSTRUCTORS_DONE);
+ WCHAR **argv = build_argv( GetCommandLineW(), &argc );
DWORD ret;
if (needs_init) _init( 0, NULL, NULL );
- ret = wmain( __wine_main_argc, __wine_main_wargv );
+ ret = wmain( argc, argv );
if (needs_init) _fini();
ExitProcess( ret );
}
More information about the wine-cvs
mailing list