[PATCH 1/2] programs/wineconsole: use wmain as entry point

Eric Pouech eric.pouech at gmail.com
Wed Apr 27 07:52:25 CDT 2022


Signed-off-by: Eric Pouech <eric.pouech at gmail.com>

---
 programs/wineconsole/Makefile.in   |    3 -
 programs/wineconsole/wineconsole.c |   95 ++++++++++++++++++++++++++++++++++--
 2 files changed, 91 insertions(+), 7 deletions(-)

diff --git a/programs/wineconsole/Makefile.in b/programs/wineconsole/Makefile.in
index b859ef8a27a..08ad51d2b6a 100644
--- a/programs/wineconsole/Makefile.in
+++ b/programs/wineconsole/Makefile.in
@@ -1,6 +1,5 @@
 MODULE    = wineconsole.exe
-IMPORTS   = advapi32
-DELAYIMPORTS = comctl32 user32 gdi32
+DELAYIMPORTS = user32
 
 EXTRADLLFLAGS = -mwindows -municode
 
diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c
index 1924bf791e6..c703127c238 100644
--- a/programs/wineconsole/wineconsole.c
+++ b/programs/wineconsole/wineconsole.c
@@ -32,14 +32,101 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(console);
 
-int WINAPI wWinMain( HINSTANCE inst, HINSTANCE prev, WCHAR *cmdline, INT show )
+static const unsigned int EC_INTERNAL = 255; /* value of exit_code for internal errors */
+
+/***********************************************************************
+ *           build_command_line
+ *
+ * Build the command line of a process from the argv array.
+ * (copied from dlls/ntdll/unix/env.c)
+ *
+ * We must quote and escape characters so that the argv array can be rebuilt
+ * from the command line:
+ * - spaces and tabs must be quoted
+ *   'a b'   -> '"a b"'
+ * - quotes must be escaped
+ *   '"'     -> '\"'
+ * - if '\'s are followed by a '"', they must be doubled and followed by '\"',
+ *   resulting in an odd number of '\' followed by a '"'
+ *   '\"'    -> '\\\"'
+ *   '\\"'   -> '\\\\\"'
+ * - '\'s are followed by the closing '"' must be doubled,
+ *   resulting in an even number of '\' followed by a '"'
+ *   ' \'    -> '" \\"'
+ *   ' \\'    -> '" \\\\"'
+ * - '\'s that are not followed by a '"' can be left as is
+ *   'a\b'   == 'a\b'
+ *   'a\\b'  == 'a\\b'
+ */
+static WCHAR *build_command_line( WCHAR **wargv )
+{
+    int len;
+    WCHAR **arg, *ret;
+    LPWSTR p;
+
+    len = 1;
+    for (arg = wargv; *arg; arg++) len += 3 + 2 * wcslen( *arg );
+    if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL;
+
+    p = ret;
+    for (arg = wargv; *arg; arg++)
+    {
+        BOOL has_space, has_quote;
+        int i, bcount;
+        WCHAR *a;
+
+        /* check for quotes and spaces in this argument (first arg is always quoted) */
+        has_space = (arg == wargv) || !**arg || wcschr( *arg, ' ' ) || wcschr( *arg, '\t' );
+        has_quote = wcschr( *arg, '"' ) != NULL;
+
+        /* now transfer it to the command line */
+        if (has_space) *p++ = '"';
+        if (has_quote || has_space)
+        {
+            bcount = 0;
+            for (a = *arg; *a; a++)
+            {
+                if (*a == '\\') bcount++;
+                else
+                {
+                    if (*a == '"') /* double all the '\\' preceding this '"', plus one */
+                        for (i = 0; i <= bcount; i++) *p++ = '\\';
+                    bcount = 0;
+                }
+                *p++ = *a;
+            }
+        }
+        else
+        {
+            wcscpy( p, *arg );
+            p += wcslen( p );
+        }
+        if (has_space)
+        {
+            /* Double all the '\' preceding the closing quote */
+            for (i = 0; i < bcount; i++) *p++ = '\\';
+            *p++ = '"';
+        }
+        *p++ = ' ';
+    }
+    if (p > ret) p--;  /* remove last space */
+    *p = 0;
+    if (p - ret >= 32767)
+    {
+        ERR( "command line too long (%Iu)\n", p - ret );
+        exit( EC_INTERNAL );
+    }
+    return ret;
+}
+
+int wmain( int argc, WCHAR *argv[] )
 {
     STARTUPINFOW startup = { sizeof(startup) };
     PROCESS_INFORMATION info;
-    WCHAR *cmd = cmdline;
+    WCHAR *cmd;
     DWORD exit_code;
 
-    static WCHAR default_cmd[] = L"cmd";
+    cmd = argc > 1 ? build_command_line( &argv[1] ) : wcsdup( L"cmd.exe" );
 
     FreeConsole(); /* make sure we're not connected to inherited console */
     if (!AllocConsole())
@@ -48,8 +135,6 @@ int WINAPI wWinMain( HINSTANCE inst, HINSTANCE prev, WCHAR *cmdline, INT show )
         return 1;
     }
 
-    if (!*cmd) cmd = default_cmd;
-
     startup.dwFlags    = STARTF_USESTDHANDLES;
     startup.hStdInput  = CreateFileW( L"CONIN$",  GENERIC_READ | GENERIC_WRITE, 0, NULL,
                                       OPEN_EXISTING, 0, 0 );




More information about the wine-devel mailing list