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