[PATCH 3/6] CMD.EXE: Handle command line as Unicode
Jason Edmeades
us at edmeades.me.uk
Sat May 5 13:20:19 CDT 2007
Note: Temporarily duplicate the command line and create an ANSI
version for the rest of the processing.
---
programs/cmd/wcmd.h | 1 +
programs/cmd/wcmdmain.c | 92 ++++++++++++++++++++++++++++++----------------
2 files changed, 61 insertions(+), 32 deletions(-)
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index 78db858..ab13595 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -26,6 +26,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
+#include <wine/unicode.h>
void WCMD_assoc (char *, BOOL);
void WCMD_batch (char *, char *, int, char *, HANDLE);
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index d0a08ec..85fe005 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -59,6 +59,9 @@ static char *WCMD_expand_envvar(char *start);
int main (int argc, char *argv[])
{
+ LPWSTR *argvW = NULL;
+ int args;
+ WCHAR *cmdW = NULL;
char string[1024];
char envvar[4];
char* cmd=NULL;
@@ -67,34 +70,44 @@ int main (int argc, char *argv[])
int opt_q;
int opt_t = 0;
+ /* Get a Unicode command line */
+ argvW = CommandLineToArgvW( GetCommandLineW(), &argc );
+ args = argc;
+
opt_c=opt_k=opt_q=opt_s=0;
- while (*argv!=NULL)
+ while (args > 0)
{
- char c;
- if ((*argv)[0]!='/' || (*argv)[1]=='\0') {
- argv++;
+ WCHAR c;
+ WINE_TRACE("Command line parm: '%s'\n", wine_dbgstr_w(*argvW));
+ if ((*argvW)[0]!='/' || (*argvW)[1]=='\0') {
+ argvW++;
+ args--;
continue;
}
- c=(*argv)[1];
- if (tolower(c)=='c') {
+ c=(*argvW)[1];
+ if (tolowerW(c)=='c') {
opt_c=1;
- } else if (tolower(c)=='q') {
+ } else if (tolowerW(c)=='q') {
opt_q=1;
- } else if (tolower(c)=='k') {
+ } else if (tolowerW(c)=='k') {
opt_k=1;
- } else if (tolower(c)=='s') {
+ } else if (tolowerW(c)=='s') {
opt_s=1;
- } else if (tolower(c)=='t' && (*argv)[2]==':') {
- opt_t=strtoul(&(*argv)[3], NULL, 16);
- } else if (tolower(c)=='x' || tolower(c)=='y') {
+ } else if (tolowerW(c)=='t' && (*argvW)[2]==':') {
+ opt_t=strtoulW(&(*argvW)[3], NULL, 16);
+ } else if (tolowerW(c)=='x' || tolowerW(c)=='y') {
/* Ignored for compatibility with Windows */
}
- if ((*argv)[2]==0)
- argv++;
+ if ((*argvW)[2]==0) {
+ argvW++;
+ args--;
+ }
else /* handle `cmd /cnotepad.exe` and `cmd /x/c ...` */
- *argv+=2;
+ {
+ *argvW+=2;
+ }
if (opt_c || opt_k) /* break out of parsing immediately after c or k */
break;
@@ -105,9 +118,10 @@ int main (int argc, char *argv[])
}
if (opt_c || opt_k) {
- int len,qcount;
- char** arg;
- char* p;
+ int len,qcount;
+ WCHAR** arg;
+ int argsLeft;
+ WCHAR* p;
/* opt_s left unflagged if the command starts with and contains exactly
* one quoted string (exactly two quote characters). The quoted string
@@ -117,10 +131,11 @@ int main (int argc, char *argv[])
/* Build the command to execute */
len = 0;
qcount = 0;
- for (arg = argv; *arg; arg++)
+ argsLeft = args;
+ for (arg = argvW; argsLeft>0; arg++,argsLeft--)
{
int has_space,bcount;
- char* a;
+ WCHAR* a;
has_space=0;
bcount=0;
@@ -143,7 +158,7 @@ int main (int argc, char *argv[])
}
a++;
}
- len+=(a-*arg)+1 /* for the separating space */;
+ len+=(a-*arg) + 1; /* for the separating space */
if (has_space)
{
len+=2; /* for the quotes */
@@ -154,10 +169,10 @@ int main (int argc, char *argv[])
if (qcount!=2)
opt_s=1;
- /* check argv[0] for a space and invalid characters */
+ /* check argvW[0] for a space and invalid characters */
if (!opt_s) {
opt_s=1;
- p=*argv;
+ p=*argvW;
while (*p!='\0') {
if (*p=='&' || *p=='<' || *p=='>' || *p=='(' || *p==')'
|| *p=='@' || *p=='^' || *p=='|') {
@@ -170,15 +185,16 @@ int main (int argc, char *argv[])
}
}
- cmd = HeapAlloc(GetProcessHeap(), 0, len);
- if (!cmd)
+ cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!cmdW)
exit(1);
- p = cmd;
- for (arg = argv; *arg; arg++)
+ p = cmdW;
+ argsLeft = args;
+ for (arg = argvW; argsLeft>0; arg++,argsLeft--)
{
int has_space,has_quote;
- char* a;
+ WCHAR* a;
/* Check for quotes and spaces in this argument */
has_space=has_quote=0;
@@ -202,7 +218,7 @@ int main (int argc, char *argv[])
*p++='"';
if (has_quote) {
int bcount;
- char* a;
+ WCHAR* a;
bcount=0;
a=*arg;
@@ -226,17 +242,27 @@ int main (int argc, char *argv[])
a++;
}
} else {
- strcpy(p,*arg);
- p+=strlen(*arg);
+ strcpyW(p,*arg);
+ p+=strlenW(*arg);
}
if (has_space)
*p++='"';
*p++=' ';
}
- if (p > cmd)
+ if (p > cmdW)
p--; /* remove last space */
*p = '\0';
+ /* FIXME: Convert back to ansi until more is in unicode */
+ cmd = HeapAlloc(GetProcessHeap(), 0, len);
+ if (!cmd) {
+ exit(1);
+ } else {
+ WideCharToMultiByte(CP_ACP, 0, cmdW, len, cmd, len, NULL, NULL);
+ }
+ WINE_TRACE("Input (U): '%s'\n", wine_dbgstr_w(cmdW));
+ WINE_TRACE("Input (A): '%s'\n", cmd);
+
/* strip first and last quote characters if opt_s; check for invalid
* executable is done later */
if (opt_s && *cmd=='\"')
@@ -254,6 +280,7 @@ int main (int argc, char *argv[])
else
WCMD_process_command(cmd);
HeapFree(GetProcessHeap(), 0, cmd);
+ HeapFree(GetProcessHeap(), 0, cmdW);
return errorlevel;
}
@@ -338,6 +365,7 @@ int main (int argc, char *argv[])
if (opt_k) {
WCMD_process_command(cmd);
HeapFree(GetProcessHeap(), 0, cmd);
+ HeapFree(GetProcessHeap(), 0, cmdW);
}
/*
--
1.5.0
More information about the wine-patches
mailing list