The only difference between the two versions is that this one doesn't prefix the result with the command line's length.
Signed-off-by: Robbert van der Helm mail@robbertvanderhelm.nl --- Instead of having having four almost identical copies of this function spread around Wine's code base (two for WCHAR*, two for char*), someone who's more familiar with Wine's code base than I am should probably merge these and move them to somewhere in `include/wine/`. --- programs/winedbg/tgt_active.c | 110 ++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+)
diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c index 3372a001dfbb..ad46d6b5fc5e 100644 --- a/programs/winedbg/tgt_active.c +++ b/programs/winedbg/tgt_active.c @@ -770,6 +770,116 @@ static void output_system_info(void) } }
+/*********************************************************************** + * build_command_line + * + * Build the command line of a process from the argv array. + * Copied from winevdm, which in turn adapted it from ENV_BuildCommandLine. The difference between + * this and the winevdm version is the command line is not prefixed with its length. + */ +static char *build_command_line(char **argv) +{ + int len; + char *p, **arg, *cmd_line; + + len = 0; + for (arg = argv; *arg; arg++) + { + BOOL has_space; + int bcount; + char* a; + + has_space=FALSE; + bcount=0; + a=*arg; + if( !*a ) has_space=TRUE; + while (*a!='\0') { + if (*a=='\') { + bcount++; + } else { + if (*a==' ' || *a=='\t') { + has_space=TRUE; + } else if (*a=='"') { + /* doubling of '' preceding a '"', + * plus escaping of said '"' + */ + len+=2*bcount+1; + } + bcount=0; + } + a++; + } + len+=(a-*arg)+1 /* for the separating space */; + if (has_space) + len+=2; /* for the quotes */ + } + + if (!(cmd_line = HeapAlloc( GetProcessHeap(), 0, len ? len : 1 ))) + return NULL; + + p = cmd_line; + for (arg = argv; *arg; arg++) + { + BOOL has_space,has_quote; + char* a; + + /* Check for quotes and spaces in this argument */ + has_space=has_quote=FALSE; + a=*arg; + if( !*a ) has_space=TRUE; + while (*a!='\0') { + if (*a==' ' || *a=='\t') { + has_space=TRUE; + if (has_quote) + break; + } else if (*a=='"') { + has_quote=TRUE; + if (has_space) + break; + } + a++; + } + + /* Now transfer it to the command line */ + if (has_space) + *p++='"'; + if (has_quote) { + int bcount; + + bcount=0; + a=*arg; + while (*a!='\0') { + if (*a=='\') { + *p++=*a; + bcount++; + } else { + if (*a=='"') { + int i; + + /* Double all the '\' preceding this '"', plus one */ + for (i=0;i<=bcount;i++) + *p++='\'; + *p++='"'; + } else { + *p++=*a; + } + bcount=0; + } + a++; + } + } else { + strcpy(p,*arg); + p+=strlen(*arg); + } + if (has_space) + *p++='"'; + *p++=' '; + } + if (len) p--; /* remove last space */ + *p = '\0'; + return cmd_line; +} + /****************************************************************** * dbg_active_attach *
This way the arguments in `winedbg [--gdb] 'foo bar.exe' arg1 'arg 2'` get treated in the same way as those in `wine 'foo bar.exe' arg1 'arg 2'`. Previously, winedbg would essentially concatenate the arguments from argv into a single command line without quoting individual arguments. With the previously mentioned winedbg invocation, this would thus cause `foo` to be run with the argumetns `bar.exe` `arg1` `arg` and `2`, instead of `foo bar.exe` being run with the expected two arguments.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51844 Signed-off-by: Robbert van der Helm mail@robbertvanderhelm.nl --- This will break existing usages that manually quote their arguments (in the same way as `build_command_line()` does), but I feel like staying consistent with the way commands line arguments normally work in Unix-land (and in `gdb --args`) would lead to fewer surprises overall. --- programs/winedbg/tgt_active.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c index ad46d6b5fc5e..ec89039c1bfd 100644 --- a/programs/winedbg/tgt_active.c +++ b/programs/winedbg/tgt_active.c @@ -921,28 +921,15 @@ enum dbg_start dbg_active_attach(int argc, char* argv[]) */ enum dbg_start dbg_active_launch(int argc, char* argv[]) { - int i, len; LPSTR cmd_line;
if (argc == 0) return start_error_parse;
- if (!(cmd_line = HeapAlloc(GetProcessHeap(), 0, len = 1))) + if (!(cmd_line = build_command_line(argv))) { - oom_leave: dbg_printf("Out of memory\n"); return start_error_init; } - cmd_line[0] = '\0'; - - for (i = 0; i < argc; i++) - { - len += strlen(argv[i]) + 1; - if (!(cmd_line = HeapReAlloc(GetProcessHeap(), 0, cmd_line, len))) - goto oom_leave; - strcat(cmd_line, argv[i]); - cmd_line[len - 2] = ' '; - cmd_line[len - 1] = '\0'; - }
if (!dbg_start_debuggee(cmd_line)) {