[PATCH 4/6] CMD.EXE: Convert cmd into unicode

Jason Edmeades us at edmeades.me.uk
Mon May 7 09:05:49 CDT 2007


Apologies for the size of this patch - I tried 3 or 4 ways of converting
chunks to unicode and always ended up duplicating huge bits of code and
having problems keeping track of duplicated variables that in the end I
did the lot in one go.

The good news is the majority of the unicode functions slotted in nicely
using the wine unicode.h functions. strdupW was missing (would be good to
add that in there, but I've done a WCMD_strdupW function in the patsh) and
I had problems with strncpyW being missing (lstrcpyn has slightly different
characteristics). sprintfW with strings and formatting is broken - I used
wvsprintf which sufficed.

I've tested as much of this as I could, including various scraps of batch
files I had lying around, but I'll monitor bugzilla for any problems.
---
 programs/cmd/Cs.rc       |    4 +
 programs/cmd/De.rc       |    4 +
 programs/cmd/En.rc       |    4 +
 programs/cmd/Es.rc       |    4 +
 programs/cmd/Fr.rc       |    4 +
 programs/cmd/Ja.rc       |    4 +
 programs/cmd/Ko.rc       |    4 +
 programs/cmd/Makefile.in |    1 +
 programs/cmd/Nl.rc       |    4 +
 programs/cmd/No.rc       |    4 +
 programs/cmd/Pl.rc       |    4 +
 programs/cmd/Pt.rc       |    4 +
 programs/cmd/Ru.rc       |    4 +
 programs/cmd/Si.rc       |    4 +
 programs/cmd/Tr.rc       |    4 +
 programs/cmd/batch.c     |  192 ++++++-----
 programs/cmd/builtins.c  |  863 +++++++++++++++++++++++++---------------------
 programs/cmd/directory.c |  324 ++++++++++--------
 programs/cmd/wcmd.h      |  102 +++---
 programs/cmd/wcmdmain.c  |  751 +++++++++++++++++++++++++---------------
 20 files changed, 1324 insertions(+), 965 deletions(-)

diff --git a/programs/cmd/Cs.rc b/programs/cmd/Cs.rc
index 82bf49b..af7820b 100644
--- a/programs/cmd/Cs.rc
+++ b/programs/cmd/Cs.rc
@@ -263,4 +263,8 @@ Zadejte HELP <pøíkaz> pro podrobnìjší informace o nìkterém z výše uvedených pøík
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/De.rc b/programs/cmd/De.rc
index da673ea..39f615e 100644
--- a/programs/cmd/De.rc
+++ b/programs/cmd/De.rc
@@ -280,4 +280,8 @@ obigen Befehle erhalten.\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/En.rc b/programs/cmd/En.rc
index 132938a..42bf552 100644
--- a/programs/cmd/En.rc
+++ b/programs/cmd/En.rc
@@ -267,4 +267,8 @@ Enter HELP <command> for further information on any of the above commands\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Es.rc b/programs/cmd/Es.rc
index eaa3f7b..674d9bc 100644
--- a/programs/cmd/Es.rc
+++ b/programs/cmd/Es.rc
@@ -275,4 +275,8 @@ Introduzca HELP <comando> para más información sobre cualquiera de los comandos\
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Fr.rc b/programs/cmd/Fr.rc
index 78b39de..7ecd58c 100644
--- a/programs/cmd/Fr.rc
+++ b/programs/cmd/Fr.rc
@@ -257,4 +257,8 @@ Entrez HELP <commande> pour plus d'informations sur les commandes ci-dessus\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Ja.rc b/programs/cmd/Ja.rc
index 5cbd119..94a9538 100644
--- a/programs/cmd/Ja.rc
+++ b/programs/cmd/Ja.rc
@@ -261,4 +261,8 @@ EXIT\t\tCMD‚ðI—¹\n\n\
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Ko.rc b/programs/cmd/Ko.rc
index 43395b9..d4331c0 100644
--- a/programs/cmd/Ko.rc
+++ b/programs/cmd/Ko.rc
@@ -259,4 +259,8 @@ HELP <¸í·É>À» Ä¡¸é ±× ¸í·ÉÀÇ »ó¼¼ÇÑ Á¤º¸¸¦ º¸¿©ÁÜ\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Makefile.in b/programs/cmd/Makefile.in
index 3a81838..c383344 100644
--- a/programs/cmd/Makefile.in
+++ b/programs/cmd/Makefile.in
@@ -4,6 +4,7 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = cmd.exe
 APPMODE   = -mconsole
+EXTRADEFS = -DUNICODE
 IMPORTS   = shell32 user32 advapi32 kernel32
 
 C_SRCS = \
diff --git a/programs/cmd/Nl.rc b/programs/cmd/Nl.rc
index 5a12123..71f8543 100644
--- a/programs/cmd/Nl.rc
+++ b/programs/cmd/Nl.rc
@@ -260,4 +260,8 @@ type HELP <opdracht> voor meer informatie over bovengenoemde opdrachten\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/No.rc b/programs/cmd/No.rc
index 25047a5..3fcf588 100644
--- a/programs/cmd/No.rc
+++ b/programs/cmd/No.rc
@@ -258,4 +258,8 @@ Skriv «HELP <kommando>» for mer informasjon om kommandoene ovenfor\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Pl.rc b/programs/cmd/Pl.rc
index 67c659c..4950323 100644
--- a/programs/cmd/Pl.rc
+++ b/programs/cmd/Pl.rc
@@ -262,4 +262,8 @@ Wpisz HELP <komenda> dla dok³adniejszych informacji o komendzie\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Pt.rc b/programs/cmd/Pt.rc
index 17090dd..4e81852 100644
--- a/programs/cmd/Pt.rc
+++ b/programs/cmd/Pt.rc
@@ -470,4 +470,8 @@ Digite HELP <comando> para mais informações sobre alguns dos comandos acima\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Ru.rc b/programs/cmd/Ru.rc
index d3860c4..a4ffe73 100644
--- a/programs/cmd/Ru.rc
+++ b/programs/cmd/Ru.rc
@@ -273,4 +273,8 @@ EXIT\t\tÂûéòè èç CMD\n\n\
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Si.rc b/programs/cmd/Si.rc
index 8060fad..eb1042c 100644
--- a/programs/cmd/Si.rc
+++ b/programs/cmd/Si.rc
@@ -259,4 +259,8 @@ Enter HELP <command> for further information on any of the above commands\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/Tr.rc b/programs/cmd/Tr.rc
index 69e707e..b8db7b0 100644
--- a/programs/cmd/Tr.rc
+++ b/programs/cmd/Tr.rc
@@ -261,4 +261,8 @@ Yukarýdaki komutlar hakkýnda daha fazla bilgi için HELP <komut> girin\n"
   WCMD_ARGERR, "Parameter error\n"
   WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n"
   WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?"
+  WCMD_NOPATH, "PATH not found\n"
+  WCMD_ANYKEY,"Press Return key to continue: "
+  WCMD_CONSTITLE,"Wine Command Prompt"  
+  WCMD_VERSION,"CMD Version %s\n\n"
 }
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 9824fe5..67efc32 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -21,7 +21,7 @@
 #include "wcmd.h"
 
 extern int echo_mode;
-extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
 extern BATCH_CONTEXT *context;
 extern DWORD errorlevel;
 
@@ -41,30 +41,31 @@ extern DWORD errorlevel;
  * a label to goto once opened.
  */
 
-void WCMD_batch (char *file, char *command, int called, char *startLabel, HANDLE pgmHandle) {
+void WCMD_batch (WCHAR *file, WCHAR *command, int called, WCHAR *startLabel, HANDLE pgmHandle) {
 
 #define WCMD_BATCH_EXT_SIZE 5
 
   HANDLE h = INVALID_HANDLE_VALUE;
-  char string[MAXSTRING];
-  char extension_batch[][WCMD_BATCH_EXT_SIZE] = {".bat",".cmd"};
-  char extension_exe[WCMD_BATCH_EXT_SIZE] = ".exe";
+  WCHAR string[MAXSTRING];
+  WCHAR extension_batch[][WCMD_BATCH_EXT_SIZE] = {{'.','b','a','t','\0'},
+                                                  {'.','c','m','d','\0'}};
+  WCHAR extension_exe[WCMD_BATCH_EXT_SIZE] = {'.','e','x','e','\0'};
   unsigned int  i;
   BATCH_CONTEXT *prev_context;
 
   if (startLabel == NULL) {
-    for(i=0; (i<(sizeof(extension_batch)/WCMD_BATCH_EXT_SIZE)) &&
+    for(i=0; (i<((sizeof(extension_batch) * sizeof(WCHAR))/WCMD_BATCH_EXT_SIZE)) &&
              (h == INVALID_HANDLE_VALUE); i++) {
-    strcpy (string, file);
-    CharLower (string);
-      if (strstr (string, extension_batch[i]) == NULL) strcat (string, extension_batch[i]);
-    h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ,
-                    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+      strcpyW (string, file);
+      CharLower (string);
+      if (strstrW (string, extension_batch[i]) == NULL) strcatW (string, extension_batch[i]);
+      h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ,
+                      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     }
     if (h == INVALID_HANDLE_VALUE) {
-      strcpy (string, file);
+      strcpyW (string, file);
       CharLower (string);
-      if (strstr (string, extension_exe) == NULL) strcat (string, extension_exe);
+      if (strstrW (string, extension_exe) == NULL) strcatW (string, extension_exe);
       h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ,
                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
       if (h != INVALID_HANDLE_VALUE) {
@@ -95,7 +96,7 @@ void WCMD_batch (char *file, char *command, int called, char *startLabel, HANDLE
 
   /* If processing a call :label, 'goto' the label in question */
   if (startLabel) {
-    strcpy(param1, startLabel);
+    strcpyW(param1, startLabel);
     WCMD_goto();
   }
 
@@ -105,7 +106,7 @@ void WCMD_batch (char *file, char *command, int called, char *startLabel, HANDLE
  */
 
   while (context -> skip_rest == FALSE && WCMD_fgets (string, sizeof(string), h)) {
-      if (strlen(string) == MAXSTRING -1) {
+      if (strlenW(string) == MAXSTRING -1) {
           WCMD_output_asis( WCMD_LoadMessage(WCMD_TRUNCATEDLINE));
           WCMD_output_asis( string);
           WCMD_output_asis( newline);
@@ -141,11 +142,11 @@ void WCMD_batch (char *file, char *command, int called, char *startLabel, HANDLE
  *	Also returns a pointer to the location of the parameter in the command line.
  */
 
-char *WCMD_parameter (char *s, int n, char **where) {
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) {
 
   int i = 0;
-  static char param[MAX_PATH];
-  char *p;
+  static WCHAR param[MAX_PATH];
+  WCHAR *p;
 
   if (where != NULL) *where = NULL;
   p = param;
@@ -211,32 +212,32 @@ char *WCMD_parameter (char *s, int n, char **where) {
  * the LF (or CRLF) from the line.
  */
 
-char *WCMD_fgets (char *s, int n, HANDLE h) {
+WCHAR *WCMD_fgets (WCHAR *s, int noChars, HANDLE h) {
 
   DWORD bytes;
   BOOL status;
-  char *p;
+  WCHAR *p;
 
   p = s;
   do {
-    status = ReadFile (h, s, 1, &bytes, NULL);
+    status = WCMD_ReadFile (h, s, 1, &bytes, NULL);
     if ((status == 0) || ((bytes == 0) && (s == p))) return NULL;
     if (*s == '\n') bytes = 0;
     else if (*s != '\r') {
       s++;
-      n--;
+      noChars--;
     }
     *s = '\0';
-  } while ((bytes == 1) && (n > 1));
+  } while ((bytes == 1) && (noChars > 1));
   return p;
 }
 
 /* WCMD_splitpath - copied from winefile as no obvious way to use it otherwise */
-void WCMD_splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext)
+void WCMD_splitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext)
 {
-        const CHAR* end; /* end of processed string */
-	const CHAR* p;	 /* search pointer */
-	const CHAR* s;	 /* copy pointer */
+        const WCHAR* end; /* end of processed string */
+	const WCHAR* p;	 /* search pointer */
+	const WCHAR* s;	 /* copy pointer */
 
 	/* extract drive name */
 	if (path[0] && path[1]==':') {
@@ -307,7 +308,7 @@ void WCMD_splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ex
  *  To work out the length of the modifier:
  *
  *  Note: In the case of %0-9 knowing the end of the modifier is easy,
- *    but in a for loop, the for end character may also be a modifier
+ *    but in a for loop, the for end WCHARacter may also be a modifier
  *    eg. for %a in (c:\a.a) do echo XXX
  *             where XXX = %~a    (just ~)
  *                         %~aa   (~ and attributes)
@@ -317,22 +318,22 @@ void WCMD_splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ex
  *  Hence search forwards until find an invalid modifier, and then
  *  backwards until find for variable or 0-9
  */
-void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
+void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable) {
 
 #define NUMMODIFIERS 11
-  const char validmodifiers[NUMMODIFIERS] = {
+  const WCHAR validmodifiers[NUMMODIFIERS] = {
         '~', 'f', 'd', 'p', 'n', 'x', 's', 'a', 't', 'z', '$'
   };
-  const char space[] = " ";
+  const WCHAR space[] = {' ', '\0'};
 
   WIN32_FILE_ATTRIBUTE_DATA fileInfo;
-  char  outputparam[MAX_PATH];
-  char  finaloutput[MAX_PATH];
-  char  fullfilename[MAX_PATH];
-  char  thisoutput[MAX_PATH];
-  char  *pos            = *start+1;
-  char  *firstModifier  = pos;
-  char  *lastModifier   = NULL;
+  WCHAR  outputparam[MAX_PATH];
+  WCHAR  finaloutput[MAX_PATH];
+  WCHAR  fullfilename[MAX_PATH];
+  WCHAR  thisoutput[MAX_PATH];
+  WCHAR  *pos            = *start+1;
+  WCHAR  *firstModifier  = pos;
+  WCHAR  *lastModifier   = NULL;
   int   modifierLen     = 0;
   BOOL  finished        = FALSE;
   int   i               = 0;
@@ -340,10 +341,10 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
   BOOL  skipFileParsing = FALSE;
   BOOL  doneModifier    = FALSE;
 
-  /* Search forwards until find invalid character modifier */
+  /* Search forwards until find invalid WCHARacter modifier */
   while (!finished) {
 
-    /* Work on the previous character */
+    /* Work on the previous WCHARacter */
     if (lastModifier != NULL) {
 
       for (i=0; i<NUMMODIFIERS; i++) {
@@ -374,10 +375,10 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
   /* Now make sure the position we stopped at is a valid parameter */
   if (!(*lastModifier >= '0' || *lastModifier <= '9') &&
       (forVariable != NULL) &&
-      (toupper(*lastModifier) != toupper(*forVariable)))  {
+      (toupperW(*lastModifier) != toupperW(*forVariable)))  {
 
     /* Its not... Step backwards until it matches or we get to the start */
-    while (toupper(*lastModifier) != toupper(*forVariable) &&
+    while (toupperW(*lastModifier) != toupperW(*forVariable) &&
           lastModifier > firstModifier) {
       lastModifier--;
     }
@@ -386,7 +387,7 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
 
   /* Extract the parameter to play with */
   if ((*lastModifier >= '0' && *lastModifier <= '9')) {
-    strcpy(outputparam, WCMD_parameter (context -> command,
+    strcpyW(outputparam, WCMD_parameter (context -> command,
                  *lastModifier-'0' + context -> shift_count[*lastModifier-'0'], NULL));
   } else {
     /* FIXME: Retrieve 'for' variable %c\n", *lastModifier); */
@@ -407,27 +408,26 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
 
   /* 1. Handle '~' : Strip surrounding quotes */
   if (outputparam[0]=='"' &&
-      memchr(firstModifier, '~', modifierLen) != NULL) {
-    int len = strlen(outputparam);
+      memchrW(firstModifier, '~', modifierLen) != NULL) {
+    int len = strlenW(outputparam);
     if (outputparam[len-1] == '"') {
         outputparam[len-1]=0x00;
         len = len - 1;
     }
-    memmove(outputparam, &outputparam[1], len-1);
+    memmove(outputparam, &outputparam[1], (len * sizeof(WCHAR))-1);
   }
 
   /* 2. Handle the special case of a $ */
-  if (memchr(firstModifier, '$', modifierLen) != NULL) {
+  if (memchrW(firstModifier, '$', modifierLen) != NULL) {
     /* Special Case: Search envar specified in $[envvar] for outputparam
        Note both $ and : are guaranteed otherwise check above would fail */
-    char *start = strchr(firstModifier, '$') + 1;
-    char *end   = strchr(firstModifier, ':');
-    char env[MAX_PATH];
-    char fullpath[MAX_PATH];
+    WCHAR *start = strchrW(firstModifier, '$') + 1;
+    WCHAR *end   = strchrW(firstModifier, ':');
+    WCHAR env[MAX_PATH];
+    WCHAR fullpath[MAX_PATH];
 
-    /* Extract the env var */
-    strncpy(env, start, (end-start));
-    env[(end-start)] = 0x00;
+    /* Extract the env var (lstrcpynW inserts null when truncating) */
+    lstrcpynW(env, start, (end-start)+1);
 
     /* If env var not found, return emptry string */
     if ((GetEnvironmentVariable(env, fullpath, MAX_PATH) == 0) ||
@@ -445,15 +445,16 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
     if (GetFullPathName(outputparam, MAX_PATH, fullfilename, NULL) == 0)
       return;
 
-    exists = GetFileAttributesExA(fullfilename, GetFileExInfoStandard,
+    exists = GetFileAttributesExW(fullfilename, GetFileExInfoStandard,
                                   &fileInfo);
 
     /* 2. Handle 'a' : Output attributes */
     if (exists &&
-        memchr(firstModifier, 'a', modifierLen) != NULL) {
+        memchrW(firstModifier, 'a', modifierLen) != NULL) {
 
+      WCHAR defaults[] = {'-','-','-','-','-','-','-','-','-','\0'};
       doneModifier = TRUE;
-      strcpy(thisoutput, "---------");
+      strcpyW(thisoutput, defaults);
       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
         thisoutput[0]='d';
       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
@@ -469,114 +470,115 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
       /* FIXME: What are 6 and 7? */
       if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
         thisoutput[8]='l';
-      strcat(finaloutput, thisoutput);
+      strcatW(finaloutput, thisoutput);
     }
 
     /* 3. Handle 't' : Date+time */
     if (exists &&
-        memchr(firstModifier, 't', modifierLen) != NULL) {
+        memchrW(firstModifier, 't', modifierLen) != NULL) {
 
       SYSTEMTIME systime;
       int datelen;
 
       doneModifier = TRUE;
-      if (finaloutput[0] != 0x00) strcat(finaloutput, space);
+      if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
 
       /* Format the time */
       FileTimeToSystemTime(&fileInfo.ftLastWriteTime, &systime);
       GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime,
                         NULL, thisoutput, MAX_PATH);
-      strcat(thisoutput, space);
-      datelen = strlen(thisoutput);
+      strcatW(thisoutput, space);
+      datelen = strlenW(thisoutput);
       GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &systime,
                         NULL, (thisoutput+datelen), MAX_PATH-datelen);
-      strcat(finaloutput, thisoutput);
+      strcatW(finaloutput, thisoutput);
     }
 
     /* 4. Handle 'z' : File length */
     if (exists &&
-        memchr(firstModifier, 'z', modifierLen) != NULL) {
+        memchrW(firstModifier, 'z', modifierLen) != NULL) {
       /* FIXME: Output full 64 bit size (sprintf does not support I64 here) */
       ULONG/*64*/ fullsize = /*(fileInfo.nFileSizeHigh << 32) +*/
                                   fileInfo.nFileSizeLow;
+      WCHAR fmt[] = {'%','u','\0'};
 
       doneModifier = TRUE;
-      if (finaloutput[0] != 0x00) strcat(finaloutput, space);
-      sprintf(thisoutput, "%u", fullsize);
-      strcat(finaloutput, thisoutput);
+      if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
+      wsprintf(thisoutput, fmt, fullsize);
+      strcatW(finaloutput, thisoutput);
     }
 
     /* 4. Handle 's' : Use short paths (File doesn't have to exist) */
-    if (memchr(firstModifier, 's', modifierLen) != NULL) {
-      if (finaloutput[0] != 0x00) strcat(finaloutput, space);
+    if (memchrW(firstModifier, 's', modifierLen) != NULL) {
+      if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
       /* Don't flag as doneModifier - %~s on its own is processed later */
       GetShortPathName(outputparam, outputparam, sizeof(outputparam));
     }
 
     /* 5. Handle 'f' : Fully qualified path (File doesn't have to exist) */
     /*      Note this overrides d,p,n,x                                 */
-    if (memchr(firstModifier, 'f', modifierLen) != NULL) {
+    if (memchrW(firstModifier, 'f', modifierLen) != NULL) {
       doneModifier = TRUE;
-      if (finaloutput[0] != 0x00) strcat(finaloutput, space);
-      strcat(finaloutput, fullfilename);
+      if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
+      strcatW(finaloutput, fullfilename);
     } else {
 
-      char drive[10];
-      char dir[MAX_PATH];
-      char fname[MAX_PATH];
-      char ext[MAX_PATH];
+      WCHAR drive[10];
+      WCHAR dir[MAX_PATH];
+      WCHAR fname[MAX_PATH];
+      WCHAR ext[MAX_PATH];
       BOOL doneFileModifier = FALSE;
 
-      if (finaloutput[0] != 0x00) strcat(finaloutput, space);
+      if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
 
       /* Split into components */
       WCMD_splitpath(fullfilename, drive, dir, fname, ext);
 
       /* 5. Handle 'd' : Drive Letter */
-      if (memchr(firstModifier, 'd', modifierLen) != NULL) {
-        strcat(finaloutput, drive);
+      if (memchrW(firstModifier, 'd', modifierLen) != NULL) {
+        strcatW(finaloutput, drive);
         doneModifier = TRUE;
         doneFileModifier = TRUE;
       }
 
       /* 6. Handle 'p' : Path */
-      if (memchr(firstModifier, 'p', modifierLen) != NULL) {
-        strcat(finaloutput, dir);
+      if (memchrW(firstModifier, 'p', modifierLen) != NULL) {
+        strcatW(finaloutput, dir);
         doneModifier = TRUE;
         doneFileModifier = TRUE;
       }
 
       /* 7. Handle 'n' : Name */
-      if (memchr(firstModifier, 'n', modifierLen) != NULL) {
-        strcat(finaloutput, fname);
+      if (memchrW(firstModifier, 'n', modifierLen) != NULL) {
+        strcatW(finaloutput, fname);
         doneModifier = TRUE;
         doneFileModifier = TRUE;
       }
 
       /* 8. Handle 'x' : Ext */
-      if (memchr(firstModifier, 'x', modifierLen) != NULL) {
-        strcat(finaloutput, ext);
+      if (memchrW(firstModifier, 'x', modifierLen) != NULL) {
+        strcatW(finaloutput, ext);
         doneModifier = TRUE;
         doneFileModifier = TRUE;
       }
 
       /* If 's' but no other parameter, dump the whole thing */
       if (!doneFileModifier &&
-          memchr(firstModifier, 's', modifierLen) != NULL) {
+          memchrW(firstModifier, 's', modifierLen) != NULL) {
         doneModifier = TRUE;
-        if (finaloutput[0] != 0x00) strcat(finaloutput, space);
-        strcat(finaloutput, outputparam);
+        if (finaloutput[0] != 0x00) strcatW(finaloutput, space);
+        strcatW(finaloutput, outputparam);
       }
     }
   }
 
   /* If No other modifier processed,  just add in parameter */
-  if (!doneModifier) strcpy(finaloutput, outputparam);
+  if (!doneModifier) strcpyW(finaloutput, outputparam);
 
   /* Finish by inserting the replacement into the string */
-  pos = strdup (lastModifier+1);
-  strcpy(*start, finaloutput);
-  strcat(*start, pos);
+  pos = WCMD_strdupW(lastModifier+1);
+  strcpyW(*start, finaloutput);
+  strcatW(*start, pos);
   free(pos);
 }
 
@@ -586,16 +588,16 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) {
  *	If there is a leading ':', calls within this batch program
  *	otherwise launches another program.
  */
-void WCMD_call (char *command) {
+void WCMD_call (WCHAR *command) {
 
   /* Run other program if no leading ':' */
   if (*command != ':') {
     WCMD_run_program(command, 1);
   } else {
 
-    char gotoLabel[MAX_PATH];
+    WCHAR gotoLabel[MAX_PATH];
 
-    strcpy(gotoLabel, param1);
+    strcpyW(gotoLabel, param1);
 
     if (context) {
 
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 5c6510f..86b3bca 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -40,19 +40,29 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(cmd);
 
-void WCMD_execute (char *orig_command, char *parameter, char *substitution);
+void WCMD_execute (WCHAR *orig_command, WCHAR *parameter, WCHAR *substitution);
 
 struct env_stack *saved_environment;
 struct env_stack *pushd_directories;
 
 extern HINSTANCE hinst;
-extern char *inbuilt[];
+extern WCHAR *inbuilt[];
 extern int echo_mode, verify_mode, defaultColor;
-extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
 extern BATCH_CONTEXT *context;
 extern DWORD errorlevel;
 
-
+static const WCHAR dotW[]    = {'.','\0'};
+static const WCHAR dotdotW[] = {'.','.','\0'};
+static const WCHAR slashW[]  = {'\\','\0'};
+static const WCHAR starW[]   = {'*','\0'};
+static const WCHAR equalW[]  = {'=','\0'};
+static const WCHAR fslashW[] = {'/','\0'};
+static const WCHAR onW[]  = {'O','N','\0'};
+static const WCHAR offW[] = {'O','F','F','\0'};
+static const WCHAR parmY[] = {'/','Y','\0'};
+static const WCHAR parmNoY[] = {'/','-','Y','\0'};
+static const WCHAR nullW[] = {'\0'};
 
 /****************************************************************************
  * WCMD_clear_screen
@@ -105,55 +115,56 @@ void WCMD_copy (void) {
   WIN32_FIND_DATA fd;
   HANDLE hff;
   BOOL force, status;
-  char outpath[MAX_PATH], inpath[MAX_PATH], *infile, copycmd[3];
+  WCHAR outpath[MAX_PATH], inpath[MAX_PATH], *infile, copycmd[3];
   DWORD len;
+  const WCHAR copyCmdW[] = {'C','O','P','Y','C','M','D','\0'};
 
   if (param1[0] == 0x00) {
     WCMD_output (WCMD_LoadMessage(WCMD_NOARG));
     return;
   }
 
-  if ((strchr(param1,'*') != NULL) && (strchr(param1,'%') != NULL)) {
-    WCMD_output ("Wildcards not yet supported\n");
+  if ((strchrW(param1,'*') != NULL) && (strchrW(param1,'%') != NULL)) {
+    WCMD_output (WCMD_LoadMessage(WCMD_NYI));
     return;
   }
 
   /* If no destination supplied, assume current directory */
   if (param2[0] == 0x00) {
-      strcpy(param2, ".");
+      strcpyW(param2, dotW);
   }
 
-  GetFullPathName (param2, sizeof(outpath), outpath, NULL);
-  if (outpath[strlen(outpath) - 1] == '\\')
-      outpath[strlen(outpath) - 1] = '\0';
+  GetFullPathName (param2, sizeof(outpath)/sizeof(WCHAR), outpath, NULL);
+  if (outpath[strlenW(outpath) - 1] == '\\')
+      outpath[strlenW(outpath) - 1] = '\0';
   hff = FindFirstFile (outpath, &fd);
   if (hff != INVALID_HANDLE_VALUE) {
     if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-      GetFullPathName (param1, sizeof(inpath), inpath, &infile);
-      strcat (outpath, "\\");
-      strcat (outpath, infile);
+      GetFullPathName (param1, sizeof(inpath)/sizeof(WCHAR), inpath, &infile);
+      strcatW (outpath, slashW);
+      strcatW (outpath, infile);
     }
     FindClose (hff);
   }
 
   /* /-Y has the highest priority, then /Y and finally the COPYCMD env. variable */
-  if (strstr (quals, "/-Y"))
+  if (strstrW (quals, parmNoY))
     force = FALSE;
-  else if (strstr (quals, "/Y"))
+  else if (strstrW (quals, parmY))
     force = TRUE;
   else {
-    len = GetEnvironmentVariable ("COPYCMD", copycmd, sizeof(copycmd));
-    force = (len && len < sizeof(copycmd) && ! lstrcmpi (copycmd, "/Y"));
+    len = GetEnvironmentVariable (copyCmdW, copycmd, sizeof(copycmd)/sizeof(WCHAR));
+    force = (len && len < (sizeof(copycmd)/sizeof(WCHAR)) && ! lstrcmpiW (copycmd, parmY));
   }
 
   if (!force) {
     hff = FindFirstFile (outpath, &fd);
     if (hff != INVALID_HANDLE_VALUE) {
-      char buffer[MAXSTRING];
+      WCHAR buffer[MAXSTRING];
 
       FindClose (hff);
 
-      sprintf(buffer, WCMD_LoadMessage(WCMD_OVERWRITE), outpath);
+      wsprintf(buffer, WCMD_LoadMessage(WCMD_OVERWRITE), outpath);
       force = WCMD_ask_confirm(buffer, FALSE, NULL);
     }
     else force = TRUE;
@@ -173,21 +184,21 @@ void WCMD_copy (void) {
  * they do not already exist.
  */
 
-static BOOL create_full_path(CHAR* path)
+static BOOL create_full_path(WCHAR* path)
 {
     int len;
-    CHAR *new_path;
+    WCHAR *new_path;
     BOOL ret = TRUE;
 
-    new_path = HeapAlloc(GetProcessHeap(),0,strlen(path)+1);
-    strcpy(new_path,path);
+    new_path = HeapAlloc(GetProcessHeap(),0,(strlenW(path) * sizeof(WCHAR))+1);
+    strcpyW(new_path,path);
 
-    while ((len = strlen(new_path)) && new_path[len - 1] == '\\')
+    while ((len = strlenW(new_path)) && new_path[len - 1] == '\\')
         new_path[len - 1] = 0;
 
     while (!CreateDirectory(new_path,NULL))
     {
-        CHAR *slash;
+        WCHAR *slash;
         DWORD last_error = GetLastError();
         if (last_error == ERROR_ALREADY_EXISTS)
             break;
@@ -198,7 +209,7 @@ static BOOL create_full_path(CHAR* path)
             break;
         }
 
-        if (!(slash = strrchr(new_path,'\\')) && ! (slash = strrchr(new_path,'/')))
+        if (!(slash = strrchrW(new_path,'\\')) && ! (slash = strrchrW(new_path,'/')))
         {
             ret = FALSE;
             break;
@@ -239,58 +250,66 @@ void WCMD_create_dir (void) {
  *         non-hidden files
  */
 
-BOOL WCMD_delete (char *command, BOOL expectDir) {
+BOOL WCMD_delete (WCHAR *command, BOOL expectDir) {
 
     int   argno         = 0;
     int   argsProcessed = 0;
-    char *argN          = command;
+    WCHAR *argN          = command;
     BOOL  foundAny      = FALSE;
+    const WCHAR parmA[] = {'/','A','\0'};
+    const WCHAR parmQ[] = {'/','Q','\0'};
+    const WCHAR parmP[] = {'/','P','\0'};
+    const WCHAR parmS[] = {'/','S','\0'};
+    const WCHAR parmF[] = {'/','F','\0'};
 
     /* If not recursing, clear error flag */
     if (expectDir) errorlevel = 0;
 
     /* Loop through all args */
     while (argN) {
-      char *thisArg = WCMD_parameter (command, argno++, &argN);
-      char argCopy[MAX_PATH];
+      WCHAR *thisArg = WCMD_parameter (command, argno++, &argN);
+      WCHAR argCopy[MAX_PATH];
 
       if (argN && argN[0] != '/') {
 
         WIN32_FIND_DATA fd;
         HANDLE hff;
-        char fpath[MAX_PATH];
-        char *p;
+        WCHAR fpath[MAX_PATH];
+        WCHAR *p;
         BOOL handleParm = TRUE;
         BOOL found = FALSE;
+        const WCHAR anyExt[]= {'.','*','\0'};
 
-        strcpy(argCopy, thisArg);
-        WINE_TRACE("del: Processing arg %s (quals:%s)\n", argCopy, quals);
+        strcpyW(argCopy, thisArg);
+        WINE_TRACE("del: Processing arg %s (quals:%s)\n",
+                   wine_dbgstr_w(argCopy), wine_dbgstr_w(quals));
         argsProcessed++;
 
         /* If filename part of parameter is * or *.*, prompt unless
            /Q supplied.                                            */
-        if ((strstr (quals, "/Q") == NULL) && (strstr (quals, "/P") == NULL)) {
+        if ((strstrW (quals, parmQ) == NULL) && (strstrW (quals, parmP) == NULL)) {
 
-          char drive[10];
-          char dir[MAX_PATH];
-          char fname[MAX_PATH];
-          char ext[MAX_PATH];
+          WCHAR drive[10];
+          WCHAR dir[MAX_PATH];
+          WCHAR fname[MAX_PATH];
+          WCHAR ext[MAX_PATH];
 
           /* Convert path into actual directory spec */
-          GetFullPathName (argCopy, sizeof(fpath), fpath, NULL);
+          GetFullPathName (argCopy, sizeof(fpath)/sizeof(WCHAR), fpath, NULL);
           WCMD_splitpath(fpath, drive, dir, fname, ext);
 
           /* Only prompt for * and *.*, not *a, a*, *.a* etc */
-          if ((strcmp(fname, "*") == 0) &&
-              (*ext == 0x00 || (strcmp(ext, ".*") == 0))) {
+          if ((strcmpW(fname, starW) == 0) &&
+              (*ext == 0x00 || (strcmpW(ext, anyExt) == 0))) {
             BOOL  ok;
-            char  question[MAXSTRING];
+            WCHAR  question[MAXSTRING];
+            const WCHAR fmt[] = {'%','s',' ','\0'};
 
             /* Note: Flag as found, to avoid file not found message */
             found = TRUE;
 
             /* Ask for confirmation */
-            sprintf(question, "%s, ", fpath);
+            wsprintf(question, fmt, fpath);
             ok = WCMD_ask_confirm(question, TRUE, NULL);
 
             /* Abort if answer is 'N' */
@@ -307,11 +326,13 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
         }
 
         /* Support del <dirname> by just deleting all files dirname\* */
-        if (handleParm && (strchr(argCopy,'*') == NULL) && (strchr(argCopy,'?') == NULL)
+        if (handleParm && (strchrW(argCopy,'*') == NULL) && (strchrW(argCopy,'?') == NULL)
 		&& (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
-          char modifiedParm[MAX_PATH];
-          strcpy(modifiedParm, argCopy);
-          strcat(modifiedParm, "\\*");
+          WCHAR modifiedParm[MAX_PATH];
+          const WCHAR slashStar[] = {'\\','*','\0'};
+
+          strcpyW(modifiedParm, argCopy);
+          strcatW(modifiedParm, slashStar);
           FindClose(hff);
           found = TRUE;
           WCMD_delete(modifiedParm, FALSE);
@@ -319,24 +340,24 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
         } else if (handleParm) {
 
           /* Build the filename to delete as <supplied directory>\<findfirst filename> */
-          strcpy (fpath, argCopy);
+          strcpyW (fpath, argCopy);
           do {
-            p = strrchr (fpath, '\\');
+            p = strrchrW (fpath, '\\');
             if (p != NULL) {
               *++p = '\0';
-              strcat (fpath, fd.cFileName);
+              strcatW (fpath, fd.cFileName);
             }
-            else strcpy (fpath, fd.cFileName);
+            else strcpyW (fpath, fd.cFileName);
             if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
               BOOL  ok = TRUE;
-              char *nextA = strstr (quals, "/A");
+              WCHAR *nextA = strstrW (quals, parmA);
 
               /* Handle attribute matching (/A) */
               if (nextA != NULL) {
                 ok = FALSE;
                 while (nextA != NULL && !ok) {
 
-                  char *thisA = (nextA+2);
+                  WCHAR *thisA = (nextA+2);
                   BOOL  stillOK = TRUE;
 
                   /* Skip optional : */
@@ -383,16 +404,16 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
                   ok = stillOK;
 
                   /* Step on to next /A set */
-                  nextA = strstr (nextA+1, "/A");
+                  nextA = strstrW (nextA+1, parmA);
                 }
               }
 
               /* /P means prompt for each file */
-              if (ok && strstr (quals, "/P") != NULL) {
-                char  question[MAXSTRING];
+              if (ok && strstrW (quals, parmP) != NULL) {
+                WCHAR  question[MAXSTRING];
 
                 /* Ask for confirmation */
-                sprintf(question, WCMD_LoadMessage(WCMD_DELPROMPT), fpath);
+                wsprintf(question, WCMD_LoadMessage(WCMD_DELPROMPT), fpath);
                 ok = WCMD_ask_confirm(question, FALSE, NULL);
               }
 
@@ -401,7 +422,7 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
 
                 /* If file is read only, and /F supplied, delete it */
                 if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY &&
-                    strstr (quals, "/F") != NULL) {
+                    strstrW (quals, parmF) != NULL) {
                     SetFileAttributes(fpath, fd.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
                 }
 
@@ -415,25 +436,25 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
         }
 
         /* Now recurse into all subdirectories handling the parameter in the same way */
-        if (strstr (quals, "/S") != NULL) {
+        if (strstrW (quals, parmS) != NULL) {
 
-          char thisDir[MAX_PATH];
+          WCHAR thisDir[MAX_PATH];
           int cPos;
 
-          char drive[10];
-          char dir[MAX_PATH];
-          char fname[MAX_PATH];
-          char ext[MAX_PATH];
+          WCHAR drive[10];
+          WCHAR dir[MAX_PATH];
+          WCHAR fname[MAX_PATH];
+          WCHAR ext[MAX_PATH];
 
           /* Convert path into actual directory spec */
-          GetFullPathName (argCopy, sizeof(thisDir), thisDir, NULL);
+          GetFullPathName (argCopy, sizeof(thisDir)/sizeof(WCHAR), thisDir, NULL);
           WCMD_splitpath(thisDir, drive, dir, fname, ext);
 
-          strcpy(thisDir, drive);
-          strcat(thisDir, dir);
-          cPos = strlen(thisDir);
+          strcpyW(thisDir, drive);
+          strcatW(thisDir, dir);
+          cPos = strlenW(thisDir);
 
-          WINE_TRACE("Searching recursively in '%s'\n", thisDir);
+          WINE_TRACE("Searching recursively in '%s'\n", wine_dbgstr_w(thisDir));
 
           /* Append '*' to the directory */
           thisDir[cPos] = '*';
@@ -450,19 +471,19 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
 
             do {
               if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
-                  (strcmp(fd.cFileName, "..") != 0) &&
-                  (strcmp(fd.cFileName, ".") != 0)) {
+                  (strcmpW(fd.cFileName, dotdotW) != 0) &&
+                  (strcmpW(fd.cFileName, dotW) != 0)) {
 
                 DIRECTORY_STACK *nextDir;
-                char subParm[MAX_PATH];
+                WCHAR subParm[MAX_PATH];
 
                 /* Work out search parameter in sub dir */
-                strcpy (subParm, thisDir);
-                strcat (subParm, fd.cFileName);
-                strcat (subParm, "\\");
-                strcat (subParm, fname);
-                strcat (subParm, ext);
-                WINE_TRACE("Recursive, Adding to search list '%s'\n", subParm);
+                strcpyW (subParm, thisDir);
+                strcatW (subParm, fd.cFileName);
+                strcatW (subParm, slashW);
+                strcatW (subParm, fname);
+                strcatW (subParm, ext);
+                WINE_TRACE("Recursive, Adding to search list '%s'\n", wine_dbgstr_w(subParm));
 
                 /* Allocate memory, add to list */
                 nextDir = (DIRECTORY_STACK *) HeapAlloc(GetProcessHeap(),0,sizeof(DIRECTORY_STACK));
@@ -470,8 +491,9 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
                 if (lastEntry != NULL) lastEntry->next = nextDir;
                 lastEntry = nextDir;
                 nextDir->next = NULL;
-                nextDir->dirName = HeapAlloc(GetProcessHeap(),0,(strlen(subParm)+1));
-                strcpy(nextDir->dirName, subParm);
+                nextDir->dirName = HeapAlloc(GetProcessHeap(),0,
+                                             (strlenW(subParm)+1) * sizeof(WCHAR));
+                strcpyW(nextDir->dirName, subParm);
               }
             } while (FindNextFile(hff, &fd) != 0);
             FindClose (hff);
@@ -516,7 +538,7 @@ BOOL WCMD_delete (char *command, BOOL expectDir) {
  * in DOS (try typing "ECHO ON AGAIN" for an example).
  */
 
-void WCMD_echo (const char *command) {
+void WCMD_echo (const WCHAR *command) {
 
   int count;
 
@@ -526,17 +548,17 @@ void WCMD_echo (const char *command) {
   }
   if (command[0]==' ')
     command++;
-  count = strlen(command);
+  count = strlenW(command);
   if (count == 0) {
-    if (echo_mode) WCMD_output (WCMD_LoadMessage(WCMD_ECHOPROMPT), "ON");
-    else WCMD_output (WCMD_LoadMessage(WCMD_ECHOPROMPT), "OFF");
+    if (echo_mode) WCMD_output (WCMD_LoadMessage(WCMD_ECHOPROMPT), onW);
+    else WCMD_output (WCMD_LoadMessage(WCMD_ECHOPROMPT), offW);
     return;
   }
-  if (lstrcmpi(command, "ON") == 0) {
+  if (lstrcmpiW(command, onW) == 0) {
     echo_mode = 1;
     return;
   }
-  if (lstrcmpi(command, "OFF") == 0) {
+  if (lstrcmpiW(command, offW) == 0) {
     echo_mode = 0;
     return;
   }
@@ -553,23 +575,25 @@ void WCMD_echo (const char *command) {
  * will probably work here, but the reverse is not necessarily the case...
  */
 
-void WCMD_for (char *p) {
+void WCMD_for (WCHAR *p) {
 
   WIN32_FIND_DATA fd;
   HANDLE hff;
-  char *cmd, *item;
-  char set[MAX_PATH], param[MAX_PATH];
+  WCHAR *cmd, *item;
+  WCHAR set[MAX_PATH], param[MAX_PATH];
   int i;
+  const WCHAR inW[] = {'i', 'n', '\0'};
+  const WCHAR doW[] = {'d', 'o', '\0'};
 
-  if (lstrcmpi (WCMD_parameter (p, 1, NULL), "in")
-	|| lstrcmpi (WCMD_parameter (p, 3, NULL), "do")
+  if (lstrcmpiW (WCMD_parameter (p, 1, NULL), inW)
+	|| lstrcmpiW (WCMD_parameter (p, 3, NULL), doW)
 	|| (param1[0] != '%')) {
     WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
     return;
   }
-  lstrcpyn (set, WCMD_parameter (p, 2, NULL), sizeof(set));
+  lstrcpynW (set, WCMD_parameter (p, 2, NULL), sizeof(set)/sizeof(WCHAR));
   WCMD_parameter (p, 4, &cmd);
-  lstrcpy (param, param1);
+  strcpyW (param, param1);
 
 /*
  *	If the parameter within the set has a wildcard then search for matching files
@@ -578,7 +602,8 @@ void WCMD_for (char *p) {
 
   i = 0;
   while (*(item = WCMD_parameter (set, i, NULL))) {
-    if (strpbrk (item, "*?")) {
+    const WCHAR wildcards[] = {'*','?','\0'};
+    if (strpbrkW (item, wildcards)) {
       hff = FindFirstFile (item, &fd);
       if (hff == INVALID_HANDLE_VALUE) {
 	return;
@@ -601,24 +626,24 @@ void WCMD_for (char *p) {
  *	Execute a command after substituting variable text for the supplied parameter
  */
 
-void WCMD_execute (char *orig_cmd, char *param, char *subst) {
+void WCMD_execute (WCHAR *orig_cmd, WCHAR *param, WCHAR *subst) {
 
-  char *new_cmd, *p, *s, *dup;
+  WCHAR *new_cmd, *p, *s, *dup;
   int size;
 
-  size = lstrlen (orig_cmd);
-  new_cmd = (char *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
-  dup = s = strdup (orig_cmd);
+  size = strlenW (orig_cmd);
+  new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
+  dup = s = WCMD_strdupW(orig_cmd);
 
-  while ((p = strstr (s, param))) {
+  while ((p = strstrW (s, param))) {
     *p = '\0';
-    size += lstrlen (subst);
-    new_cmd = (char *) LocalReAlloc ((HANDLE)new_cmd, size, 0);
-    strcat (new_cmd, s);
-    strcat (new_cmd, subst);
-    s = p + lstrlen (param);
+    size += strlenW (subst);
+    new_cmd = (WCHAR *) LocalReAlloc ((HANDLE)new_cmd, size, 0);
+    strcatW (new_cmd, s);
+    strcatW (new_cmd, subst);
+    s = p + strlenW (param);
   }
-  strcat (new_cmd, s);
+  strcatW (new_cmd, s);
   WCMD_process_command (new_cmd);
   free (dup);
   LocalFree ((HANDLE)new_cmd);
@@ -631,21 +656,21 @@ void WCMD_execute (char *orig_cmd, char *param, char *subst) {
  *	Simple on-line help. Help text is stored in the resource file.
  */
 
-void WCMD_give_help (char *command) {
+void WCMD_give_help (WCHAR *command) {
 
   int i;
-  char buffer[2048];
+  WCHAR buffer[2048];
 
   command = WCMD_strtrim_leading_spaces(command);
-  if (lstrlen(command) == 0) {
-    LoadString (hinst, 1000, buffer, sizeof(buffer));
+  if (strlenW(command) == 0) {
+    LoadString (hinst, 1000, buffer, sizeof(buffer)/sizeof(WCHAR));
     WCMD_output_asis (buffer);
   }
   else {
     for (i=0; i<=WCMD_EXIT; i++) {
       if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
 	  param1, -1, inbuilt[i], -1) == 2) {
-	LoadString (hinst, i, buffer, sizeof(buffer));
+	LoadString (hinst, i, buffer, sizeof(buffer)/sizeof(WCHAR));
 	WCMD_output_asis (buffer);
 	return;
       }
@@ -666,17 +691,18 @@ void WCMD_give_help (char *command) {
 
 void WCMD_goto (void) {
 
-  char string[MAX_PATH];
+  WCHAR string[MAX_PATH];
 
   if (param1[0] == 0x00) {
     WCMD_output (WCMD_LoadMessage(WCMD_NOARG));
     return;
   }
   if (context != NULL) {
-    char *paramStart = param1;
+    WCHAR *paramStart = param1;
+    const WCHAR eofW[] = {':','e','o','f','\0'};
 
     /* Handle special :EOF label */
-    if (lstrcmpi (":eof", param1) == 0) {
+    if (lstrcmpiW (eofW, param1) == 0) {
       context -> skip_rest = TRUE;
       return;
     }
@@ -685,8 +711,8 @@ void WCMD_goto (void) {
     if (*paramStart == ':') paramStart++;
 
     SetFilePointer (context -> h, 0, NULL, FILE_BEGIN);
-    while (WCMD_fgets (string, sizeof(string), context -> h)) {
-      if ((string[0] == ':') && (lstrcmpi (&string[1], paramStart) == 0)) return;
+    while (WCMD_fgets (string, sizeof(string)/sizeof(WCHAR), context -> h)) {
+      if ((string[0] == ':') && (lstrcmpiW (&string[1], paramStart) == 0)) return;
     }
     WCMD_output (WCMD_LoadMessage(WCMD_NOTARGET));
   }
@@ -699,11 +725,12 @@ void WCMD_goto (void) {
  *	Push a directory onto the stack
  */
 
-void WCMD_pushd (char *command) {
+void WCMD_pushd (WCHAR *command) {
     struct env_stack *curdir;
     WCHAR *thisdir;
+    const WCHAR parmD[] = {'/','D','\0'};
 
-    if (strchr(command, '/') != NULL) {
+    if (strchrW(command, '/') != NULL) {
       SetLastError(ERROR_INVALID_PARAMETER);
       WCMD_print_error();
       return;
@@ -719,7 +746,7 @@ void WCMD_pushd (char *command) {
     }
 
     /* Change directory using CD code with /D parameter */
-    strcpy(quals, "/D");
+    strcpyW(quals, parmD);
     GetCurrentDirectoryW (1024, thisdir);
     errorlevel = 0;
     WCMD_setshow_default(command);
@@ -766,37 +793,42 @@ void WCMD_popd (void) {
  * FIXME: Much more syntax checking needed!
  */
 
-void WCMD_if (char *p) {
+void WCMD_if (WCHAR *p) {
 
   int negate = 0, test = 0;
-  char condition[MAX_PATH], *command, *s;
-
-  if (!lstrcmpi (param1, "not")) {
+  WCHAR condition[MAX_PATH], *command, *s;
+  const WCHAR notW[]    = {'n','o','t','\0'};
+  const WCHAR errlvlW[] = {'e','r','r','o','r','l','e','v','e','l','\0'};
+  const WCHAR existW[]  = {'e','x','i','s','t','\0'};
+  const WCHAR defdW[]   = {'d','e','f','i','n','e','d','\0'};
+  const WCHAR eqeqW[]   = {'=','=','\0'};
+
+  if (!lstrcmpiW (param1, notW)) {
     negate = 1;
-    lstrcpy (condition, param2);
+    strcpyW (condition, param2);
   }
   else {
-    lstrcpy (condition, param1);
+    strcpyW (condition, param1);
   }
-  if (!lstrcmpi (condition, "errorlevel")) {
-    if (errorlevel >= atoi(WCMD_parameter (p, 1+negate, NULL))) test = 1;
+  if (!lstrcmpiW (condition, errlvlW)) {
+    if (errorlevel >= atoiW(WCMD_parameter (p, 1+negate, NULL))) test = 1;
     WCMD_parameter (p, 2+negate, &command);
   }
-  else if (!lstrcmpi (condition, "exist")) {
-    if (GetFileAttributesA(WCMD_parameter (p, 1+negate, NULL)) != INVALID_FILE_ATTRIBUTES) {
+  else if (!lstrcmpiW (condition, existW)) {
+    if (GetFileAttributes(WCMD_parameter (p, 1+negate, NULL)) != INVALID_FILE_ATTRIBUTES) {
         test = 1;
     }
     WCMD_parameter (p, 2+negate, &command);
   }
-  else if (!lstrcmpi (condition, "defined")) {
-    if (GetEnvironmentVariableA(WCMD_parameter (p, 1+negate, NULL), NULL, 0) > 0) {
+  else if (!lstrcmpiW (condition, defdW)) {
+    if (GetEnvironmentVariable(WCMD_parameter (p, 1+negate, NULL), NULL, 0) > 0) {
         test = 1;
     }
     WCMD_parameter (p, 2+negate, &command);
   }
-  else if ((s = strstr (p, "=="))) {
+  else if ((s = strstrW (p, eqeqW))) {
     s += 2;
-    if (!lstrcmpi (condition, WCMD_parameter (s, 0, NULL))) test = 1;
+    if (!lstrcmpiW (condition, WCMD_parameter (s, 0, NULL))) test = 1;
     WCMD_parameter (s, 1, &command);
   }
   else {
@@ -804,7 +836,7 @@ void WCMD_if (char *p) {
     return;
   }
   if (test != negate) {
-    command = strdup (command);
+    command = WCMD_strdupW(command);
     WCMD_process_command (command);
     free (command);
   }
@@ -821,12 +853,12 @@ void WCMD_move (void) {
   int             status;
   WIN32_FIND_DATA fd;
   HANDLE          hff;
-  char            input[MAX_PATH];
-  char            output[MAX_PATH];
-  char            drive[10];
-  char            dir[MAX_PATH];
-  char            fname[MAX_PATH];
-  char            ext[MAX_PATH];
+  WCHAR            input[MAX_PATH];
+  WCHAR            output[MAX_PATH];
+  WCHAR            drive[10];
+  WCHAR            dir[MAX_PATH];
+  WCHAR            fname[MAX_PATH];
+  WCHAR            ext[MAX_PATH];
 
   if (param1[0] == 0x00) {
     WCMD_output (WCMD_LoadMessage(WCMD_NOARG));
@@ -835,48 +867,49 @@ void WCMD_move (void) {
 
   /* If no destination supplied, assume current directory */
   if (param2[0] == 0x00) {
-      strcpy(param2, ".");
+      strcpyW(param2, dotW);
   }
 
   /* If 2nd parm is directory, then use original filename */
   /* Convert partial path to full path */
-  GetFullPathName (param1, sizeof(input), input, NULL);
-  GetFullPathName (param2, sizeof(output), output, NULL);
-  WINE_TRACE("Move from '%s'('%s') to '%s'\n", input, param1, output);
+  GetFullPathName (param1, sizeof(input)/sizeof(WCHAR), input, NULL);
+  GetFullPathName (param2, sizeof(output)/sizeof(WCHAR), output, NULL);
+  WINE_TRACE("Move from '%s'('%s') to '%s'\n", wine_dbgstr_w(input),
+             wine_dbgstr_w(param1), wine_dbgstr_w(output));
 
   /* Split into components */
   WCMD_splitpath(input, drive, dir, fname, ext);
 
   hff = FindFirstFile (input, &fd);
   while (hff != INVALID_HANDLE_VALUE) {
-    char  dest[MAX_PATH];
-    char  src[MAX_PATH];
+    WCHAR  dest[MAX_PATH];
+    WCHAR  src[MAX_PATH];
     DWORD attribs;
 
-    WINE_TRACE("Processing file '%s'\n", fd.cFileName);
+    WINE_TRACE("Processing file '%s'\n", wine_dbgstr_w(fd.cFileName));
 
     /* Build src & dest name */
-    strcpy(src, drive);
-    strcat(src, dir);
+    strcpyW(src, drive);
+    strcatW(src, dir);
 
     /* See if dest is an existing directory */
     attribs = GetFileAttributes(output);
     if (attribs != INVALID_FILE_ATTRIBUTES &&
        (attribs & FILE_ATTRIBUTE_DIRECTORY)) {
-      strcpy(dest, output);
-      strcat(dest, "\\");
-      strcat(dest, fd.cFileName);
+      strcpyW(dest, output);
+      strcatW(dest, slashW);
+      strcatW(dest, fd.cFileName);
     } else {
-      strcpy(dest, output);
+      strcpyW(dest, output);
     }
 
-    strcat(src, fd.cFileName);
+    strcatW(src, fd.cFileName);
 
-    WINE_TRACE("Source '%s'\n", src);
-    WINE_TRACE("Dest   '%s'\n", dest);
+    WINE_TRACE("Source '%s'\n", wine_dbgstr_w(src));
+    WINE_TRACE("Dest   '%s'\n", wine_dbgstr_w(dest));
 
     /* Check if file is read only, otherwise move it */
-    attribs = GetFileAttributesA(src);
+    attribs = GetFileAttributes(src);
     if ((attribs != INVALID_FILE_ATTRIBUTES) &&
         (attribs & FILE_ATTRIBUTE_READONLY)) {
       SetLastError(ERROR_ACCESS_DENIED);
@@ -885,30 +918,32 @@ void WCMD_move (void) {
       BOOL ok = TRUE;
 
       /* If destination exists, prompt unless /Y supplied */
-      if (GetFileAttributesA(dest) != INVALID_FILE_ATTRIBUTES) {
+      if (GetFileAttributes(dest) != INVALID_FILE_ATTRIBUTES) {
         BOOL force = FALSE;
-        char copycmd[MAXSTRING];
+        WCHAR copycmd[MAXSTRING];
         int len;
 
         /* /-Y has the highest priority, then /Y and finally the COPYCMD env. variable */
-        if (strstr (quals, "/-Y"))
+        if (strstrW (quals, parmNoY))
           force = FALSE;
-        else if (strstr (quals, "/Y"))
+        else if (strstrW (quals, parmY))
           force = TRUE;
         else {
-          len = GetEnvironmentVariable ("COPYCMD", copycmd, sizeof(copycmd));
-          force = (len && len < sizeof(copycmd) && ! lstrcmpi (copycmd, "/Y"));
+          const WCHAR copyCmdW[] = {'C','O','P','Y','C','M','D','\0'};
+          len = GetEnvironmentVariable (copyCmdW, copycmd, sizeof(copycmd)/sizeof(WCHAR));
+          force = (len && len < (sizeof(copycmd)/sizeof(WCHAR))
+                       && ! lstrcmpiW (copycmd, parmY));
         }
 
         /* Prompt if overwriting */
         if (!force) {
-          char  question[MAXSTRING];
-          char  yesChar[10];
+          WCHAR  question[MAXSTRING];
+          WCHAR  yesChar[10];
 
-          strcpy(yesChar, WCMD_LoadMessage(WCMD_YES));
+          strcpyW(yesChar, WCMD_LoadMessage(WCMD_YES));
 
           /* Ask for confirmation */
-          sprintf(question, WCMD_LoadMessage(WCMD_OVERWRITE), dest);
+          wsprintf(question, WCMD_LoadMessage(WCMD_OVERWRITE), dest);
           ok = WCMD_ask_confirm(question, FALSE, NULL);
 
           /* So delete the destination prior to the move */
@@ -952,10 +987,11 @@ void WCMD_move (void) {
 void WCMD_pause (void) {
 
   DWORD count;
-  char string[32];
+  WCHAR string[32];
 
   WCMD_output (anykey);
-  ReadFile (GetStdHandle(STD_INPUT_HANDLE), string, sizeof(string), &count, NULL);
+  WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), string,
+                 sizeof(string)/sizeof(WCHAR), &count, NULL);
 }
 
 /****************************************************************************
@@ -964,22 +1000,25 @@ void WCMD_pause (void) {
  * Delete a directory.
  */
 
-void WCMD_remove_dir (char *command) {
+void WCMD_remove_dir (WCHAR *command) {
 
   int   argno         = 0;
   int   argsProcessed = 0;
-  char *argN          = command;
+  WCHAR *argN          = command;
+  const WCHAR parmS[] = {'/','S','\0'};
+  const WCHAR parmQ[] = {'/','Q','\0'};
 
   /* Loop through all args */
   while (argN) {
-    char *thisArg = WCMD_parameter (command, argno++, &argN);
+    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN);
     if (argN && argN[0] != '/') {
-      WINE_TRACE("rd: Processing arg %s (quals:%s)\n", thisArg, quals);
+      WINE_TRACE("rd: Processing arg %s (quals:%s)\n", wine_dbgstr_w(thisArg),
+                 wine_dbgstr_w(quals));
       argsProcessed++;
 
       /* If subdirectory search not supplied, just try to remove
          and report error if it fails (eg if it contains a file) */
-      if (strstr (quals, "/S") == NULL) {
+      if (strstrW (quals, parmS) == NULL) {
         if (!RemoveDirectory (thisArg)) WCMD_print_error ();
 
       /* Otherwise use ShFileOp to recursively remove a directory */
@@ -988,12 +1027,13 @@ void WCMD_remove_dir (char *command) {
         SHFILEOPSTRUCT lpDir;
 
         /* Ask first */
-        if (strstr (quals, "/Q") == NULL) {
+        if (strstrW (quals, parmQ) == NULL) {
           BOOL  ok;
-          char  question[MAXSTRING];
+          WCHAR  question[MAXSTRING];
+          const WCHAR fmt[] = {'%','s',' ','\0'};
 
           /* Ask for confirmation */
-          sprintf(question, "%s, ", thisArg);
+          wsprintf(question, fmt, thisArg);
           ok = WCMD_ask_confirm(question, TRUE, NULL);
 
           /* Abort if answer is 'N' */
@@ -1006,7 +1046,7 @@ void WCMD_remove_dir (char *command) {
         lpDir.pFrom  = thisArg;
         lpDir.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
         lpDir.wFunc  = FO_DELETE;
-        if (SHFileOperationA(&lpDir)) WCMD_print_error ();
+        if (SHFileOperation(&lpDir)) WCMD_print_error ();
       }
     }
   }
@@ -1030,12 +1070,12 @@ void WCMD_rename (void) {
   int             status;
   HANDLE          hff;
   WIN32_FIND_DATA fd;
-  char            input[MAX_PATH];
-  char           *dotDst = NULL;
-  char            drive[10];
-  char            dir[MAX_PATH];
-  char            fname[MAX_PATH];
-  char            ext[MAX_PATH];
+  WCHAR            input[MAX_PATH];
+  WCHAR           *dotDst = NULL;
+  WCHAR            drive[10];
+  WCHAR            dir[MAX_PATH];
+  WCHAR            fname[MAX_PATH];
+  WCHAR            ext[MAX_PATH];
   DWORD           attribs;
 
   errorlevel = 0;
@@ -1048,7 +1088,7 @@ void WCMD_rename (void) {
   }
 
   /* Destination cannot contain a drive letter or directory separator */
-  if ((strchr(param1,':') != NULL) || (strchr(param1,'\\') != NULL)) {
+  if ((strchrW(param1,':') != NULL) || (strchrW(param1,'\\') != NULL)) {
       SetLastError(ERROR_INVALID_PARAMETER);
       WCMD_print_error();
       errorlevel = 1;
@@ -1056,21 +1096,22 @@ void WCMD_rename (void) {
   }
 
   /* Convert partial path to full path */
-  GetFullPathName (param1, sizeof(input), input, NULL);
-  WINE_TRACE("Rename from '%s'('%s') to '%s'\n", input, param1, param2);
-  dotDst = strchr(param2, '.');
+  GetFullPathName (param1, sizeof(input)/sizeof(WCHAR), input, NULL);
+  WINE_TRACE("Rename from '%s'('%s') to '%s'\n", wine_dbgstr_w(input),
+             wine_dbgstr_w(param1), wine_dbgstr_w(param2));
+  dotDst = strchrW(param2, '.');
 
   /* Split into components */
   WCMD_splitpath(input, drive, dir, fname, ext);
 
   hff = FindFirstFile (input, &fd);
   while (hff != INVALID_HANDLE_VALUE) {
-    char  dest[MAX_PATH];
-    char  src[MAX_PATH];
-    char *dotSrc = NULL;
+    WCHAR  dest[MAX_PATH];
+    WCHAR  src[MAX_PATH];
+    WCHAR *dotSrc = NULL;
     int   dirLen;
 
-    WINE_TRACE("Processing file '%s'\n", fd.cFileName);
+    WINE_TRACE("Processing file '%s'\n", wine_dbgstr_w(fd.cFileName));
 
     /* FIXME: If dest name or extension is *, replace with filename/ext
        part otherwise use supplied name. This supports:
@@ -1078,36 +1119,36 @@ void WCMD_rename (void) {
           ren jim.* fred.* etc
        However, windows has a more complex algorithum supporting eg
           ?'s and *'s mid name                                         */
-    dotSrc = strchr(fd.cFileName, '.');
+    dotSrc = strchrW(fd.cFileName, '.');
 
     /* Build src & dest name */
-    strcpy(src, drive);
-    strcat(src, dir);
-    strcpy(dest, src);
-    dirLen = strlen(src);
-    strcat(src, fd.cFileName);
+    strcpyW(src, drive);
+    strcatW(src, dir);
+    strcpyW(dest, src);
+    dirLen = strlenW(src);
+    strcatW(src, fd.cFileName);
 
     /* Build name */
     if (param2[0] == '*') {
-      strcat(dest, fd.cFileName);
+      strcatW(dest, fd.cFileName);
       if (dotSrc) dest[dirLen + (dotSrc - fd.cFileName)] = 0x00;
     } else {
-      strcat(dest, param2);
+      strcatW(dest, param2);
       if (dotDst) dest[dirLen + (dotDst - param2)] = 0x00;
     }
 
     /* Build Extension */
     if (dotDst && (*(dotDst+1)=='*')) {
-      if (dotSrc) strcat(dest, dotSrc);
+      if (dotSrc) strcatW(dest, dotSrc);
     } else if (dotDst) {
-      if (dotDst) strcat(dest, dotDst);
+      if (dotDst) strcatW(dest, dotDst);
     }
 
-    WINE_TRACE("Source '%s'\n", src);
-    WINE_TRACE("Dest   '%s'\n", dest);
+    WINE_TRACE("Source '%s'\n", wine_dbgstr_w(src));
+    WINE_TRACE("Dest   '%s'\n", wine_dbgstr_w(dest));
 
     /* Check if file is read only, otherwise move it */
-    attribs = GetFileAttributesA(src);
+    attribs = GetFileAttributes(src);
     if ((attribs != INVALID_FILE_ATTRIBUTES) &&
         (attribs & FILE_ATTRIBUTE_READONLY)) {
       SetLastError(ERROR_ACCESS_DENIED);
@@ -1145,7 +1186,7 @@ static WCHAR *WCMD_dupenv( const WCHAR *env )
 
   len = 0;
   while ( env[len] )
-    len += (lstrlenW(&env[len]) + 1);
+    len += (strlenW(&env[len]) + 1);
 
   env_copy = LocalAlloc (LMEM_FIXED, (len+1) * sizeof (WCHAR) );
   if (!env_copy)
@@ -1165,10 +1206,10 @@ static WCHAR *WCMD_dupenv( const WCHAR *env )
  *  setlocal pushes the environment onto a stack
  *  Save the environment as unicode so we don't screw anything up.
  */
-void WCMD_setlocal (const char *s) {
+void WCMD_setlocal (const WCHAR *s) {
   WCHAR *env;
   struct env_stack *env_copy;
-  char cwd[MAX_PATH];
+  WCHAR cwd[MAX_PATH];
 
   /* DISABLEEXTENSIONS ignored */
 
@@ -1199,24 +1240,10 @@ void WCMD_setlocal (const char *s) {
 }
 
 /*****************************************************************************
- * WCMD_strchrW
- */
-static inline WCHAR *WCMD_strchrW(WCHAR *str, WCHAR ch)
-{
-   while(*str)
-   {
-     if(*str == ch)
-       return str;
-     str++;
-   }
-   return NULL;
-}
-
-/*****************************************************************************
  * WCMD_endlocal
  *
  *  endlocal pops the environment off a stack
- *  Note: When searching for '=', search from char position 1, to handle
+ *  Note: When searching for '=', search from WCHAR position 1, to handle
  *        special internal environment variables =C:, =D: etc
  */
 void WCMD_endlocal (void) {
@@ -1236,8 +1263,8 @@ void WCMD_endlocal (void) {
   old = WCMD_dupenv (GetEnvironmentStringsW ());
   len = 0;
   while (old[len]) {
-    n = lstrlenW(&old[len]) + 1;
-    p = WCMD_strchrW(&old[len] + 1, '=');
+    n = strlenW(&old[len]) + 1;
+    p = strchrW(&old[len] + 1, '=');
     if (p)
     {
       *p++ = 0;
@@ -1252,8 +1279,8 @@ void WCMD_endlocal (void) {
   env = temp->strings;
   len = 0;
   while (env[len]) {
-    n = lstrlenW(&env[len]) + 1;
-    p = WCMD_strchrW(&env[len] + 1, '=');
+    n = strlenW(&env[len]) + 1;
+    p = strchrW(&env[len] + 1, '=');
     if (p)
     {
       *p++ = 0;
@@ -1264,11 +1291,13 @@ void WCMD_endlocal (void) {
 
   /* Restore current drive letter */
   if (IsCharAlpha(temp->u.cwd)) {
-    char envvar[4];
-    char cwd[MAX_PATH];
-    sprintf(envvar, "=%c:", temp->u.cwd);
+    WCHAR envvar[4];
+    WCHAR cwd[MAX_PATH];
+    WCHAR fmt[] = {'=','%','c',':','\0'};
+
+    wsprintf(envvar, fmt, temp->u.cwd);
     if (GetEnvironmentVariable(envvar, cwd, MAX_PATH)) {
-      WINE_TRACE("Resetting cwd to %s\n", cwd);
+      WINE_TRACE("Resetting cwd to %s\n", wine_dbgstr_w(cwd));
       SetCurrentDirectory(cwd);
     }
   }
@@ -1295,16 +1324,18 @@ void WCMD_setshow_attrib (void) {
   DWORD count;
   HANDLE hff;
   WIN32_FIND_DATA fd;
-  char flags[9] = {"        "};
+  WCHAR flags[9] = {' ',' ',' ',' ',' ',' ',' ',' ','\0'};
 
   if (param1[0] == '-') {
     WCMD_output (WCMD_LoadMessage(WCMD_NYI));
     return;
   }
 
-  if (lstrlen(param1) == 0) {
-    GetCurrentDirectory (sizeof(param1), param1);
-    strcat (param1, "\\*");
+  if (strlenW(param1) == 0) {
+    const WCHAR slashStarW[]  = {'\\','*','\0'};
+
+    GetCurrentDirectory (sizeof(param1)/sizeof(WCHAR), param1);
+    strcatW (param1, slashStarW);
   }
 
   hff = FindFirstFile (param1, &fd);
@@ -1314,6 +1345,7 @@ void WCMD_setshow_attrib (void) {
   else {
     do {
       if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+        const WCHAR fmt[] = {'%','s',' ',' ',' ','%','s','\n','\0'};
         if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
 	  flags[0] = 'H';
 	}
@@ -1332,7 +1364,7 @@ void WCMD_setshow_attrib (void) {
         if (fd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) {
 	  flags[5] = 'C';
 	}
-        WCMD_output ("%s   %s\n", flags, fd.cFileName);
+        WCMD_output (fmt, flags, fd.cFileName);
 	for (count=0; count < 8; count++) flags[count] = ' ';
       }
     } while (FindNextFile(hff, &fd) != 0);
@@ -1346,28 +1378,29 @@ void WCMD_setshow_attrib (void) {
  *	Set/Show the current default directory
  */
 
-void WCMD_setshow_default (char *command) {
+void WCMD_setshow_default (WCHAR *command) {
 
   BOOL status;
-  char string[1024];
-  char cwd[1024];
-  char *pos;
+  WCHAR string[1024];
+  WCHAR cwd[1024];
+  WCHAR *pos;
   WIN32_FIND_DATA fd;
   HANDLE hff;
+  const WCHAR parmD[] = {'/','D','\0'};
 
-  WINE_TRACE("Request change to directory '%s'\n", command);
+  WINE_TRACE("Request change to directory '%s'\n", wine_dbgstr_w(command));
 
   /* Skip /D and trailing whitespace if on the front of the command line */
   if (CompareString (LOCALE_USER_DEFAULT,
                      NORM_IGNORECASE | SORT_STRINGSORT,
-                     command, 2, "/D", -1) == 2) {
+                     command, 2, parmD, -1) == 2) {
     command += 2;
     while (*command && *command==' ') command++;
   }
 
-  GetCurrentDirectory (sizeof(cwd), cwd);
-  if (strlen(command) == 0) {
-    strcat (cwd, newline);
+  GetCurrentDirectory (sizeof(cwd)/sizeof(WCHAR), cwd);
+  if (strlenW(command) == 0) {
+    strcatW (cwd, newline);
     WCMD_output (cwd);
   }
   else {
@@ -1381,22 +1414,23 @@ void WCMD_setshow_default (char *command) {
     *pos = 0x00;
 
     /* Search for approprate directory */
-    WINE_TRACE("Looking for directory '%s'\n", string);
+    WINE_TRACE("Looking for directory '%s'\n", wine_dbgstr_w(string));
     hff = FindFirstFile (string, &fd);
     while (hff != INVALID_HANDLE_VALUE) {
       if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-        char fpath[MAX_PATH];
-        char drive[10];
-        char dir[MAX_PATH];
-        char fname[MAX_PATH];
-        char ext[MAX_PATH];
+        WCHAR fpath[MAX_PATH];
+        WCHAR drive[10];
+        WCHAR dir[MAX_PATH];
+        WCHAR fname[MAX_PATH];
+        WCHAR ext[MAX_PATH];
+        const WCHAR fmt[] = {'%','s','%','s','%','s','\0'};
 
         /* Convert path into actual directory spec */
-        GetFullPathName (string, sizeof(fpath), fpath, NULL);
+        GetFullPathName (string, sizeof(fpath)/sizeof(WCHAR), fpath, NULL);
         WCMD_splitpath(fpath, drive, dir, fname, ext);
 
         /* Rebuild path */
-        sprintf(string, "%s%s%s", drive, dir, fd.cFileName);
+        wsprintf(string, fmt, drive, dir, fd.cFileName);
 
         FindClose(hff);
         hff = INVALID_HANDLE_VALUE;
@@ -1412,7 +1446,7 @@ void WCMD_setshow_default (char *command) {
     }
 
     /* Change to that directory */
-    WINE_TRACE("Really changing to directory '%s'\n", string);
+    WINE_TRACE("Really changing to directory '%s'\n", wine_dbgstr_w(string));
 
     status = SetCurrentDirectory (string);
     if (!status) {
@@ -1423,7 +1457,7 @@ void WCMD_setshow_default (char *command) {
 
       /* Restore old directory if drive letter would change, and
            CD x:\directory /D (or pushd c:\directory) not supplied */
-      if ((strstr(quals, "/D") == NULL) &&
+      if ((strstrW(quals, parmD) == NULL) &&
           (param1[1] == ':') && (toupper(param1[0]) != toupper(cwd[0]))) {
         SetCurrentDirectory(cwd);
       }
@@ -1434,10 +1468,10 @@ void WCMD_setshow_default (char *command) {
        /D (allows changing drive letter when not resident on that
        drive                                                          */
     if ((string[1] == ':') && IsCharAlpha (string[0])) {
-      char env[4];
-      strcpy(env, "=");
-      strncpy(env+1, string, 2);
-      env[3] = 0x00;
+      WCHAR env[4];
+      strcpyW(env, equalW);
+      lstrcpynW(env+1, string, 3);  /* (lstrcpynW inserts null when truncating) */
+      WINE_FIXME("Setting '%s' to '%s'\n", wine_dbgstr_w(env), wine_dbgstr_w(string));
       SetEnvironmentVariable(env, string);
     }
 
@@ -1454,16 +1488,18 @@ void WCMD_setshow_default (char *command) {
 
 void WCMD_setshow_date (void) {
 
-  char curdate[64], buffer[64];
+  WCHAR curdate[64], buffer[64];
   DWORD count;
+  const WCHAR parmT[] = {'/','T','\0'};
 
-  if (lstrlen(param1) == 0) {
+  if (strlenW(param1) == 0) {
     if (GetDateFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
-  		curdate, sizeof(curdate))) {
+  		curdate, sizeof(curdate)/sizeof(WCHAR))) {
       WCMD_output (WCMD_LoadMessage(WCMD_CURRENTDATE), curdate);
-      if (strstr (quals, "/T") == NULL) {
+      if (strstrW (quals, parmT) == NULL) {
         WCMD_output (WCMD_LoadMessage(WCMD_NEWDATE));
-        ReadFile (GetStdHandle(STD_INPUT_HANDLE), buffer, sizeof(buffer), &count, NULL);
+        WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE),
+                       buffer, sizeof(buffer)/sizeof(WCHAR), &count, NULL);
         if (count > 2) {
           WCMD_output (WCMD_LoadMessage(WCMD_NYI));
         }
@@ -1482,7 +1518,7 @@ void WCMD_setshow_date (void) {
 static int WCMD_compare( const void *a, const void *b )
 {
     int r;
-    const char * const *str_a = a, * const *str_b = b;
+    const WCHAR * const *str_a = a, * const *str_b = b;
     r = CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
 	  *str_a, -1, *str_b, -1 );
     if( r == CSTR_LESS_THAN ) return -1;
@@ -1497,29 +1533,29 @@ static int WCMD_compare( const void *a, const void *b )
  * Optionally only display those who start with a stub
  * returns the count displayed
  */
-static int WCMD_setshow_sortenv(const char *s, const char *stub)
+static int WCMD_setshow_sortenv(const WCHAR *s, const WCHAR *stub)
 {
   UINT count=0, len=0, i, displayedcount=0, stublen=0;
-  const char **str;
+  const WCHAR **str;
 
-  if (stub) stublen = strlen(stub);
+  if (stub) stublen = strlenW(stub);
 
   /* count the number of strings, and the total length */
   while ( s[len] ) {
-    len += (lstrlen(&s[len]) + 1);
+    len += (strlenW(&s[len]) + 1);
     count++;
   }
 
   /* add the strings to an array */
-  str = LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, count * sizeof (char*) );
+  str = LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, count * sizeof (WCHAR*) );
   if( !str )
     return 0;
   str[0] = s;
   for( i=1; i<count; i++ )
-    str[i] = str[i-1] + lstrlen(str[i-1]) + 1;
+    str[i] = str[i-1] + strlenW(str[i-1]) + 1;
 
   /* sort the array */
-  qsort( str, count, sizeof (char*), WCMD_compare );
+  qsort( str, count, sizeof (WCHAR*), WCMD_compare );
 
   /* print it */
   for( i=0; i<count; i++ ) {
@@ -1545,11 +1581,12 @@ static int WCMD_setshow_sortenv(const char *s, const char *stub)
  * Set/Show the environment variables
  */
 
-void WCMD_setshow_env (char *s) {
+void WCMD_setshow_env (WCHAR *s) {
 
   LPVOID env;
-  char *p;
+  WCHAR *p;
   int status;
+  const WCHAR parmP[] = {'/','P','\0'};
 
   errorlevel = 0;
   if (param1[0] == 0x00 && quals[0] == 0x00) {
@@ -1561,35 +1598,37 @@ void WCMD_setshow_env (char *s) {
   /* See if /P supplied, and if so echo the prompt, and read in a reply */
   if (CompareString (LOCALE_USER_DEFAULT,
                      NORM_IGNORECASE | SORT_STRINGSORT,
-                     s, 2, "/P", -1) == 2) {
-    char string[MAXSTRING];
+                     s, 2, parmP, -1) == 2) {
+    WCHAR string[MAXSTRING];
     DWORD count;
 
     s += 2;
     while (*s && *s==' ') s++;
 
     /* If no parameter, or no '=' sign, return an error */
-    if (!(*s) || ((p = strchr (s, '=')) == NULL )) {
+    if (!(*s) || ((p = strchrW (s, '=')) == NULL )) {
       WCMD_output (WCMD_LoadMessage(WCMD_NOARG));
       return;
     }
 
     /* Output the prompt */
     *p++ = '\0';
-    if (strlen(p) != 0) WCMD_output(p);
+    if (strlenW(p) != 0) WCMD_output(p);
 
     /* Read the reply */
-    ReadFile (GetStdHandle(STD_INPUT_HANDLE), string, sizeof(string), &count, NULL);
+    WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), string,
+                   sizeof(string)/sizeof(WCHAR), &count, NULL);
     if (count > 1) {
       string[count-1] = '\0'; /* ReadFile output is not null-terminated! */
       if (string[count-2] == '\r') string[count-2] = '\0'; /* Under Windoze we get CRLF! */
-      WINE_TRACE("set /p: Setting var '%s' to '%s'\n", s, string);
+      WINE_TRACE("set /p: Setting var '%s' to '%s'\n", wine_dbgstr_w(s),
+                 wine_dbgstr_w(string));
       status = SetEnvironmentVariable (s, string);
     }
 
   } else {
     DWORD gle;
-    p = strchr (s, '=');
+    p = strchrW (s, '=');
     if (p == NULL) {
       env = GetEnvironmentStrings ();
       if (WCMD_setshow_sortenv( env, s ) == 0) {
@@ -1600,7 +1639,7 @@ void WCMD_setshow_env (char *s) {
     }
     *p++ = '\0';
 
-    if (strlen(p) == 0) p = NULL;
+    if (strlenW(p) == 0) p = NULL;
     status = SetEnvironmentVariable (s, p);
     gle = GetLastError();
     if ((!status) & (gle == ERROR_ENVVAR_NOT_FOUND)) {
@@ -1615,25 +1654,27 @@ void WCMD_setshow_env (char *s) {
  * Set/Show the path environment variable
  */
 
-void WCMD_setshow_path (char *command) {
+void WCMD_setshow_path (WCHAR *command) {
 
-  char string[1024];
+  WCHAR string[1024];
   DWORD status;
+  const WCHAR pathW[] = {'P','A','T','H','\0'};
+  const WCHAR pathEqW[] = {'P','A','T','H','=','\0'};
 
-  if (strlen(param1) == 0) {
-    status = GetEnvironmentVariable ("PATH", string, sizeof(string));
+  if (strlenW(param1) == 0) {
+    status = GetEnvironmentVariable (pathW, string, sizeof(string)/sizeof(WCHAR));
     if (status != 0) {
-      WCMD_output_asis ( "PATH=");
+      WCMD_output_asis ( pathEqW);
       WCMD_output_asis ( string);
       WCMD_output_asis ( newline);
     }
     else {
-      WCMD_output ("PATH not found\n");
+      WCMD_output (WCMD_LoadMessage(WCMD_NOPATH));
     }
   }
   else {
     if (*command == '=') command++; /* Skip leading '=' */
-    status = SetEnvironmentVariable ("PATH", command);
+    status = SetEnvironmentVariable (pathW, command);
     if (!status) WCMD_print_error();
   }
 }
@@ -1646,18 +1687,19 @@ void WCMD_setshow_path (char *command) {
 
 void WCMD_setshow_prompt (void) {
 
-  char *s;
+  WCHAR *s;
+  const WCHAR promptW[] = {'P','R','O','M','P','T','\0'};
 
-  if (strlen(param1) == 0) {
-    SetEnvironmentVariable ("PROMPT", NULL);
+  if (strlenW(param1) == 0) {
+    SetEnvironmentVariable (promptW, NULL);
   }
   else {
     s = param1;
     while ((*s == '=') || (*s == ' ')) s++;
-    if (strlen(s) == 0) {
-      SetEnvironmentVariable ("PROMPT", NULL);
+    if (strlenW(s) == 0) {
+      SetEnvironmentVariable (promptW, NULL);
     }
-    else SetEnvironmentVariable ("PROMPT", s);
+    else SetEnvironmentVariable (promptW, s);
   }
 }
 
@@ -1670,18 +1712,21 @@ void WCMD_setshow_prompt (void) {
 
 void WCMD_setshow_time (void) {
 
-  char curtime[64], buffer[64];
+  WCHAR curtime[64], buffer[64];
   DWORD count;
   SYSTEMTIME st;
+  const WCHAR parmT[] = {'/','T','\0'};
 
-  if (strlen(param1) == 0) {
+
+  if (strlenW(param1) == 0) {
     GetLocalTime(&st);
     if (GetTimeFormat (LOCALE_USER_DEFAULT, 0, &st, NULL,
-  		curtime, sizeof(curtime))) {
+  		curtime, sizeof(curtime)/sizeof(WCHAR))) {
       WCMD_output (WCMD_LoadMessage(WCMD_CURRENTDATE), curtime);
-      if (strstr (quals, "/T") == NULL) {
+      if (strstrW (quals, parmT) == NULL) {
         WCMD_output (WCMD_LoadMessage(WCMD_NEWTIME));
-        ReadFile (GetStdHandle(STD_INPUT_HANDLE), buffer, sizeof(buffer), &count, NULL);
+        WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), buffer,
+                       sizeof(buffer)/sizeof(WCHAR), &count, NULL);
         if (count > 2) {
           WCMD_output (WCMD_LoadMessage(WCMD_NYI));
         }
@@ -1701,11 +1746,11 @@ void WCMD_setshow_time (void) {
  * Optional /n says where to start shifting (n=0-8)
  */
 
-void WCMD_shift (char *command) {
+void WCMD_shift (WCHAR *command) {
   int start;
 
   if (context != NULL) {
-    char *pos = strchr(command, '/');
+    WCHAR *pos = strchrW(command, '/');
     int   i;
 
     if (pos == NULL) {
@@ -1732,7 +1777,7 @@ void WCMD_shift (char *command) {
  *
  * Set the console title
  */
-void WCMD_title (char *command) {
+void WCMD_title (WCHAR *command) {
   SetConsoleTitle(command);
 }
 
@@ -1742,10 +1787,10 @@ void WCMD_title (char *command) {
  * Copy a file to standard output.
  */
 
-void WCMD_type (char *command) {
+void WCMD_type (WCHAR *command) {
 
   int   argno         = 0;
-  char *argN          = command;
+  WCHAR *argN          = command;
   BOOL  writeHeaders  = FALSE;
 
   if (param1[0] == 0x00) {
@@ -1758,15 +1803,15 @@ void WCMD_type (char *command) {
   /* Loop through all args */
   errorlevel = 0;
   while (argN) {
-    char *thisArg = WCMD_parameter (command, argno++, &argN);
+    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN);
 
     HANDLE h;
-    char buffer[512];
+    WCHAR buffer[512];
     DWORD count;
 
     if (!argN) break;
 
-    WINE_TRACE("type: Processing arg '%s'\n", thisArg);
+    WINE_TRACE("type: Processing arg '%s'\n", wine_dbgstr_w(thisArg));
     h = CreateFile (thisArg, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
 		FILE_ATTRIBUTE_NORMAL, NULL);
     if (h == INVALID_HANDLE_VALUE) {
@@ -1775,9 +1820,10 @@ void WCMD_type (char *command) {
       errorlevel = 1;
     } else {
       if (writeHeaders) {
-        WCMD_output("\n%s\n\n", thisArg);
+        const WCHAR fmt[] = {'\n','%','s','\n','\n','\0'};
+        WCMD_output(fmt, thisArg);
       }
-      while (ReadFile (h, buffer, sizeof(buffer), &count, NULL)) {
+      while (WCMD_ReadFile (h, buffer, sizeof(buffer)/sizeof(WCHAR), &count, NULL)) {
         if (count == 0) break;	/* ReadFile reports success on EOF! */
         buffer[count] = 0;
         WCMD_output_asis (buffer);
@@ -1793,20 +1839,26 @@ void WCMD_type (char *command) {
  * Output either a file or stdin to screen in pages
  */
 
-void WCMD_more (char *command) {
+void WCMD_more (WCHAR *command) {
 
   int   argno         = 0;
-  char *argN          = command;
+  WCHAR *argN          = command;
   BOOL  useinput      = FALSE;
-  char  moreStr[100];
-  char  moreStrPage[100];
-  char  buffer[512];
+  WCHAR  moreStr[100];
+  WCHAR  moreStrPage[100];
+  WCHAR  buffer[512];
   DWORD count;
+  const WCHAR moreStart[] = {'-','-',' ','\0'};
+  const WCHAR moreFmt[]   = {'%','s',' ','-','-','\n','\0'};
+  const WCHAR moreFmt2[]  = {'%','s',' ','(','%','2','.','2','d','%','%',
+                             ')',' ','-','-','\n','\0'};
+  const WCHAR conInW[]    = {'C','O','N','I','N','$','\0'};
 
   /* Prefix the NLS more with '-- ', then load the text */
   errorlevel = 0;
-  strcpy(moreStr, "-- ");
-  LoadString (hinst, WCMD_MORESTR, &moreStr[3], sizeof(moreStr)-3);
+  strcpyW(moreStr, moreStart);
+  LoadString (hinst, WCMD_MORESTR, &moreStr[3],
+              (sizeof(moreStr)/sizeof(WCHAR))-3);
 
   if (param1[0] == 0x00) {
 
@@ -1815,7 +1867,7 @@ void WCMD_more (char *command) {
        more are satistied by the next line from the input (file). To
        avoid this, ensure stdin is to the console                    */
     HANDLE hstdin  = GetStdHandle(STD_INPUT_HANDLE);
-    HANDLE hConIn = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
+    HANDLE hConIn = CreateFile(conInW, GENERIC_READ | GENERIC_WRITE,
                          FILE_SHARE_READ, NULL, OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL, 0);
     SetStdHandle(STD_INPUT_HANDLE, hConIn);
@@ -1823,10 +1875,10 @@ void WCMD_more (char *command) {
     /* Warning: No easy way of ending the stream (ctrl+z on windows) so
        once you get in this bit unless due to a pipe, its going to end badly...  */
     useinput = TRUE;
-    sprintf(moreStrPage, "%s --\n", moreStr);
+    wsprintf(moreStrPage, moreFmt, moreStr);
 
     WCMD_enter_paged_mode(moreStrPage);
-    while (ReadFile (hstdin, buffer, sizeof(buffer)-1, &count, NULL)) {
+    while (WCMD_ReadFile (hstdin, buffer, (sizeof(buffer)/sizeof(WCHAR))-1, &count, NULL)) {
       if (count == 0) break;	/* ReadFile reports success on EOF! */
       buffer[count] = 0;
       WCMD_output_asis (buffer);
@@ -1845,7 +1897,7 @@ void WCMD_more (char *command) {
     WCMD_enter_paged_mode(moreStrPage);
 
     while (argN) {
-      char *thisArg = WCMD_parameter (command, argno++, &argN);
+      WCHAR *thisArg = WCMD_parameter (command, argno++, &argN);
       HANDLE h;
 
       if (!argN) break;
@@ -1853,15 +1905,16 @@ void WCMD_more (char *command) {
       if (needsPause) {
 
         /* Wait */
-        sprintf(moreStrPage, "%s (100%%) --\n", moreStr);
+        wsprintf(moreStrPage, moreFmt2, moreStr, 100);
         WCMD_leave_paged_mode();
         WCMD_output_asis(moreStrPage);
-        ReadFile (GetStdHandle(STD_INPUT_HANDLE), buffer, sizeof(buffer), &count, NULL);
+        WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), buffer,
+                       sizeof(buffer)/sizeof(WCHAR), &count, NULL);
         WCMD_enter_paged_mode(moreStrPage);
       }
 
 
-      WINE_TRACE("more: Processing arg '%s'\n", thisArg);
+      WINE_TRACE("more: Processing arg '%s'\n", wine_dbgstr_w(thisArg));
       h = CreateFile (thisArg, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
 		FILE_ATTRIBUTE_NORMAL, NULL);
       if (h == INVALID_HANDLE_VALUE) {
@@ -1878,13 +1931,13 @@ void WCMD_more (char *command) {
         fileLen = (((ULONG64)fileInfo.nFileSizeHigh) << 32) + fileInfo.nFileSizeLow;
 
         needsPause = TRUE;
-        while (ReadFile (h, buffer, sizeof(buffer), &count, NULL)) {
+        while (WCMD_ReadFile (h, buffer, (sizeof(buffer)/sizeof(WCHAR))-1, &count, NULL)) {
           if (count == 0) break;	/* ReadFile reports success on EOF! */
           buffer[count] = 0;
           curPos += count;
 
           /* Update % count (would be used in WCMD_output_asis as prompt) */
-          sprintf(moreStrPage, "%s (%2.2d%%) --\n", moreStr, (int) min(99, (curPos * 100)/fileLen));
+          wsprintf(moreStrPage, moreFmt2, moreStr, (int) min(99, (curPos * 100)/fileLen));
 
           WCMD_output_asis (buffer);
         }
@@ -1904,21 +1957,21 @@ void WCMD_more (char *command) {
  * it...
  */
 
-void WCMD_verify (char *command) {
+void WCMD_verify (WCHAR *command) {
 
   int count;
 
-  count = strlen(command);
+  count = strlenW(command);
   if (count == 0) {
-    if (verify_mode) WCMD_output (WCMD_LoadMessage(WCMD_VERIFYPROMPT), "ON");
-    else WCMD_output (WCMD_LoadMessage(WCMD_VERIFYPROMPT), "OFF");
+    if (verify_mode) WCMD_output (WCMD_LoadMessage(WCMD_VERIFYPROMPT), onW);
+    else WCMD_output (WCMD_LoadMessage(WCMD_VERIFYPROMPT), offW);
     return;
   }
-  if (lstrcmpi(command, "ON") == 0) {
+  if (lstrcmpiW(command, onW) == 0) {
     verify_mode = 1;
     return;
   }
-  else if (lstrcmpi(command, "OFF") == 0) {
+  else if (lstrcmpiW(command, offW) == 0) {
     verify_mode = 0;
     return;
   }
@@ -1943,28 +1996,30 @@ void WCMD_version (void) {
  * Display volume info and/or set volume label. Returns 0 if error.
  */
 
-int WCMD_volume (int mode, char *path) {
+int WCMD_volume (int mode, WCHAR *path) {
 
   DWORD count, serial;
-  char string[MAX_PATH], label[MAX_PATH], curdir[MAX_PATH];
+  WCHAR string[MAX_PATH], label[MAX_PATH], curdir[MAX_PATH];
   BOOL status;
 
-  if (lstrlen(path) == 0) {
-    status = GetCurrentDirectory (sizeof(curdir), curdir);
+  if (strlenW(path) == 0) {
+    status = GetCurrentDirectory (sizeof(curdir)/sizeof(WCHAR), curdir);
     if (!status) {
       WCMD_print_error ();
       return 0;
     }
-    status = GetVolumeInformation (NULL, label, sizeof(label), &serial, NULL,
-    	NULL, NULL, 0);
+    status = GetVolumeInformation (NULL, label, sizeof(label)/sizeof(WCHAR),
+                                   &serial, NULL, NULL, NULL, 0);
   }
   else {
-    if ((path[1] != ':') || (lstrlen(path) != 2)) {
+    const WCHAR fmt[] = {'%','s','\\','\0'};
+    if ((path[1] != ':') || (strlenW(path) != 2)) {
       WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
       return 0;
     }
-    wsprintf (curdir, "%s\\", path);
-    status = GetVolumeInformation (curdir, label, sizeof(label), &serial, NULL,
+    wsprintf (curdir, fmt, path);
+    status = GetVolumeInformation (curdir, label, sizeof(label)/sizeof(WCHAR),
+                                   &serial, NULL,
     	NULL, NULL, 0);
   }
   if (!status) {
@@ -1975,12 +2030,13 @@ int WCMD_volume (int mode, char *path) {
     	curdir[0], label, HIWORD(serial), LOWORD(serial));
   if (mode) {
     WCMD_output (WCMD_LoadMessage(WCMD_VOLUMEPROMPT));
-    ReadFile (GetStdHandle(STD_INPUT_HANDLE), string, sizeof(string), &count, NULL);
+    WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), string,
+                   sizeof(string)/sizeof(WCHAR), &count, NULL);
     if (count > 1) {
       string[count-1] = '\0';		/* ReadFile output is not null-terminated! */
       if (string[count-2] == '\r') string[count-2] = '\0'; /* Under Windoze we get CRLF! */
     }
-    if (lstrlen(path) != 0) {
+    if (strlenW(path) != 0) {
       if (!SetVolumeLabel (curdir, string)) WCMD_print_error ();
     }
     else {
@@ -1999,9 +2055,10 @@ int WCMD_volume (int mode, char *path) {
 
 void WCMD_exit (void) {
 
-    int rc = atoi(param1); /* Note: atoi of empty parameter is 0 */
+    const WCHAR parmB[] = {'/','B','\0'};
+    int rc = atoiW(param1); /* Note: atoi of empty parameter is 0 */
 
-    if (context && lstrcmpi(quals, "/B") == 0) {
+    if (context && lstrcmpiW(quals, parmB) == 0) {
         errorlevel = rc;
         context -> skip_rest = TRUE;
     } else {
@@ -2020,38 +2077,41 @@ void WCMD_exit (void) {
  *                   set to TRUE
  *
  */
-BOOL WCMD_ask_confirm (char *message, BOOL showSureText, BOOL *optionAll) {
+BOOL WCMD_ask_confirm (WCHAR *message, BOOL showSureText, BOOL *optionAll) {
 
-    char  msgbuffer[MAXSTRING];
-    char  Ybuffer[MAXSTRING];
-    char  Nbuffer[MAXSTRING];
-    char  Abuffer[MAXSTRING];
-    char  answer[MAX_PATH] = "";
+    WCHAR  msgbuffer[MAXSTRING];
+    WCHAR  Ybuffer[MAXSTRING];
+    WCHAR  Nbuffer[MAXSTRING];
+    WCHAR  Abuffer[MAXSTRING];
+    WCHAR  answer[MAX_PATH] = {'\0'};
     DWORD count = 0;
 
     /* Load the translated 'Are you sure', plus valid answers */
-    LoadString (hinst, WCMD_CONFIRM, msgbuffer, sizeof(msgbuffer));
-    LoadString (hinst, WCMD_YES, Ybuffer, sizeof(Ybuffer));
-    LoadString (hinst, WCMD_NO,  Nbuffer, sizeof(Nbuffer));
-    LoadString (hinst, WCMD_ALL, Abuffer, sizeof(Abuffer));
+    LoadString (hinst, WCMD_CONFIRM, msgbuffer, sizeof(msgbuffer)/sizeof(WCHAR));
+    LoadString (hinst, WCMD_YES, Ybuffer, sizeof(Ybuffer)/sizeof(WCHAR));
+    LoadString (hinst, WCMD_NO,  Nbuffer, sizeof(Nbuffer)/sizeof(WCHAR));
+    LoadString (hinst, WCMD_ALL, Abuffer, sizeof(Abuffer)/sizeof(WCHAR));
 
     /* Loop waiting on a Y or N */
     while (answer[0] != Ybuffer[0] && answer[0] != Nbuffer[0]) {
+      const WCHAR startBkt[] = {' ','(','\0'};
+      const WCHAR endBkt[]   = {')','?','\0'};
+
       WCMD_output_asis (message);
       if (showSureText) {
         WCMD_output_asis (msgbuffer);
       }
-      WCMD_output_asis (" (");
+      WCMD_output_asis (startBkt);
       WCMD_output_asis (Ybuffer);
-      WCMD_output_asis ("/");
+      WCMD_output_asis (fslashW);
       WCMD_output_asis (Nbuffer);
       if (optionAll) {
-          WCMD_output_asis ("/");
+          WCMD_output_asis (fslashW);
           WCMD_output_asis (Abuffer);
       }
-      WCMD_output_asis (")?");
-      ReadFile (GetStdHandle(STD_INPUT_HANDLE), answer, sizeof(answer),
-                &count, NULL);
+      WCMD_output_asis (endBkt);
+      WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), answer,
+                     sizeof(answer)/sizeof(WCHAR), &count, NULL);
       answer[0] = toupper(answer[0]);
     }
 
@@ -2066,24 +2126,25 @@ BOOL WCMD_ask_confirm (char *message, BOOL showSureText, BOOL *optionAll) {
  *	Lists or sets file associations  (assoc = TRUE)
  *      Lists or sets file types         (assoc = FALSE)
  */
-void WCMD_assoc (char *command, BOOL assoc) {
+void WCMD_assoc (WCHAR *command, BOOL assoc) {
 
     HKEY    key;
     DWORD   accessOptions = KEY_READ;
-    char   *newValue;
+    WCHAR   *newValue;
     LONG    rc = ERROR_SUCCESS;
-    char    keyValue[MAXSTRING];
+    WCHAR    keyValue[MAXSTRING];
     DWORD   valueLen = MAXSTRING;
     HKEY    readKey;
-
+    const WCHAR shOpCmdW[] = {'\\','S','h','e','l','l','\\',
+        'O','p','e','n','\\','C','o','m','m','a','n','d','\0'};
 
     /* See if parameter includes '=' */
     errorlevel = 0;
-    newValue = strchr(command, '=');
+    newValue = strchrW(command, '=');
     if (newValue) accessOptions |= KEY_WRITE;
 
     /* Open a key to HKEY_CLASSES_ROOT for enumerating */
-    if (RegOpenKeyEx(HKEY_CLASSES_ROOT, "", 0,
+    if (RegOpenKeyEx(HKEY_CLASSES_ROOT, nullW, 0,
                      accessOptions, &key) != ERROR_SUCCESS) {
       WINE_FIXME("Unexpected failure opening HKCR key: %d\n", GetLastError());
       return;
@@ -2095,7 +2156,7 @@ void WCMD_assoc (char *command, BOOL assoc) {
 
       /* Enumerate all the keys */
       while (rc != ERROR_NO_MORE_ITEMS) {
-        char  keyName[MAXSTRING];
+        WCHAR  keyName[MAXSTRING];
         DWORD nameLen;
 
         /* Find the next value */
@@ -2111,18 +2172,18 @@ void WCMD_assoc (char *command, BOOL assoc) {
           if ((keyName[0] == '.' && assoc) ||
               (!(keyName[0] == '.') && (!assoc)))
           {
-            char subkey[MAXSTRING];
-            strcpy(subkey, keyName);
-            if (!assoc) strcat(subkey, "\\Shell\\Open\\Command");
+            WCHAR subkey[MAXSTRING];
+            strcpyW(subkey, keyName);
+            if (!assoc) strcatW(subkey, shOpCmdW);
 
             if (RegOpenKeyEx(key, subkey, 0,
                              accessOptions, &readKey) == ERROR_SUCCESS) {
 
-              valueLen = sizeof(keyValue);
+              valueLen = sizeof(keyValue)/sizeof(WCHAR);
               rc = RegQueryValueEx(readKey, NULL, NULL, NULL,
                                    (LPBYTE)keyValue, &valueLen);
               WCMD_output_asis(keyName);
-              WCMD_output_asis("=");
+              WCMD_output_asis(equalW);
               /* If no default value found, leave line empty after '=' */
               if (rc == ERROR_SUCCESS) {
                 WCMD_output_asis(keyValue);
@@ -2138,17 +2199,17 @@ void WCMD_assoc (char *command, BOOL assoc) {
 
       /* Parameter supplied - if no '=' on command line, its a query */
       if (newValue == NULL) {
-        char *space;
-        char subkey[MAXSTRING];
+        WCHAR *space;
+        WCHAR subkey[MAXSTRING];
 
         /* Query terminates the parameter at the first space */
-        strcpy(keyValue, command);
-        space = strchr(keyValue, ' ');
+        strcpyW(keyValue, command);
+        space = strchrW(keyValue, ' ');
         if (space) *space=0x00;
 
         /* Set up key name */
-        strcpy(subkey, keyValue);
-        if (!assoc) strcat(subkey, "\\Shell\\Open\\Command");
+        strcpyW(subkey, keyValue);
+        if (!assoc) strcatW(subkey, shOpCmdW);
 
         if (RegOpenKeyEx(key, subkey, 0,
                          accessOptions, &readKey) == ERROR_SUCCESS) {
@@ -2156,23 +2217,23 @@ void WCMD_assoc (char *command, BOOL assoc) {
           rc = RegQueryValueEx(readKey, NULL, NULL, NULL,
                                (LPBYTE)keyValue, &valueLen);
           WCMD_output_asis(command);
-          WCMD_output_asis("=");
+          WCMD_output_asis(equalW);
           /* If no default value found, leave line empty after '=' */
           if (rc == ERROR_SUCCESS) WCMD_output_asis(keyValue);
           WCMD_output_asis(newline);
           RegCloseKey(readKey);
 
         } else {
-          char  msgbuffer[MAXSTRING];
-          char  outbuffer[MAXSTRING];
+          WCHAR  msgbuffer[MAXSTRING];
+          WCHAR  outbuffer[MAXSTRING];
 
           /* Load the translated 'File association not found' */
           if (assoc) {
-            LoadString (hinst, WCMD_NOASSOC, msgbuffer, sizeof(msgbuffer));
+            LoadString (hinst, WCMD_NOASSOC, msgbuffer, sizeof(msgbuffer)/sizeof(WCHAR));
           } else {
-            LoadString (hinst, WCMD_NOFTYPE, msgbuffer, sizeof(msgbuffer));
+            LoadString (hinst, WCMD_NOFTYPE, msgbuffer, sizeof(msgbuffer)/sizeof(WCHAR));
           }
-          sprintf(outbuffer, msgbuffer, keyValue);
+          wsprintf(outbuffer, msgbuffer, keyValue);
           WCMD_output_asis(outbuffer);
           errorlevel = 2;
         }
@@ -2180,38 +2241,40 @@ void WCMD_assoc (char *command, BOOL assoc) {
       /* Not a query - its a set or clear of a value */
       } else {
 
-        char subkey[MAXSTRING];
+        WCHAR subkey[MAXSTRING];
 
         /* Get pointer to new value */
         *newValue = 0x00;
         newValue++;
 
         /* Set up key name */
-        strcpy(subkey, command);
-        if (!assoc) strcat(subkey, "\\Shell\\Open\\Command");
+        strcpyW(subkey, command);
+        if (!assoc) strcatW(subkey, shOpCmdW);
 
         /* If nothing after '=' then clear value - only valid for ASSOC */
         if (*newValue == 0x00) {
 
           if (assoc) rc = RegDeleteKey(key, command);
           if (assoc && rc == ERROR_SUCCESS) {
-            WINE_TRACE("HKCR Key '%s' deleted\n", command);
+            WINE_TRACE("HKCR Key '%s' deleted\n", wine_dbgstr_w(command));
 
           } else if (assoc && rc != ERROR_FILE_NOT_FOUND) {
             WCMD_print_error();
             errorlevel = 2;
 
           } else {
-            char  msgbuffer[MAXSTRING];
-            char  outbuffer[MAXSTRING];
+            WCHAR  msgbuffer[MAXSTRING];
+            WCHAR  outbuffer[MAXSTRING];
 
             /* Load the translated 'File association not found' */
             if (assoc) {
-              LoadString (hinst, WCMD_NOASSOC, msgbuffer, sizeof(msgbuffer));
+              LoadString (hinst, WCMD_NOASSOC, msgbuffer,
+                          sizeof(msgbuffer)/sizeof(WCHAR));
             } else {
-              LoadString (hinst, WCMD_NOFTYPE, msgbuffer, sizeof(msgbuffer));
+              LoadString (hinst, WCMD_NOFTYPE, msgbuffer,
+                          sizeof(msgbuffer)/sizeof(WCHAR));
             }
-            sprintf(outbuffer, msgbuffer, keyValue);
+            wsprintf(outbuffer, msgbuffer, keyValue);
             WCMD_output_asis(outbuffer);
             errorlevel = 2;
           }
@@ -2222,7 +2285,7 @@ void WCMD_assoc (char *command, BOOL assoc) {
                               accessOptions, NULL, &readKey, NULL);
           if (rc == ERROR_SUCCESS) {
             rc = RegSetValueEx(readKey, NULL, 0, REG_SZ,
-                                 (LPBYTE)newValue, strlen(newValue));
+                                 (LPBYTE)newValue, strlenW(newValue));
             RegCloseKey(readKey);
           }
 
@@ -2231,7 +2294,7 @@ void WCMD_assoc (char *command, BOOL assoc) {
             errorlevel = 2;
           } else {
             WCMD_output_asis(command);
-            WCMD_output_asis("=");
+            WCMD_output_asis(equalW);
             WCMD_output_asis(newValue);
             WCMD_output_asis(newline);
           }
@@ -2256,7 +2319,7 @@ void WCMD_color (void) {
   CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
   HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
 
-  if (param1[0] != 0x00 && strlen(param1) > 2) {
+  if (param1[0] != 0x00 && strlenW(param1) > 2) {
     WCMD_output (WCMD_LoadMessage(WCMD_ARGERR));
     return;
   }
@@ -2276,7 +2339,7 @@ void WCMD_color (void) {
       if (param1[0] == 0x00) {
         color = defaultColor;
       } else {
-        color = strtoul(param1, NULL, 16);
+        color = strtoulW(param1, NULL, 16);
       }
 
       /* Fail if fg == bg color */
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c
index 49c2c1a..a7e6ae4 100644
--- a/programs/cmd/directory.c
+++ b/programs/cmd/directory.c
@@ -33,13 +33,13 @@
 WINE_DEFAULT_DEBUG_CHANNEL(cmd);
 
 int WCMD_dir_sort (const void *a, const void *b);
-char * WCMD_filesize64 (ULONGLONG free);
-char * WCMD_strrev (char *buff);
-static void WCMD_getfileowner(char *filename, char *owner, int ownerlen);
-static void WCMD_dir_trailer(char drive);
+WCHAR * WCMD_filesize64 (ULONGLONG free);
+WCHAR * WCMD_strrev (WCHAR *buff);
+static void WCMD_getfileowner(WCHAR *filename, WCHAR *owner, int ownerlen);
+static void WCMD_dir_trailer(WCHAR drive);
 
 extern int echo_mode;
-extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
 extern DWORD errorlevel;
 
 typedef enum _DISPLAYTIME
@@ -67,6 +67,12 @@ static BOOL orderReverse, orderGroupDirs, orderGroupDirsReverse, orderByCol;
 static BOOL separator;
 static ULONG showattrs, attrsbits;
 
+static const WCHAR dotW[]    = {'.','\0'};
+static const WCHAR dotdotW[] = {'.','.','\0'};
+static const WCHAR starW[]   = {'*','\0'};
+static const WCHAR slashW[]  = {'\\','\0'};
+static const WCHAR emptyW[]  = {'\0'};
+
 /*****************************************************************************
  * WCMD_directory
  *
@@ -74,34 +80,35 @@ static ULONG showattrs, attrsbits;
  *
  */
 
-void WCMD_directory (char *cmd) {
+void WCMD_directory (WCHAR *cmd) {
 
-  char path[MAX_PATH], cwd[MAX_PATH];
+  WCHAR path[MAX_PATH], cwd[MAX_PATH];
   int status, paged_mode;
   CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
-  char *p;
-  char string[MAXSTRING];
+  WCHAR *p;
+  WCHAR string[MAXSTRING];
   int   argno         = 0;
   int   argsProcessed = 0;
-  char *argN          = cmd;
-  char  lastDrive;
+  WCHAR *argN          = cmd;
+  WCHAR  lastDrive;
   BOOL  trailerReqd = FALSE;
   DIRECTORY_STACK *fullParms = NULL;
   DIRECTORY_STACK *prevEntry = NULL;
   DIRECTORY_STACK *thisEntry = NULL;
-  char drive[10];
-  char dir[MAX_PATH];
-  char fname[MAX_PATH];
-  char ext[MAX_PATH];
+  WCHAR drive[10];
+  WCHAR dir[MAX_PATH];
+  WCHAR fname[MAX_PATH];
+  WCHAR ext[MAX_PATH];
+  const WCHAR dircmdW[] = {'D','I','R','C','M','D','\0'};
 
   errorlevel = 0;
 
   /* Prefill Quals with (uppercased) DIRCMD env var */
-  if (GetEnvironmentVariable ("DIRCMD", string, sizeof(string))) {
+  if (GetEnvironmentVariable (dircmdW, string, sizeof(string)/sizeof(WCHAR))) {
     p = string;
     while ( (*p = toupper(*p)) ) ++p;
-    strcat(string,quals);
-    strcpy(quals, string);
+    strcatW(string,quals);
+    strcpyW(quals, string);
   }
 
   byte_total = 0;
@@ -138,7 +145,7 @@ void WCMD_directory (char *cmd) {
       p++;
     }
 
-    WINE_TRACE("Processing arg '%c' (in %s)\n", *p, quals);
+    WINE_TRACE("Processing arg '%c' (in %s)\n", *p, wine_dbgstr_w(quals));
     switch (*p) {
     case 'P': if (negate) paged_mode = !paged_mode;
               else paged_mode = TRUE;
@@ -188,7 +195,7 @@ void WCMD_directory (char *cmd) {
     case 'O': p = p + 1;
               if (*p==':') p++;  /* Skip optional : */
               while (*p && *p != '/') {
-                WINE_TRACE("Processing subparm '%c' (in %s)\n", *p, quals);
+                WINE_TRACE("Processing subparm '%c' (in %s)\n", *p, wine_dbgstr_w(quals));
                 switch (*p) {
                 case 'N': dirOrder = Name;       break;
                 case 'E': dirOrder = Extension;  break;
@@ -222,7 +229,7 @@ void WCMD_directory (char *cmd) {
                   p++;
                 }
 
-                WINE_TRACE("Processing subparm '%c' (in %s)\n", *p, quals);
+                WINE_TRACE("Processing subparm '%c' (in %s)\n", *p, wine_dbgstr_w(quals));
                 switch (*p) {
                 case 'D': mask = FILE_ATTRIBUTE_DIRECTORY; break;
                 case 'H': mask = FILE_ATTRIBUTE_HIDDEN;    break;
@@ -276,62 +283,64 @@ void WCMD_directory (char *cmd) {
   argno         = 0;
   argsProcessed = 0;
   argN          = cmd;
-  GetCurrentDirectory (1024, cwd);
-  strcat(cwd, "\\");
+  GetCurrentDirectory (MAX_PATH, cwd);
+  strcatW(cwd, slashW);
 
   /* Loop through all args, calculating full effective directory */
   fullParms = NULL;
   prevEntry = NULL;
   while (argN) {
-    char fullname[MAXSTRING];
-    char *thisArg = WCMD_parameter (cmd, argno++, &argN);
+    WCHAR fullname[MAXSTRING];
+    WCHAR *thisArg = WCMD_parameter (cmd, argno++, &argN);
     if (argN && argN[0] != '/') {
 
-      WINE_TRACE("Found parm '%s'\n", thisArg);
+      WINE_TRACE("Found parm '%s'\n", wine_dbgstr_w(thisArg));
       if (thisArg[1] == ':' && thisArg[2] == '\\') {
-        strcpy(fullname, thisArg);
+        strcpyW(fullname, thisArg);
       } else if (thisArg[1] == ':' && thisArg[2] != '\\') {
-        char envvar[4];
-        sprintf(envvar, "=%c:", thisArg[0]);
+        WCHAR envvar[4];
+        WCHAR envFmt[] = {'=','%','c',':','\0'};
+        wsprintf(envvar, envFmt, thisArg[0]);
         if (!GetEnvironmentVariable(envvar, fullname, MAX_PATH)) {
-          sprintf(fullname, "%c:", thisArg[0]);
+          WCHAR noEnvFmt[] = {'%','c',':','\0'};
+          wsprintf(fullname, noEnvFmt, thisArg[0]);
         }
-        strcat(fullname, "\\");
-        strcat(fullname, &thisArg[2]);
+        strcatW(fullname, slashW);
+        strcatW(fullname, &thisArg[2]);
       } else if (thisArg[0] == '\\') {
-        strncpy(fullname, cwd, 2);
-        fullname[2] = 0x00;
-        strcat((fullname+2), thisArg);
+        lstrcpynW(fullname, cwd, 3); /* (lstrcpynW inserts null when truncating) */
+        strcatW((fullname+2), thisArg);
       } else {
-        strcpy(fullname, cwd);
-        strcat(fullname, thisArg);
+        strcpyW(fullname, cwd);
+        strcatW(fullname, thisArg);
       }
-      WINE_TRACE("Using location '%s'\n", fullname);
+      WINE_TRACE("Using location '%s'\n", wine_dbgstr_w(fullname));
 
-      status = GetFullPathName (fullname, sizeof(path), path, NULL);
+      status = GetFullPathName (fullname, sizeof(path)/sizeof(WCHAR), path, NULL);
 
       /*
        *  If the path supplied does not include a wildcard, and the endpoint of the
        *  path references a directory, we need to list the *contents* of that
        *  directory not the directory file itself.
        */
-      if ((strchr(path, '*') == NULL) && (strchr(path, '%') == NULL)) {
+      if ((strchrW(path, '*') == NULL) && (strchrW(path, '%') == NULL)) {
         status = GetFileAttributes (path);
         if ((status != INVALID_FILE_ATTRIBUTES) && (status & FILE_ATTRIBUTE_DIRECTORY)) {
-          if (path[strlen(path)-1] == '\\') {
-            strcat (path, "*");
+          if (path[strlenW(path)-1] == '\\') {
+            strcatW (path, starW);
           }
           else {
-            strcat (path, "\\*");
+            const WCHAR slashStarW[]  = {'\\','*','\0'};
+            strcatW (path, slashStarW);
           }
         }
       } else {
         /* Special case wildcard search with no extension (ie parameters ending in '.') as
            GetFullPathName strips off the additional '.'                                  */
-        if (fullname[strlen(fullname)-1] == '.') strcat(path, ".");
+        if (fullname[strlenW(fullname)-1] == '.') strcatW(path, dotW);
       }
 
-      WINE_TRACE("Using path '%s'\n", path);
+      WINE_TRACE("Using path '%s'\n", wine_dbgstr_w(path));
       thisEntry = (DIRECTORY_STACK *) HeapAlloc(GetProcessHeap(),0,sizeof(DIRECTORY_STACK));
       if (fullParms == NULL) fullParms = thisEntry;
       if (prevEntry != NULL) prevEntry->next = thisEntry;
@@ -341,15 +350,18 @@ void WCMD_directory (char *cmd) {
       /* Split into components */
       WCMD_splitpath(path, drive, dir, fname, ext);
       WINE_TRACE("Path Parts: drive: '%s' dir: '%s' name: '%s' ext:'%s'\n",
-                 drive, dir, fname, ext);
+                 wine_dbgstr_w(drive), wine_dbgstr_w(dir),
+                 wine_dbgstr_w(fname), wine_dbgstr_w(ext));
 
-      thisEntry->dirName = HeapAlloc(GetProcessHeap(),0,strlen(drive)+strlen(dir)+1);
-      strcpy(thisEntry->dirName, drive);
-      strcat(thisEntry->dirName, dir);
+      thisEntry->dirName = HeapAlloc(GetProcessHeap(),0,
+                                     sizeof(WCHAR) * (strlenW(drive)+strlenW(dir)+1));
+      strcpyW(thisEntry->dirName, drive);
+      strcatW(thisEntry->dirName, dir);
 
-      thisEntry->fileName = HeapAlloc(GetProcessHeap(),0,strlen(fname)+strlen(ext)+1);
-      strcpy(thisEntry->fileName, fname);
-      strcat(thisEntry->fileName, ext);
+      thisEntry->fileName = HeapAlloc(GetProcessHeap(),0,
+                                     sizeof(WCHAR) * (strlenW(fname)+strlenW(ext)+1));
+      strcpyW(thisEntry->fileName, fname);
+      strcatW(thisEntry->fileName, ext);
 
     }
   }
@@ -359,10 +371,10 @@ void WCMD_directory (char *cmd) {
     WINE_TRACE("Inserting default '*'\n");
     fullParms = (DIRECTORY_STACK *) HeapAlloc(GetProcessHeap(),0, sizeof(DIRECTORY_STACK));
     fullParms->next = NULL;
-    fullParms->dirName = HeapAlloc(GetProcessHeap(),0,(strlen(cwd)+1));
-    strcpy(fullParms->dirName, cwd);
-    fullParms->fileName = HeapAlloc(GetProcessHeap(),0,2);
-    strcpy(fullParms->fileName, "*");
+    fullParms->dirName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR) * (strlenW(cwd)+1));
+    strcpyW(fullParms->dirName, cwd);
+    fullParms->fileName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR) * 2);
+    strcpyW(fullParms->fileName, starW);
   }
 
   lastDrive = '?';
@@ -385,11 +397,10 @@ void WCMD_directory (char *cmd) {
       lastDrive = toupper(thisEntry->dirName[0]);
 
       if (!bare) {
-         char drive[3];
+         WCHAR drive[3];
 
          WINE_TRACE("Writing volume for '%c:'\n", thisEntry->dirName[0]);
-         strncpy(drive, thisEntry->dirName, 2);
-         drive[2] = 0x00;
+         lstrcpynW(drive, thisEntry->dirName, 3); /* (lstrcpynW inserts null when truncating) */
          status = WCMD_volume (0, drive);
          trailerReqd = TRUE;
          if (!status) {
@@ -398,7 +409,8 @@ void WCMD_directory (char *cmd) {
          }
       }
     } else {
-      if (!bare) WCMD_output ("\n\n");
+      const WCHAR newLine2[] = {'\n','\n','\0'};
+      if (!bare) WCMD_output (newLine2);
     }
 
     /* Clear any errors from previous invocations, and process it */
@@ -436,8 +448,8 @@ exit:
 
 static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int level) {
 
-  char string[1024], datestring[32], timestring[32];
-  char real_path[MAX_PATH];
+  WCHAR string[1024], datestring[32], timestring[32];
+  WCHAR real_path[MAX_PATH];
   WIN32_FIND_DATA *fd;
   FILETIME ft;
   SYSTEMTIME st;
@@ -450,6 +462,14 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
   int concurrentDirs = 0;
   BOOL done_header = FALSE;
 
+  const WCHAR fmtDir[]  = {'%','1','0','s',' ',' ','%','8','s',' ',' ',
+                    '<','D','I','R','>',' ',' ',' ',' ',' ',' ',' ',' ',' ','\0'};
+  const WCHAR fmtFile[] = {'%','1','0','s',' ',' ','%','8','s',' ',' ',
+                    ' ',' ','%','1','0','s',' ',' ','\0'};
+  const WCHAR fmt2[]  = {'%','-','1','3','s','\0'};
+  const WCHAR fmt3[]  = {'%','-','2','3','s','\0'};
+  const WCHAR fmt4[]  = {'%','s','\0'};
+  const WCHAR fmt5[]  = {'%','s','%','s','\0'};
 
   dir_count = 0;
   file_count = 0;
@@ -463,15 +483,15 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
      mirrors what windows does                                            */
   parms = inputparms;
   fd = HeapAlloc(GetProcessHeap(),0,sizeof(WIN32_FIND_DATA));
-  while (parms && strcmp(inputparms->dirName, parms->dirName) == 0) {
+  while (parms && strcmpW(inputparms->dirName, parms->dirName) == 0) {
     concurrentDirs++;
 
     /* Work out the full path + filename */
-    strcpy(real_path, parms->dirName);
-    strcat(real_path, parms->fileName);
+    strcpyW(real_path, parms->dirName);
+    strcatW(real_path, parms->fileName);
 
     /* Load all files into an in memory structure */
-    WINE_TRACE("Looking for matches to '%s'\n", real_path);
+    WINE_TRACE("Looking for matches to '%s'\n", wine_dbgstr_w(real_path));
     hff = FindFirstFile (real_path, (fd+entry_count));
     if (hff != INVALID_HANDLE_VALUE) {
       do {
@@ -482,7 +502,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
 
         /* Keep running track of longest filename for wide output */
         if (wide || orderByCol) {
-           int tmpLen = strlen((fd+(entry_count-1))->cFileName) + 3;
+           int tmpLen = strlenW((fd+(entry_count-1))->cFileName) + 3;
            if ((fd+(entry_count-1))->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) tmpLen = tmpLen + 2;
            if (tmpLen > widest) widest = tmpLen;
         }
@@ -499,14 +519,16 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
     }
 
     /* Work out the actual current directory name without a trailing \ */
-    strcpy(real_path, parms->dirName);
-    real_path[strlen(parms->dirName)-1] = 0x00;
+    strcpyW(real_path, parms->dirName);
+    real_path[strlenW(parms->dirName)-1] = 0x00;
 
     /* Output the results */
     if (!bare) {
        if (level != 0 && (entry_count > 0)) WCMD_output (newline);
        if (!recurse || ((entry_count > 0) && done_header==FALSE)) {
-           WCMD_output ("Directory of %s\n\n", real_path);
+           WCHAR headerW[] = {'D','i','r','e','c','t','o','r','y',' ','o','f',
+                              ' ','%','s','\n','\n','\0'};
+           WCMD_output (headerW, real_path);
            done_header = TRUE;
        }
     }
@@ -536,7 +558,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
     for (rows=0; rows<numRows; rows++) {
      BOOL addNewLine = TRUE;
      for (cols=0; cols<numCols; cols++) {
-      char username[24];
+      WCHAR username[24];
 
       /* Work out the index of the entry being pointed to */
       if (orderByCol) {
@@ -549,15 +571,15 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
 
       /* /L convers all names to lower case */
       if (lower) {
-          char *p = (fd+i)->cFileName;
+          WCHAR *p = (fd+i)->cFileName;
           while ( (*p = tolower(*p)) ) ++p;
       }
 
       /* /Q gets file ownership information */
       if (usernames) {
-          lstrcpy (string, inputparms->dirName);
-          lstrcat (string, (fd+i)->cFileName);
-          WCMD_getfileowner(string, username, sizeof(username));
+          strcpyW (string, inputparms->dirName);
+          strcatW (string, (fd+i)->cFileName);
+          WCMD_getfileowner(string, username, sizeof(username)/sizeof(WCHAR));
       }
 
       if (dirTime == Written) {
@@ -569,20 +591,22 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
       }
       FileTimeToSystemTime (&ft, &st);
       GetDateFormat (0, DATE_SHORTDATE, &st, NULL, datestring,
-			sizeof(datestring));
+			sizeof(datestring)/sizeof(WCHAR));
       GetTimeFormat (0, TIME_NOSECONDS, &st,
-			NULL, timestring, sizeof(timestring));
+			NULL, timestring, sizeof(timestring)/sizeof(WCHAR));
 
       if (wide) {
 
         tmp_width = cur_width;
         if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-            WCMD_output ("[%s]", (fd+i)->cFileName);
+            WCHAR fmt[] = {'[','%','s',']','\0'};
+            WCMD_output (fmt, (fd+i)->cFileName);
             dir_count++;
-            tmp_width = tmp_width + strlen((fd+i)->cFileName) + 2;
+            tmp_width = tmp_width + strlenW((fd+i)->cFileName) + 2;
         } else {
-            WCMD_output ("%s", (fd+i)->cFileName);
-            tmp_width = tmp_width + strlen((fd+i)->cFileName) ;
+            WCHAR fmt[] = {'%','s','\0'};
+            WCMD_output (fmt, (fd+i)->cFileName);
+            tmp_width = tmp_width + strlenW((fd+i)->cFileName) ;
             file_count++;
             file_size.u.LowPart = (fd+i)->nFileSizeLow;
             file_size.u.HighPart = (fd+i)->nFileSizeHigh;
@@ -593,21 +617,22 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
         if ((cur_width + widest) > max_width) {
             cur_width = 0;
         } else {
-            WCMD_output ("%*.s", (tmp_width - cur_width) ,"");
+            const WCHAR fmt[]  = {'%','*','.','s','\0'};
+            WCMD_output (fmt, (tmp_width - cur_width), emptyW);
         }
 
       } else if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
         dir_count++;
 
         if (!bare) {
-           WCMD_output ("%10s  %8s  <DIR>         ", datestring, timestring);
-           if (shortname) WCMD_output ("%-13s", (fd+i)->cAlternateFileName);
-           if (usernames) WCMD_output ("%-23s", username);
-           WCMD_output("%s",(fd+i)->cFileName);
+           WCMD_output (fmtDir, datestring, timestring);
+           if (shortname) WCMD_output (fmt2, (fd+i)->cAlternateFileName);
+           if (usernames) WCMD_output (fmt3, username);
+           WCMD_output(fmt4,(fd+i)->cFileName);
         } else {
-           if (!((strcmp((fd+i)->cFileName, ".") == 0) ||
-                 (strcmp((fd+i)->cFileName, "..") == 0))) {
-              WCMD_output ("%s%s", recurse?inputparms->dirName:"", (fd+i)->cFileName);
+           if (!((strcmpW((fd+i)->cFileName, dotW) == 0) ||
+                 (strcmpW((fd+i)->cFileName, dotdotW) == 0))) {
+              WCMD_output (fmt5, recurse?inputparms->dirName:emptyW, (fd+i)->cFileName);
            } else {
               addNewLine = FALSE;
            }
@@ -619,13 +644,13 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
         file_size.u.HighPart = (fd+i)->nFileSizeHigh;
         byte_count.QuadPart += file_size.QuadPart;
         if (!bare) {
-           WCMD_output ("%10s  %8s    %10s  ", datestring, timestring,
+           WCMD_output (fmtFile, datestring, timestring,
                         WCMD_filesize64(file_size.QuadPart));
-           if (shortname) WCMD_output ("%-13s", (fd+i)->cAlternateFileName);
-           if (usernames) WCMD_output ("%-23s", username);
-           WCMD_output("%s",(fd+i)->cFileName);
+           if (shortname) WCMD_output (fmt2, (fd+i)->cAlternateFileName);
+           if (usernames) WCMD_output (fmt3, username);
+           WCMD_output(fmt4,(fd+i)->cFileName);
         } else {
-           WCMD_output ("%s%s", recurse?inputparms->dirName:"", (fd+i)->cFileName);
+           WCMD_output (fmt5, recurse?inputparms->dirName:emptyW, (fd+i)->cFileName);
         }
       }
      }
@@ -635,10 +660,14 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
 
     if (!bare) {
        if (file_count == 1) {
-         WCMD_output ("       1 file %25s bytes\n", WCMD_filesize64 (byte_count.QuadPart));
+         WCHAR fmt[] = {' ',' ',' ',' ',' ',' ',' ','1',' ','f','i','l','e',' ',
+                        '%','2','5','s',' ','b','y','t','e','s','\n','\0'};
+         WCMD_output (fmt, WCMD_filesize64 (byte_count.QuadPart));
        }
        else {
-         WCMD_output ("%8d files %24s bytes\n", file_count, WCMD_filesize64 (byte_count.QuadPart));
+         WCHAR fmt[] = {'%','8','d',' ','f','i','l','e','s',' ','%','2','4','s',
+                        ' ','b','y','t','e','s','\n','\0'};
+         WCMD_output (fmt, file_count, WCMD_filesize64 (byte_count.QuadPart));
        }
     }
     byte_total = byte_total + byte_count.QuadPart;
@@ -646,8 +675,15 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
     dir_total = dir_total + dir_count;
 
     if (!bare && !recurse) {
-       if (dir_count == 1) WCMD_output ("%8d directory         ", 1);
-       else WCMD_output ("%8d directories", dir_count);
+       if (dir_count == 1) {
+           WCHAR fmt[] = {'%','8','d',' ','d','i','r','e','c','t','o','r','y',
+                          ' ',' ',' ',' ',' ',' ',' ',' ',' ','\0'};
+           WCMD_output (fmt, 1);
+       } else {
+           WCHAR fmt[] = {'%','8','d',' ','d','i','r','e','c','t','o','r','i',
+                          'e','s','\0'};
+           WCMD_output (fmt, dir_count);
+       }
     }
   }
   HeapFree(GetProcessHeap(),0,fd);
@@ -659,16 +695,16 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
     WIN32_FIND_DATA finddata;
 
     /* Build path to search */
-    strcpy(string, inputparms->dirName);
-    strcat(string, "*");
+    strcpyW(string, inputparms->dirName);
+    strcatW(string, starW);
 
-    WINE_TRACE("Recursive, looking for '%s'\n", string);
+    WINE_TRACE("Recursive, looking for '%s'\n", wine_dbgstr_w(string));
     hff = FindFirstFile (string, &finddata);
     if (hff != INVALID_HANDLE_VALUE) {
       do {
         if ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
-            (strcmp(finddata.cFileName, "..") != 0) &&
-            (strcmp(finddata.cFileName, ".") != 0)) {
+            (strcmpW(finddata.cFileName, dotdotW) != 0) &&
+            (strcmpW(finddata.cFileName, dotW) != 0)) {
 
           DIRECTORY_STACK *thisDir;
           int              dirsToCopy = concurrentDirs;
@@ -679,10 +715,10 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
             dirsToCopy--;
 
             /* Work out search parameter in sub dir */
-            strcpy (string, inputparms->dirName);
-            strcat (string, finddata.cFileName);
-            strcat (string, "\\");
-            WINE_TRACE("Recursive, Adding to search list '%s'\n", string);
+            strcpyW (string, inputparms->dirName);
+            strcatW (string, finddata.cFileName);
+            strcatW (string, slashW);
+            WINE_TRACE("Recursive, Adding to search list '%s'\n", wine_dbgstr_w(string));
 
             /* Allocate memory, add to list */
             thisDir = (DIRECTORY_STACK *) HeapAlloc(GetProcessHeap(),0,sizeof(DIRECTORY_STACK));
@@ -690,10 +726,12 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
             if (lastEntry != NULL) lastEntry->next = thisDir;
             lastEntry = thisDir;
             thisDir->next = NULL;
-            thisDir->dirName = HeapAlloc(GetProcessHeap(),0,(strlen(string)+1));
-            strcpy(thisDir->dirName, string);
-            thisDir->fileName = HeapAlloc(GetProcessHeap(),0,(strlen(parms->fileName)+1));
-            strcpy(thisDir->fileName, parms->fileName);
+            thisDir->dirName = HeapAlloc(GetProcessHeap(),0,
+                                         sizeof(WCHAR) * (strlenW(string)+1));
+            strcpyW(thisDir->dirName, string);
+            thisDir->fileName = HeapAlloc(GetProcessHeap(),0,
+                                          sizeof(WCHAR) * (strlenW(parms->fileName)+1));
+            strcpyW(thisDir->fileName, parms->fileName);
             parms = parms->next;
           }
         }
@@ -727,17 +765,17 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
 /*****************************************************************************
  * WCMD_filesize64
  *
- * Convert a 64-bit number into a character string, with commas every three digits.
+ * Convert a 64-bit number into a WCHARacter string, with commas every three digits.
  * Result is returned in a static string overwritten with each call.
  * FIXME: There must be a better algorithm!
  */
 
-char * WCMD_filesize64 (ULONGLONG n) {
+WCHAR * WCMD_filesize64 (ULONGLONG n) {
 
   ULONGLONG q;
   unsigned int r, i;
-  char *p;
-  static char buff[32];
+  WCHAR *p;
+  static WCHAR buff[32];
 
   p = buff;
   i = -3;
@@ -756,15 +794,15 @@ char * WCMD_filesize64 (ULONGLONG n) {
 /*****************************************************************************
  * WCMD_strrev
  *
- * Reverse a character string in-place (strrev() is not available under unixen :-( ).
+ * Reverse a WCHARacter string in-place (strrev() is not available under unixen :-( ).
  */
 
-char * WCMD_strrev (char *buff) {
+WCHAR * WCMD_strrev (WCHAR *buff) {
 
   int r, i;
-  char b;
+  WCHAR b;
 
-  r = lstrlen (buff);
+  r = strlenW (buff);
   for (i=0; i<r/2; i++) {
     b = buff[i];
     buff[i] = buff[r-i-1];
@@ -799,7 +837,7 @@ int WCMD_dir_sort (const void *a, const void *b)
 
   /* Order by Name: */
   } else if (dirOrder == Name) {
-    result = lstrcmpi(filea->cFileName, fileb->cFileName);
+    result = lstrcmpiW(filea->cFileName, fileb->cFileName);
 
   /* Order by Size: */
   } else if (dirOrder == Size) {
@@ -837,16 +875,16 @@ int WCMD_dir_sort (const void *a, const void *b)
 
   /* Order by Extension: (Takes into account which date (/T option) */
   } else if (dirOrder == Extension) {
-      char drive[10];
-      char dir[MAX_PATH];
-      char fname[MAX_PATH];
-      char extA[MAX_PATH];
-      char extB[MAX_PATH];
+      WCHAR drive[10];
+      WCHAR dir[MAX_PATH];
+      WCHAR fname[MAX_PATH];
+      WCHAR extA[MAX_PATH];
+      WCHAR extB[MAX_PATH];
 
       /* Split into components */
       WCMD_splitpath(filea->cFileName, drive, dir, fname, extA);
       WCMD_splitpath(fileb->cFileName, drive, dir, fname, extB);
-      result = lstrcmpi(extA, extB);
+      result = lstrcmpiW(extA, extB);
   }
 
   if (orderReverse) result = -result;
@@ -856,14 +894,14 @@ int WCMD_dir_sort (const void *a, const void *b)
 /*****************************************************************************
  * WCMD_getfileowner
  *
- * Reverse a character string in-place (strrev() is not available under unixen :-( ).
+ * Reverse a WCHARacter string in-place (strrev() is not available under unixen :-( ).
  */
-void WCMD_getfileowner(char *filename, char *owner, int ownerlen) {
+void WCMD_getfileowner(WCHAR *filename, WCHAR *owner, int ownerlen) {
 
     ULONG sizeNeeded = 0;
     DWORD rc;
-    char name[MAXSTRING];
-    char domain[MAXSTRING];
+    WCHAR name[MAXSTRING];
+    WCHAR domain[MAXSTRING];
 
     /* In case of error, return empty string */
     *owner = 0x00;
@@ -899,7 +937,8 @@ void WCMD_getfileowner(char *filename, char *owner, int ownerlen) {
 
         /* Convert to a username */
         if (LookupAccountSid(NULL, pSID, name, &nameLen, domain, &domainLen, &nameuse)) {
-            snprintf(owner, ownerlen, "%s%c%s", domain, '\\', name);
+            const WCHAR fmt[]  = {'%','s','%','c','%','s','\0'};
+            snprintfW(owner, ownerlen, fmt, domain, '\\', name);
         }
         HeapFree(GetProcessHeap(),0,secBuffer);
     }
@@ -911,23 +950,30 @@ void WCMD_getfileowner(char *filename, char *owner, int ownerlen) {
  *
  * Print out the trailer for the supplied drive letter
  */
-static void WCMD_dir_trailer(char drive) {
+static void WCMD_dir_trailer(WCHAR drive) {
     ULARGE_INTEGER avail, total, freebytes;
     DWORD status;
-    char driveName[4] = "c:\\";
+    WCHAR driveName[4] = {'c',':','\\','\0'};
 
     driveName[0] = drive;
     status = GetDiskFreeSpaceEx (driveName, &avail, &total, &freebytes);
-    WINE_TRACE("Writing trailer for '%s' gave %d(%d)\n", driveName, status, GetLastError());
+    WINE_TRACE("Writing trailer for '%s' gave %d(%d)\n", wine_dbgstr_w(driveName),
+               status, GetLastError());
 
     if (errorlevel==0 && !bare) {
       if (recurse) {
-        WCMD_output ("\n     Total files listed:\n%8d files%25s bytes\n",
-             file_total, WCMD_filesize64 (byte_total));
-        WCMD_output ("%8d directories %18s bytes free\n\n",
-             dir_total, WCMD_filesize64 (freebytes.QuadPart));
+        WCHAR fmt1[] = {'\n',' ',' ',' ',' ',' ','T','o','t','a','l',' ','f','i','l','e','s',
+                        ' ','l','i','s','t','e','d',':','\n','%','8','d',' ','f','i','l','e',
+                        's','%','2','5','s',' ','b','y','t','e','s','\n','\0'};
+        WCHAR fmt2[] = {'%','8','d',' ','d','i','r','e','c','t','o','r','i','e','s',' ','%',
+                        '1','8','s',' ','b','y','t','e','s',' ','f','r','e','e','\n','\n',
+                        '\0'};
+        WCMD_output (fmt1, file_total, WCMD_filesize64 (byte_total));
+        WCMD_output (fmt2, dir_total, WCMD_filesize64 (freebytes.QuadPart));
       } else {
-        WCMD_output (" %18s bytes free\n\n", WCMD_filesize64 (freebytes.QuadPart));
+        WCHAR fmt[] = {' ','%','1','8','s',' ','b','y','t','e','s',' ','f','r','e','e',
+                       '\n','\n','\0'};
+        WCMD_output (fmt, WCMD_filesize64 (freebytes.QuadPart));
       }
     }
 }
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index ab13595..9fe729d 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -28,71 +28,74 @@
 #include <ctype.h>
 #include <wine/unicode.h>
 
-void WCMD_assoc (char *, BOOL);
-void WCMD_batch (char *, char *, int, char *, HANDLE);
-void WCMD_call (char *command);
+void WCMD_assoc (WCHAR *, BOOL);
+void WCMD_batch (WCHAR *, WCHAR *, int, WCHAR *, HANDLE);
+void WCMD_call (WCHAR *command);
 void WCMD_change_tty (void);
 void WCMD_clear_screen (void);
 void WCMD_color (void);
 void WCMD_copy (void);
 void WCMD_create_dir (void);
-BOOL WCMD_delete (char *, BOOL);
-void WCMD_directory (char *);
-void WCMD_echo (const char *);
+BOOL WCMD_delete (WCHAR *, BOOL);
+void WCMD_directory (WCHAR *);
+void WCMD_echo (const WCHAR *);
 void WCMD_endlocal (void);
-void WCMD_enter_paged_mode(const char *);
+void WCMD_enter_paged_mode(const WCHAR *);
 void WCMD_exit (void);
-void WCMD_for (char *);
-void WCMD_give_help (char *command);
+void WCMD_for (WCHAR *);
+void WCMD_give_help (WCHAR *command);
 void WCMD_goto (void);
-void WCMD_if (char *);
+void WCMD_if (WCHAR *);
 void WCMD_leave_paged_mode(void);
-void WCMD_more (char *);
+void WCMD_more (WCHAR *);
 void WCMD_move (void);
-void WCMD_output (const char *format, ...);
-void WCMD_output_asis (const char *message);
-void WCMD_parse (char *s, char *q, char *p1, char *p2);
+void WCMD_output (const WCHAR *format, ...);
+void WCMD_output_asis (const WCHAR *message);
+void WCMD_parse (WCHAR *s, WCHAR *q, WCHAR *p1, WCHAR *p2);
 void WCMD_pause (void);
-void WCMD_pipe (char *command);
+void WCMD_pipe (WCHAR *command);
 void WCMD_popd (void);
 void WCMD_print_error (void);
-void WCMD_process_command (char *command);
-void WCMD_pushd (char *);
-int  WCMD_read_console (char *string, int str_len);
-void WCMD_remove_dir (char *command);
+void WCMD_process_command (WCHAR *command);
+void WCMD_pushd (WCHAR *);
+int  WCMD_read_console (WCHAR *string, int str_len);
+void WCMD_remove_dir (WCHAR *command);
 void WCMD_rename (void);
-void WCMD_run_program (char *command, int called);
-void WCMD_setlocal (const char *command);
+void WCMD_run_program (WCHAR *command, int called);
+void WCMD_setlocal (const WCHAR *command);
 void WCMD_setshow_attrib (void);
 void WCMD_setshow_date (void);
-void WCMD_setshow_default (char *command);
-void WCMD_setshow_env (char *command);
-void WCMD_setshow_path (char *command);
+void WCMD_setshow_default (WCHAR *command);
+void WCMD_setshow_env (WCHAR *command);
+void WCMD_setshow_path (WCHAR *command);
 void WCMD_setshow_prompt (void);
 void WCMD_setshow_time (void);
-void WCMD_shift (char *command);
+void WCMD_shift (WCHAR *command);
 void WCMD_show_prompt (void);
-void WCMD_title (char *);
-void WCMD_type (char *);
-void WCMD_verify (char *command);
+void WCMD_title (WCHAR *);
+void WCMD_type (WCHAR *);
+void WCMD_verify (WCHAR *command);
 void WCMD_version (void);
-int  WCMD_volume (int mode, char *command);
-
-char *WCMD_fgets (char *s, int n, HANDLE stream);
-char *WCMD_parameter (char *s, int n, char **where);
-char *WCMD_strtrim_leading_spaces (char *string);
-void WCMD_strtrim_trailing_spaces (char *string);
-void WCMD_opt_s_strip_quotes(char *cmd);
-void WCMD_HandleTildaModifiers(char **start, char *forVariable);
-BOOL WCMD_ask_confirm (char *message, BOOL showSureText, BOOL *optionAll);
-
-void WCMD_splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext);
-char *WCMD_LoadMessage(UINT id);
+int  WCMD_volume (int mode, WCHAR *command);
+
+WCHAR *WCMD_fgets (WCHAR *s, int n, HANDLE stream);
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where);
+WCHAR *WCMD_strtrim_leading_spaces (WCHAR *string);
+void WCMD_strtrim_trailing_spaces (WCHAR *string);
+void WCMD_opt_s_strip_quotes(WCHAR *cmd);
+void WCMD_HandleTildaModifiers(WCHAR **start, WCHAR *forVariable);
+BOOL WCMD_ask_confirm (WCHAR *message, BOOL showSureText, BOOL *optionAll);
+
+void WCMD_splitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
+WCHAR *WCMD_LoadMessage(UINT id);
+WCHAR *WCMD_strdupW(WCHAR *input);
+BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars,
+                   LPDWORD charsRead, const LPOVERLAPPED unused);
 
 /*	Data structure to hold context when executing batch files */
 
 typedef struct {
-  char *command;	/* The command which invoked the batch file */
+  WCHAR *command;	/* The command which invoked the batch file */
   HANDLE h;             /* Handle to the open batch file */
   int shift_count[10];	/* Offset in terms of shifts for %0 - %9 */
   void *prev_context;	/* Pointer to the previous context block */
@@ -106,7 +109,7 @@ struct env_stack
   struct env_stack *next;
   union {
     int    stackdepth;       /* Only used for pushd and popd */
-    char   cwd;              /* Only used for set/endlocal   */
+    WCHAR   cwd;              /* Only used for set/endlocal   */
   } u;
   WCHAR *strings;
 };
@@ -116,8 +119,8 @@ struct env_stack
 typedef struct _DIRECTORY_STACK
 {
   struct _DIRECTORY_STACK *next;
-  char  *dirName;
-  char  *fileName;
+  WCHAR  *dirName;
+  WCHAR  *fileName;
 } DIRECTORY_STACK;
 
 #endif /* !RC_INVOKED */
@@ -181,9 +184,9 @@ typedef struct _DIRECTORY_STACK
 #define WCMD_EXIT   44
 
 /* Some standard messages */
-extern const char newline[];
-extern const char version_string[];
-extern const char anykey[];
+extern const WCHAR newline[];
+extern WCHAR anykey[];
+extern WCHAR version_string[];
 
 /* Translated messages */
 #define WCMD_CONFIRM          1001
@@ -215,6 +218,11 @@ extern const char anykey[];
 #define WCMD_ARGERR           1027
 #define WCMD_VOLUMEDETAIL     1028
 #define WCMD_VOLUMEPROMPT     1029
+#define WCMD_NOPATH           1030
+#define WCMD_ANYKEY           1031
+#define WCMD_CONSTITLE        1032
+#define WCMD_VERSION          1033
+
 
 /* msdn specified max for Win XP */
 #define MAXSTRING 8192
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index 85fe005..eeeda33 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -30,27 +30,70 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(cmd);
 
-const char * const inbuilt[] = {"ATTRIB", "CALL", "CD", "CHDIR", "CLS", "COPY", "CTTY",
-		"DATE", "DEL", "DIR", "ECHO", "ERASE", "FOR", "GOTO",
-		"HELP", "IF", "LABEL", "MD", "MKDIR", "MOVE", "PATH", "PAUSE",
-		"PROMPT", "REM", "REN", "RENAME", "RD", "RMDIR", "SET", "SHIFT",
-                "TIME", "TITLE", "TYPE", "VERIFY", "VER", "VOL",
-                "ENDLOCAL", "SETLOCAL", "PUSHD", "POPD", "ASSOC", "COLOR", "FTYPE",
-                "MORE", "EXIT" };
+const WCHAR inbuilt[][10] = {
+        {'A','T','T','R','I','B','\0'},
+        {'C','A','L','L','\0'},
+        {'C','D','\0'},
+        {'C','H','D','I','R','\0'},
+        {'C','L','S','\0'},
+        {'C','O','P','Y','\0'},
+        {'C','T','T','Y','\0'},
+        {'D','A','T','E','\0'},
+        {'D','E','L','\0'},
+        {'D','I','R','\0'},
+        {'E','C','H','O','\0'},
+        {'E','R','A','S','E','\0'},
+        {'F','O','R','\0'},
+        {'G','O','T','O','\0'},
+        {'H','E','L','P','\0'},
+        {'I','F','\0'},
+        {'L','A','B','E','L','\0'},
+        {'M','D','\0'},
+        {'M','K','D','I','R','\0'},
+        {'M','O','V','E','\0'},
+        {'P','A','T','H','\0'},
+        {'P','A','U','S','E','\0'},
+        {'P','R','O','M','P','T','\0'},
+        {'R','E','M','\0'},
+        {'R','E','N','\0'},
+        {'R','E','N','A','M','E','\0'},
+        {'R','D','\0'},
+        {'R','M','D','I','R','\0'},
+        {'S','E','T','\0'},
+        {'S','H','I','F','T','\0'},
+        {'T','I','M','E','\0'},
+        {'T','I','T','L','E','\0'},
+        {'T','Y','P','E','\0'},
+        {'V','E','R','I','F','Y','\0'},
+        {'V','E','R','\0'},
+        {'V','O','L','\0'},
+        {'E','N','D','L','O','C','A','L','\0'},
+        {'S','E','T','L','O','C','A','L','\0'},
+        {'P','U','S','H','D','\0'},
+        {'P','O','P','D','\0'},
+        {'A','S','S','O','C','\0'},
+        {'C','O','L','O','R','\0'},
+        {'F','T','Y','P','E','\0'},
+        {'M','O','R','E','\0'},
+        {'E','X','I','T','\0'}
+};
 
 HINSTANCE hinst;
 DWORD errorlevel;
 int echo_mode = 1, verify_mode = 0, defaultColor = 7;
 static int opt_c, opt_k, opt_s;
-const char newline[] = "\n";
-const char version_string[] = "CMD Version " PACKAGE_VERSION "\n\n";
-const char anykey[] = "Press Return key to continue: ";
-char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+const WCHAR newline[] = {'\n','\0'};
+static const WCHAR equalsW[] = {'=','\0'};
+WCHAR anykey[100];
+WCHAR version_string[100];
+WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
 BATCH_CONTEXT *context = NULL;
 extern struct env_stack *pushd_directories;
-static const char *pagedMessage = NULL;
+static const WCHAR *pagedMessage = NULL;
+static char  *output_bufA = NULL;
+#define MAX_WRITECONSOLE_SIZE 65535
 
-static char *WCMD_expand_envvar(char *start);
+static WCHAR *WCMD_expand_envvar(WCHAR *start);
 
 /*****************************************************************************
  * Main entry point. This is a console application so we have a main() not a
@@ -61,14 +104,22 @@ int main (int argc, char *argv[])
 {
   LPWSTR *argvW = NULL;
   int     args;
-  WCHAR  *cmdW  = NULL;
-  char string[1024];
-  char envvar[4];
-  char* cmd=NULL;
+  WCHAR  *cmd   = NULL;
+  WCHAR string[1024];
+  WCHAR envvar[4];
   DWORD count;
   HANDLE h;
   int opt_q;
   int opt_t = 0;
+  const WCHAR autoexec[] = {'\\','a','u','t','o','e','x','e','c','.',
+                            'b','a','t','\0'};
+  char ansiVersion[100];
+
+  /* Pre initialize some messages */
+  strcpy(ansiVersion, PACKAGE_VERSION);
+  MultiByteToWideChar(CP_ACP, 0, ansiVersion, -1, string, 1024);
+  wsprintf(version_string, WCMD_LoadMessage(WCMD_VERSION), string);
+  strcpyW(anykey, WCMD_LoadMessage(WCMD_ANYKEY));
 
   /* Get a Unicode command line */
   argvW = CommandLineToArgvW( GetCommandLineW(), &argc );
@@ -114,7 +165,8 @@ int main (int argc, char *argv[])
   }
 
   if (opt_q) {
-    WCMD_echo("OFF");
+    const WCHAR eoff[] = {'O','F','F','\0'};
+    WCMD_echo(eoff);
   }
 
   if (opt_c || opt_k) {
@@ -185,11 +237,11 @@ int main (int argc, char *argv[])
           }
       }
 
-      cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-      if (!cmdW)
+      cmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+      if (!cmd)
           exit(1);
 
-      p = cmdW;
+      p = cmd;
       argsLeft = args;
       for (arg = argvW; argsLeft>0; arg++,argsLeft--)
       {
@@ -249,19 +301,11 @@ int main (int argc, char *argv[])
               *p++='"';
           *p++=' ';
       }
-      if (p > cmdW)
+      if (p > cmd)
           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);
+      WINE_TRACE("/c command line: '%s'\n", wine_dbgstr_w(cmd));
 
       /* strip first and last quote characters if opt_s; check for invalid
        * executable is done later */
@@ -275,18 +319,17 @@ int main (int argc, char *argv[])
        * the currently allocated input and output handles. This allows
        * us to pipe to and read from the command interpreter.
        */
-      if (strchr(cmd,'|') != NULL)
+      if (strchrW(cmd,'|') != NULL)
           WCMD_pipe(cmd);
       else
           WCMD_process_command(cmd);
       HeapFree(GetProcessHeap(), 0, cmd);
-      HeapFree(GetProcessHeap(), 0, cmdW);
       return errorlevel;
   }
 
   SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_LINE_INPUT |
                  ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
-  SetConsoleTitle("Wine Command Prompt");
+  SetConsoleTitle(WCMD_LoadMessage(WCMD_CONSTITLE));
 
   /* Note: cmd.exe /c dir does not get a new color, /k dir does */
   if (opt_t) {
@@ -304,44 +347,47 @@ int main (int argc, char *argv[])
       HKEY key;
       DWORD type;
       DWORD value=0, size=4;
+      const WCHAR regKeyW[] = {'S','o','f','t','w','a','r','e','\\',
+          'M','i','c','r','o','s','o','f','t','\\',
+          'C','o','m','m','a','n','d',' ','P','r','o','c','e','s','s','o','r','\0'};
+      const WCHAR dfltColorW[] = {'D','e','f','a','u','l','t','C','o','l','o','r','\0'};
 
-      if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Command Processor",
+      if (RegOpenKeyEx(HKEY_CURRENT_USER, regKeyW,
                        0, KEY_READ, &key) == ERROR_SUCCESS) {
-          char  strvalue[4];
+          WCHAR  strvalue[4];
 
           /* See if DWORD or REG_SZ */
-          if (RegQueryValueEx(key, "DefaultColor", NULL, &type,
+          if (RegQueryValueEx(key, dfltColorW, NULL, &type,
                      NULL, NULL) == ERROR_SUCCESS) {
               if (type == REG_DWORD) {
                   size = sizeof(DWORD);
-                  RegQueryValueEx(key, "DefaultColor", NULL, NULL,
+                  RegQueryValueEx(key, dfltColorW, NULL, NULL,
                                   (LPBYTE)&value, &size);
               } else if (type == REG_SZ) {
-                  size = sizeof(strvalue);
-                  RegQueryValueEx(key, "DefaultColor", NULL, NULL,
+                  size = sizeof(strvalue)/sizeof(WCHAR);
+                  RegQueryValueEx(key, dfltColorW, NULL, NULL,
                                   (LPBYTE)strvalue, &size);
-                  value = strtoul(strvalue, NULL, 10);
+                  value = strtoulW(strvalue, NULL, 10);
               }
           }
       }
 
-      if (value == 0 && RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                       "Software\\Microsoft\\Command Processor",
+      if (value == 0 && RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKeyW,
                        0, KEY_READ, &key) == ERROR_SUCCESS) {
-          char  strvalue[4];
+          WCHAR  strvalue[4];
 
           /* See if DWORD or REG_SZ */
-          if (RegQueryValueEx(key, "DefaultColor", NULL, &type,
+          if (RegQueryValueEx(key, dfltColorW, NULL, &type,
                      NULL, NULL) == ERROR_SUCCESS) {
               if (type == REG_DWORD) {
                   size = sizeof(DWORD);
-                  RegQueryValueEx(key, "DefaultColor", NULL, NULL,
+                  RegQueryValueEx(key, dfltColorW, NULL, NULL,
                                   (LPBYTE)&value, &size);
               } else if (type == REG_SZ) {
-                  size = sizeof(strvalue);
-                  RegQueryValueEx(key, "DefaultColor", NULL, NULL,
+                  size = sizeof(strvalue)/sizeof(WCHAR);
+                  RegQueryValueEx(key, dfltColorW, NULL, NULL,
                                   (LPBYTE)strvalue, &size);
-                  value = strtoul(strvalue, NULL, 10);
+                  value = strtoulW(strvalue, NULL, 10);
               }
           }
       }
@@ -358,26 +404,26 @@ int main (int argc, char *argv[])
   /* Save cwd into appropriate env var */
   GetCurrentDirectory(1024, string);
   if (IsCharAlpha(string[0]) && string[1] == ':') {
-    sprintf(envvar, "=%c:", string[0]);
+    const WCHAR fmt[] = {'=','%','c',':','\0'};
+    wsprintf(envvar, fmt, string[0]);
     SetEnvironmentVariable(envvar, string);
   }
 
   if (opt_k) {
       WCMD_process_command(cmd);
       HeapFree(GetProcessHeap(), 0, cmd);
-      HeapFree(GetProcessHeap(), 0, cmdW);
   }
 
 /*
  *	If there is an AUTOEXEC.BAT file, try to execute it.
  */
 
-  GetFullPathName ("\\autoexec.bat", sizeof(string), string, NULL);
+  GetFullPathName (autoexec, sizeof(string)/sizeof(WCHAR), string, NULL);
   h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   if (h != INVALID_HANDLE_VALUE) {
     CloseHandle (h);
 #if 0
-    WCMD_batch ((char *)"\\autoexec.bat", (char *)"\\autoexec.bat", 0, NULL, INVALID_HANDLE_VALUE);
+    WCMD_batch (autoexec, autoexec, 0, NULL, INVALID_HANDLE_VALUE);
 #endif
   }
 
@@ -388,12 +434,13 @@ int main (int argc, char *argv[])
   WCMD_version ();
   while (TRUE) {
     WCMD_show_prompt ();
-    ReadFile (GetStdHandle(STD_INPUT_HANDLE), string, sizeof(string), &count, NULL);
+    WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), string,
+                   sizeof(string)/sizeof(WCHAR), &count, NULL);
     if (count > 1) {
       string[count-1] = '\0'; /* ReadFile output is not null-terminated! */
       if (string[count-2] == '\r') string[count-2] = '\0'; /* Under Windoze we get CRLF! */
-      if (lstrlen (string) != 0) {
-        if (strchr(string,'|') != NULL) {
+      if (strlenW (string) != 0) {
+        if (strchrW(string,'|') != NULL) {
           WCMD_pipe (string);
         }
         else {
@@ -411,16 +458,16 @@ int main (int argc, char *argv[])
  */
 
 
-void WCMD_process_command (char *command)
+void WCMD_process_command (WCHAR *command)
 {
-    char *cmd, *p, *s, *t, *redir;
+    WCHAR *cmd, *p, *s, *t, *redir;
     int status, i;
     DWORD count, creationDisposition;
     HANDLE h;
-    char *whichcmd;
+    WCHAR *whichcmd;
     SECURITY_ATTRIBUTES sa;
-    char *new_cmd;
-    char *first_redir = NULL;
+    WCHAR *new_cmd;
+    WCHAR *first_redir = NULL;
     HANDLE old_stdhandles[3] = {INVALID_HANDLE_VALUE,
                                 INVALID_HANDLE_VALUE,
                                 INVALID_HANDLE_VALUE};
@@ -429,8 +476,8 @@ void WCMD_process_command (char *command)
                                 STD_ERROR_HANDLE};
 
     /* Move copy of the command onto the heap so it can be expanded */
-    new_cmd = HeapAlloc( GetProcessHeap(), 0, MAXSTRING );
-    strcpy(new_cmd, command);
+    new_cmd = HeapAlloc( GetProcessHeap(), 0, MAXSTRING * sizeof(WCHAR));
+    strcpyW(new_cmd, command);
 
     /* For commands in a context (batch program):                  */
     /*   Expand environment variables in a batch file %{0-9} first */
@@ -442,7 +489,7 @@ void WCMD_process_command (char *command)
     /*   manual expansion of environment variables here            */
 
     p = new_cmd;
-    while ((p = strchr(p, '%'))) {
+    while ((p = strchrW(p, '%'))) {
       i = *(p+1) - '0';
 
       /* Replace %~ modifications if in batch program */
@@ -452,20 +499,20 @@ void WCMD_process_command (char *command)
 
       /* Replace use of %0...%9 if in batch program*/
       } else if (context && (i >= 0) && (i <= 9)) {
-        s = strdup (p+2);
+        s = WCMD_strdupW(p+2);
         t = WCMD_parameter (context -> command, i + context -> shift_count[i], NULL);
-        strcpy (p, t);
-        strcat (p, s);
+        strcpyW (p, t);
+        strcatW (p, s);
         free (s);
 
       /* Replace use of %* if in batch program*/
       } else if (context && *(p+1)=='*') {
-        char *startOfParms = NULL;
-        s = strdup (p+2);
+        WCHAR *startOfParms = NULL;
+        s = WCMD_strdupW(p+2);
         t = WCMD_parameter (context -> command, 1, &startOfParms);
-        if (startOfParms != NULL) strcpy (p, startOfParms);
+        if (startOfParms != NULL) strcpyW (p, startOfParms);
         else *p = 0x00;
-        strcat (p, s);
+        strcatW (p, s);
         free (s);
 
       } else {
@@ -478,13 +525,13 @@ void WCMD_process_command (char *command)
     /* so remove any remaining %var%                                */
     if (context) {
       p = cmd;
-      while ((p = strchr(p, '%'))) {
-        s = strchr(p+1, '%');
+      while ((p = strchrW(p, '%'))) {
+        s = strchrW(p+1, '%');
         if (!s) {
           *p=0x00;
         } else {
-          t = strdup(s+1);
-          strcpy(p, t);
+          t = WCMD_strdupW(s+1);
+          strcpyW(p, t);
           free(t);
         }
       }
@@ -501,17 +548,18 @@ void WCMD_process_command (char *command)
  *	Changing default drive has to be handled as a special case.
  */
 
-    if ((cmd[1] == ':') && IsCharAlpha (cmd[0]) && (strlen(cmd) == 2)) {
-      char envvar[5];
-      char dir[MAX_PATH];
+    if ((cmd[1] == ':') && IsCharAlpha (cmd[0]) && (strlenW(cmd) == 2)) {
+      WCHAR envvar[5];
+      WCHAR dir[MAX_PATH];
 
       /* According to MSDN CreateProcess docs, special env vars record
          the current directory on each drive, in the form =C:
          so see if one specified, and if so go back to it             */
-      strcpy(envvar, "=");
-      strcat(envvar, cmd);
+      strcpyW(envvar, equalsW);
+      strcatW(envvar, cmd);
       if (GetEnvironmentVariable(envvar, dir, MAX_PATH) == 0) {
-        sprintf(cmd, "%s\\", cmd);
+        const WCHAR fmt[] = {'%','s','\\','\0'};
+        wsprintf(cmd, fmt, cmd);
       }
       status = SetCurrentDirectory (cmd);
       if (!status) WCMD_print_error ();
@@ -527,7 +575,7 @@ void WCMD_process_command (char *command)
  *	Redirect stdin, stdout and/or stderr if required.
  */
 
-    if ((p = strchr(cmd,'<')) != NULL) {
+    if ((p = strchrW(cmd,'<')) != NULL) {
       if (first_redir == NULL) first_redir = p;
       h = CreateFile (WCMD_parameter (++p, 0, NULL), GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING,
 		FILE_ATTRIBUTE_NORMAL, NULL);
@@ -542,7 +590,7 @@ void WCMD_process_command (char *command)
 
     /* Scan the whole command looking for > and 2> */
     redir = cmd;
-    while (redir != NULL && ((p = strchr(redir,'>')) != NULL)) {
+    while (redir != NULL && ((p = strchrW(redir,'>')) != NULL)) {
       int handle = 0;
 
       if (*(p-1)!='2') {
@@ -577,7 +625,7 @@ void WCMD_process_command (char *command)
         WINE_TRACE("Redirect %d (%p) to %d (%p)\n", handle, GetStdHandle(idx_stdhandles[idx]), idx, h);
 
       } else {
-        char *param = WCMD_parameter (p, 0, NULL);
+        WCHAR *param = WCMD_parameter (p, 0, NULL);
         h = CreateFile (param, GENERIC_WRITE, 0, &sa, creationDisposition,
                         FILE_ATTRIBUTE_NORMAL, NULL);
         if (h == INVALID_HANDLE_VALUE) {
@@ -589,7 +637,7 @@ void WCMD_process_command (char *command)
               INVALID_SET_FILE_POINTER) {
           WCMD_print_error ();
         }
-        WINE_TRACE("Redirect %d to '%s' (%p)\n", handle, param, h);
+        WINE_TRACE("Redirect %d to '%s' (%p)\n", handle, wine_dbgstr_w(param), h);
       }
 
       old_stdhandles[handle] = GetStdHandle (idx_stdhandles[handle]);
@@ -603,7 +651,7 @@ void WCMD_process_command (char *command)
  * Strip leading whitespaces, and a '@' if supplied
  */
     whichcmd = WCMD_strtrim_leading_spaces(cmd);
-    WINE_TRACE("Command: '%s'\n", cmd);
+    WINE_TRACE("Command: '%s'\n", wine_dbgstr_w(cmd));
     if (whichcmd[0] == '@') whichcmd++;
 
 /*
@@ -712,7 +760,7 @@ void WCMD_process_command (char *command)
         WCMD_setshow_time ();
         break;
       case WCMD_TITLE:
-        if (strlen(&whichcmd[count]) > 0)
+        if (strlenW(&whichcmd[count]) > 0)
           WCMD_title(&whichcmd[count+1]);
         break;
       case WCMD_TYPE:
@@ -778,13 +826,13 @@ static void init_msvcrt_io_block(STARTUPINFO* st)
          * to change those std handles (this depends on the way wcmd sets
          * it's new input & output handles)
          */
-        size_t sz = max(sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * 3, st_p.cbReserved2);
+        size_t sz = max(sizeof(unsigned) + (sizeof(WCHAR) + sizeof(HANDLE)) * 3, st_p.cbReserved2);
         BYTE* ptr = HeapAlloc(GetProcessHeap(), 0, sz);
         if (ptr)
         {
             unsigned num = *(unsigned*)st_p.lpReserved2;
-            char* flags = (char*)(ptr + sizeof(unsigned));
-            HANDLE* handles = (HANDLE*)(flags + num * sizeof(char));
+            WCHAR* flags = (WCHAR*)(ptr + sizeof(unsigned));
+            HANDLE* handles = (HANDLE*)(flags + num * sizeof(WCHAR));
 
             memcpy(ptr, st_p.lpReserved2, st_p.cbReserved2);
             st->cbReserved2 = sz;
@@ -834,81 +882,90 @@ static void init_msvcrt_io_block(STARTUPINFO* st)
  *          findexecutable to acheive this which is left untouched.
  */
 
-void WCMD_run_program (char *command, int called) {
+void WCMD_run_program (WCHAR *command, int called) {
 
-  char  temp[MAX_PATH];
-  char  pathtosearch[MAXSTRING];
-  char *pathposn;
-  char  stemofsearch[MAX_PATH];
-  char *lastSlash;
-  char  pathext[MAXSTRING];
+  WCHAR  temp[MAX_PATH];
+  WCHAR  pathtosearch[MAXSTRING];
+  WCHAR *pathposn;
+  WCHAR  stemofsearch[MAX_PATH];
+  WCHAR *lastSlash;
+  WCHAR  pathext[MAXSTRING];
   BOOL  extensionsupplied = FALSE;
   BOOL  launched = FALSE;
   BOOL  status;
   BOOL  assumeInternal = FALSE;
   DWORD len;
-
+  const WCHAR envPath[] = {'P','A','T','H','\0'};
+  const WCHAR envPathExt[] = {'P','A','T','H','E','X','T','\0'};
+  const WCHAR delims[] = {'/','\\',':','\0'};
 
   WCMD_parse (command, quals, param1, param2);	/* Quick way to get the filename */
   if (!(*param1) && !(*param2))
     return;
 
   /* Calculate the search path and stem to search for */
-  if (strpbrk (param1, "/\\:") == NULL) {  /* No explicit path given, search path */
-    strcpy(pathtosearch,".;");
-    len = GetEnvironmentVariable ("PATH", &pathtosearch[2], sizeof(pathtosearch)-2);
-    if ((len == 0) || (len >= sizeof(pathtosearch) - 2)) {
-      lstrcpy (pathtosearch, ".");
+  if (strpbrkW (param1, delims) == NULL) {  /* No explicit path given, search path */
+    const WCHAR curDir[] = {'.',';','\0'};
+    strcpyW(pathtosearch, curDir);
+    len = GetEnvironmentVariable (envPath, &pathtosearch[2], (sizeof(pathtosearch)/sizeof(WCHAR))-2);
+    if ((len == 0) || (len >= (sizeof(pathtosearch)/sizeof(WCHAR)) - 2)) {
+      const WCHAR curDir[] = {'.','\0'};
+      strcpyW (pathtosearch, curDir);
     }
-    if (strchr(param1, '.') != NULL) extensionsupplied = TRUE;
-    strcpy(stemofsearch, param1);
+    if (strchrW(param1, '.') != NULL) extensionsupplied = TRUE;
+    strcpyW(stemofsearch, param1);
 
   } else {
 
     /* Convert eg. ..\fred to include a directory by removing file part */
-    GetFullPathName(param1, sizeof(pathtosearch), pathtosearch, NULL);
-    lastSlash = strrchr(pathtosearch, '\\');
-    if (lastSlash && strchr(lastSlash, '.') != NULL) extensionsupplied = TRUE;
+    GetFullPathName(param1, sizeof(pathtosearch)/sizeof(WCHAR), pathtosearch, NULL);
+    lastSlash = strrchrW(pathtosearch, '\\');
+    if (lastSlash && strchrW(lastSlash, '.') != NULL) extensionsupplied = TRUE;
     if (lastSlash) *lastSlash = 0x00;
-    strcpy(stemofsearch, lastSlash+1);
+    strcpyW(stemofsearch, lastSlash+1);
   }
 
   /* Now extract PATHEXT */
-  len = GetEnvironmentVariable ("PATHEXT", pathext, sizeof(pathext));
-  if ((len == 0) || (len >= sizeof(pathext))) {
-    lstrcpy (pathext, ".bat;.com;.cmd;.exe");
+  len = GetEnvironmentVariable (envPathExt, pathext, sizeof(pathext)/sizeof(WCHAR));
+  if ((len == 0) || (len >= (sizeof(pathext)/sizeof(WCHAR)))) {
+    const WCHAR dfltPathExt[] = {'.','b','a','t',';',
+                                 '.','c','o','m',';',
+                                 '.','c','m','d',';',
+                                 '.','e','x','e','\0'};
+    strcpyW (pathext, dfltPathExt);
   }
 
   /* Loop through the search path, dir by dir */
   pathposn = pathtosearch;
-  WINE_TRACE("Searching in '%s' for '%s'\n", pathtosearch, stemofsearch);
+  WINE_TRACE("Searching in '%s' for '%s'\n", wine_dbgstr_w(pathtosearch),
+             wine_dbgstr_w(stemofsearch));
   while (!launched && pathposn) {
 
-    char  thisDir[MAX_PATH] = "";
-    char *pos               = NULL;
+    WCHAR  thisDir[MAX_PATH] = {'\0'};
+    WCHAR *pos               = NULL;
     BOOL  found             = FALSE;
+    const WCHAR slashW[] = {'\\','\0'};
 
     /* Work on the first directory on the search path */
-    pos = strchr(pathposn, ';');
+    pos = strchrW(pathposn, ';');
     if (pos) {
-      strncpy(thisDir, pathposn, (pos-pathposn));
-      thisDir[(pos-pathposn)] = 0x00;
+      lstrcpynW(thisDir, pathposn, (pos-pathposn)+1); /* (lstrcpynW inserts null when truncating) */
       pathposn = pos+1;
 
     } else {
-      strcpy(thisDir, pathposn);
+      strcpyW(thisDir, pathposn);
       pathposn = NULL;
     }
 
     /* Since you can have eg. ..\.. on the path, need to expand
        to full information                                      */
-    strcpy(temp, thisDir);
+    strcpyW(temp, thisDir);
     GetFullPathName(temp, MAX_PATH, thisDir, NULL);
 
     /* 1. If extension supplied, see if that file exists */
-    strcat(thisDir, "\\");
-    strcat(thisDir, stemofsearch);
-    pos = &thisDir[strlen(thisDir)]; /* Pos = end of name */
+    strcatW(thisDir, slashW);
+    strcatW(thisDir, stemofsearch);
+    pos = &thisDir[strlenW(thisDir)]; /* Pos = end of name */
 
     /* 1. If extension supplied, see if that file exists */
     if (extensionsupplied) {
@@ -921,24 +978,24 @@ void WCMD_run_program (char *command, int called) {
     if (!found) {
       HANDLE          h;
       WIN32_FIND_DATA finddata;
+      const WCHAR allFiles[] = {'.','*','\0'};
 
-      strcat(thisDir,".*");
+      strcatW(thisDir,allFiles);
       h = FindFirstFile(thisDir, &finddata);
       FindClose(h);
       if (h != INVALID_HANDLE_VALUE) {
 
-        char *thisExt = pathext;
+        WCHAR *thisExt = pathext;
 
         /* 3. Yes - Try each path ext */
         while (thisExt) {
-          char *nextExt = strchr(thisExt, ';');
+          WCHAR *nextExt = strchrW(thisExt, ';');
 
           if (nextExt) {
-            strncpy(pos, thisExt, (nextExt-thisExt));
-            pos[(nextExt-thisExt)] = 0x00;
+            lstrcpynW(pos, thisExt, (nextExt-thisExt)+1); /* (lstrcpynW inserts null when truncating) */
             thisExt = nextExt+1;
           } else {
-            strcpy(pos, thisExt);
+            strcpyW(pos, thisExt);
             thisExt = NULL;
           }
 
@@ -959,7 +1016,7 @@ void WCMD_run_program (char *command, int called) {
         WINE_TRACE("ASSUMING INTERNAL\n");
         assumeInternal = TRUE;
     } else {
-        WINE_TRACE("Found as %s\n", thisDir);
+        WINE_TRACE("Found as %s\n", wine_dbgstr_w(thisDir));
     }
 
     /* Once found, launch it */
@@ -969,14 +1026,17 @@ void WCMD_run_program (char *command, int called) {
       SHFILEINFO psfi;
       DWORD console;
       HINSTANCE hinst;
-      char *ext = strrchr( thisDir, '.' );
+      WCHAR *ext = strrchrW( thisDir, '.' );
+      const WCHAR batExt[] = {'.','b','a','t','\0'};
+      const WCHAR cmdExt[] = {'.','c','m','d','\0'};
+
       launched = TRUE;
 
       /* Special case BAT and CMD */
-      if (ext && !strcasecmp(ext, ".bat")) {
+      if (ext && !strcmpiW(ext, batExt)) {
         WCMD_batch (thisDir, command, called, NULL, INVALID_HANDLE_VALUE);
         return;
-      } else if (ext && !strcasecmp(ext, ".cmd")) {
+      } else if (ext && !strcmpiW(ext, cmdExt)) {
         WCMD_batch (thisDir, command, called, NULL, INVALID_HANDLE_VALUE);
         return;
       } else {
@@ -999,7 +1059,7 @@ void WCMD_run_program (char *command, int called) {
                                 command, NULL, NULL, TRUE, 0, NULL, NULL, &st, &pe);
         if ((opt_c || opt_k) && !opt_s && !status
             && GetLastError()==ERROR_FILE_NOT_FOUND && command[0]=='\"') {
-          /* strip first and last quote characters and try again */
+          /* strip first and last quote WCHARacters and try again */
           WCMD_opt_s_strip_quotes(command);
           opt_s=1;
           WCMD_run_program(command, called);
@@ -1047,13 +1107,16 @@ void WCMD_run_program (char *command, int called) {
 void WCMD_show_prompt (void) {
 
   int status;
-  char out_string[MAX_PATH], curdir[MAX_PATH], prompt_string[MAX_PATH];
-  char *p, *q;
+  WCHAR out_string[MAX_PATH], curdir[MAX_PATH], prompt_string[MAX_PATH];
+  WCHAR *p, *q;
   DWORD len;
+  const WCHAR envPrompt[] = {'P','R','O','M','P','T','\0'};
 
-  len = GetEnvironmentVariable ("PROMPT", prompt_string, sizeof(prompt_string));
-  if ((len == 0) || (len >= sizeof(prompt_string))) {
-    lstrcpy (prompt_string, "$P$G");
+  len = GetEnvironmentVariable (envPrompt, prompt_string,
+                                sizeof(prompt_string)/sizeof(WCHAR));
+  if ((len == 0) || (len >= (sizeof(prompt_string)/sizeof(WCHAR)))) {
+    const WCHAR dfltPrompt[] = {'$','P','$','G','\0'};
+    strcpyW (prompt_string, dfltPrompt);
   }
   p = prompt_string;
   q = out_string;
@@ -1098,15 +1161,15 @@ void WCMD_show_prompt (void) {
 	  *q++ = '<';
 	  break;
 	case 'N':
-          status = GetCurrentDirectory (sizeof(curdir), curdir);
+          status = GetCurrentDirectory (sizeof(curdir)/sizeof(WCHAR), curdir);
 	  if (status) {
 	    *q++ = curdir[0];
 	  }
 	  break;
 	case 'P':
-          status = GetCurrentDirectory (sizeof(curdir), curdir);
+          status = GetCurrentDirectory (sizeof(curdir)/sizeof(WCHAR), curdir);
 	  if (status) {
-	    lstrcat (q, curdir);
+	    strcatW (q, curdir);
 	    while (*q) q++;
 	  }
 	  break;
@@ -1120,8 +1183,8 @@ void WCMD_show_prompt (void) {
 	  GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL, q, MAX_PATH);
 	  while (*q) q++;
 	  break;
-	case 'V':
-	  lstrcat (q, version_string);
+        case 'V':
+	  strcatW (q, version_string);
 	  while (*q) q++;
           break;
 	case '_':
@@ -1175,7 +1238,7 @@ void WCMD_print_error (void) {
  *	Parameters in quotes are handled.
  */
 
-void WCMD_parse (char *s, char *q, char *p1, char *p2) {
+void WCMD_parse (WCHAR *s, WCHAR *q, WCHAR *p1, WCHAR *p2) {
 
 int p = 0;
 
@@ -1222,12 +1285,47 @@ int p = 0;
 
 /*******************************************************************
  * WCMD_output_asis_len - send output to current standard output
- *        device without formatting eg. when message contains '%'
- *        of a supplied length.
+ *
+ * Output a formatted unicode string. Ideally this will go to the console
+ *  and hence required WriteConsoleW to output it, however if file i/o is
+ *  redirected, it needs to be WriteFile'd using OEM (not ANSI) format
  */
-static void WCMD_output_asis_len(const char *message, int len) {
-  DWORD count;
-  WriteFile (GetStdHandle(STD_OUTPUT_HANDLE), message, len, &count, NULL);
+static void WCMD_output_asis_len(const WCHAR *message, int len) {
+
+    DWORD   nOut= 0;
+    DWORD   res = 0;
+
+    /* If nothing to write, return (MORE does this sometimes) */
+    if (!len) return;
+
+    /* Try to write as unicode assuming it is to a console */
+    res = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
+                        message, len, &nOut, NULL);
+
+    /* If writing to console fails, assume its file
+       i/o so convert to OEM codepage and output                  */
+    if (!res) {
+      BOOL usedDefaultChar = FALSE;
+      DWORD convertedChars;
+
+      /*
+       * Allocate buffer to use when writing to file. (Not freed, as one off)
+       */
+      if (!output_bufA) output_bufA = HeapAlloc(GetProcessHeap(), 0,
+                                                MAX_WRITECONSOLE_SIZE);
+      if (!output_bufA) {
+        WINE_FIXME("Out of memory - could not allocate ansi 64K buffer\n");
+        return;
+      }
+
+      /* Convert to OEM, then output */
+      convertedChars = WideCharToMultiByte(GetConsoleOutputCP(), 0, message,
+                          len, output_bufA, MAX_WRITECONSOLE_SIZE,
+                          "?", &usedDefaultChar);
+      WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), output_bufA, convertedChars,
+                &nOut, FALSE);
+    }
+    return;
 }
 
 /*******************************************************************
@@ -1235,38 +1333,45 @@ static void WCMD_output_asis_len(const char *message, int len) {
  *
  */
 
-void WCMD_output (const char *format, ...) {
+void WCMD_output (const WCHAR *format, ...) {
 
   va_list ap;
-  char string[1024];
+  WCHAR string[1024];
   int ret;
 
   va_start(ap,format);
-  ret = vsnprintf (string, sizeof( string), format, ap);
-  va_end(ap);
-  if( ret >= sizeof( string)) {
+  //ret = vsnprintfW (string, sizeof(string)/sizeof(WCHAR), format, ap);
+  ret = wvsprintf (string, format, ap);
+  if( ret >= (sizeof(string)/sizeof(WCHAR))) {
        WINE_ERR("Output truncated in WCMD_output\n" );
-       ret = sizeof(string) - 1;
+       ret = (sizeof(string)/sizeof(WCHAR)) - 1;
        string[ret] = '\0';
   }
+  va_end(ap);
   WCMD_output_asis_len(string, ret);
 }
 
 
 static int line_count;
 static int max_height;
+static int max_width;
 static BOOL paged_mode;
+static int numChars;
 
-void WCMD_enter_paged_mode(const char *msg)
+void WCMD_enter_paged_mode(const WCHAR *msg)
 {
   CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
 
-  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo))
+  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) {
     max_height = consoleInfo.dwSize.Y;
-  else
+    max_width  = consoleInfo.dwSize.X;
+  } else {
     max_height = 25;
+    max_width  = 80;
+  }
   paged_mode = TRUE;
   line_count = 0;
+  numChars   = 0;
   pagedMessage = (msg==NULL)? anykey : msg;
 }
 
@@ -1281,28 +1386,36 @@ void WCMD_leave_paged_mode(void)
  *        without formatting eg. when message contains '%'
  */
 
-void WCMD_output_asis (const char *message) {
+void WCMD_output_asis (const WCHAR *message) {
   DWORD count;
-  char* ptr;
-  char string[1024];
+  const WCHAR* ptr;
+  WCHAR string[1024];
 
   if (paged_mode) {
     do {
-      if ((ptr = strchr(message, '\n')) != NULL) ptr++;
-      WCMD_output_asis_len(message, (ptr) ? ptr - message : lstrlen(message));
+      ptr = message;
+      while (*ptr && *ptr!='\n' && (numChars < max_width)) {
+        numChars++;
+        ptr++;
+      };
+      if (*ptr == '\n') ptr++;
+      WCMD_output_asis_len(message, (ptr) ? ptr - message : strlenW(message));
       if (ptr) {
+        numChars = 0;
         if (++line_count >= max_height - 1) {
-          line_count = 1;
-          WCMD_output_asis_len(pagedMessage, lstrlen(pagedMessage));
-          ReadFile (GetStdHandle(STD_INPUT_HANDLE), string, sizeof(string), &count, NULL);
+          line_count = 0;
+          WCMD_output_asis_len(pagedMessage, strlenW(pagedMessage));
+          WCMD_ReadFile (GetStdHandle(STD_INPUT_HANDLE), string,
+                         sizeof(string)/sizeof(WCHAR), &count, NULL);
         }
       }
-    } while ((message = ptr) != NULL);
+    } while (((message = ptr) != NULL) && (*ptr));
   } else {
     WCMD_output_asis_len(message, lstrlen(message));
   }
 }
 
+
 /***************************************************************************
  * WCMD_strtrim_leading_spaces
  *
@@ -1310,9 +1423,9 @@ void WCMD_output_asis (const char *message) {
  *	non-space character. Does not modify the input string
  */
 
-char *WCMD_strtrim_leading_spaces (char *string) {
+WCHAR *WCMD_strtrim_leading_spaces (WCHAR *string) {
 
-  char *ptr;
+  WCHAR *ptr;
 
   ptr = string;
   while (*ptr == ' ') ptr++;
@@ -1323,14 +1436,14 @@ char *WCMD_strtrim_leading_spaces (char *string) {
  * WCMD_strtrim_trailing_spaces
  *
  *	Remove trailing spaces from a string. This routine modifies the input
- *	string by placing a null after the last non-space character
+ *	string by placing a null after the last non-space WCHARacter
  */
 
-void WCMD_strtrim_trailing_spaces (char *string) {
+void WCMD_strtrim_trailing_spaces (WCHAR *string) {
 
-  char *ptr;
+  WCHAR *ptr;
 
-  ptr = string + lstrlen (string) - 1;
+  ptr = string + strlenW (string) - 1;
   while ((*ptr == ' ') && (ptr >= string)) {
     *ptr = '\0';
     ptr--;
@@ -1340,11 +1453,11 @@ void WCMD_strtrim_trailing_spaces (char *string) {
 /*************************************************************************
  * WCMD_opt_s_strip_quotes
  *
- *	Remove first and last quote characters, preserving all other text
+ *	Remove first and last quote WCHARacters, preserving all other text
  */
 
-void WCMD_opt_s_strip_quotes(char *cmd) {
-  char *src = cmd + 1, *dest = cmd, *lastq = NULL;
+void WCMD_opt_s_strip_quotes(WCHAR *cmd) {
+  WCHAR *src = cmd + 1, *dest = cmd, *lastq = NULL;
   while((*dest=*src) != '\0') {
       if (*src=='\"')
           lastq=dest;
@@ -1363,28 +1476,33 @@ void WCMD_opt_s_strip_quotes(char *cmd) {
  *	Handle pipes within a command - the DOS way using temporary files.
  */
 
-void WCMD_pipe (char *command) {
+void WCMD_pipe (WCHAR *command) {
+
+  WCHAR *p;
+  WCHAR temp_path[MAX_PATH], temp_file[MAX_PATH], temp_file2[MAX_PATH], temp_cmd[1024];
+  const WCHAR redirOut[] = {'%','s',' ','>',' ','%','s','\0'};
+  const WCHAR redirIn[]  = {'%','s',' ','<',' ','%','s','\0'};
+  const WCHAR redirBoth[]= {'%','s',' ','<',' ','%','s',' ','>','%','s','\0'};
+  const WCHAR cmdW[]     = {'C','M','D','\0'};
 
-  char *p;
-  char temp_path[MAX_PATH], temp_file[MAX_PATH], temp_file2[MAX_PATH], temp_cmd[1024];
 
-  GetTempPath (sizeof(temp_path), temp_path);
-  GetTempFileName (temp_path, "CMD", 0, temp_file);
-  p = strchr(command, '|');
+  GetTempPath (sizeof(temp_path)/sizeof(WCHAR), temp_path);
+  GetTempFileName (temp_path, cmdW, 0, temp_file);
+  p = strchrW(command, '|');
   *p++ = '\0';
-  wsprintf (temp_cmd, "%s > %s", command, temp_file);
+  wsprintf (temp_cmd, redirOut, command, temp_file);
   WCMD_process_command (temp_cmd);
   command = p;
-  while ((p = strchr(command, '|'))) {
+  while ((p = strchrW(command, '|'))) {
     *p++ = '\0';
-    GetTempFileName (temp_path, "CMD", 0, temp_file2);
-    wsprintf (temp_cmd, "%s < %s > %s", command, temp_file, temp_file2);
+    GetTempFileName (temp_path, cmdW, 0, temp_file2);
+    wsprintf (temp_cmd, redirBoth, command, temp_file, temp_file2);
     WCMD_process_command (temp_cmd);
     DeleteFile (temp_file);
-    lstrcpy (temp_file, temp_file2);
+    strcpyW (temp_file, temp_file2);
     command = p;
   }
-  wsprintf (temp_cmd, "%s < %s", command, temp_file);
+  wsprintf (temp_cmd, redirIn, command, temp_file);
   WCMD_process_command (temp_cmd);
   DeleteFile (temp_file);
 }
@@ -1392,85 +1510,99 @@ void WCMD_pipe (char *command) {
 /*************************************************************************
  * WCMD_expand_envvar
  *
- *	Expands environment variables, allowing for character substitution
+ *	Expands environment variables, allowing for WCHARacter substitution
  */
-static char *WCMD_expand_envvar(char *start) {
-    char *endOfVar = NULL, *s;
-    char *colonpos = NULL;
-    char thisVar[MAXSTRING];
-    char thisVarContents[MAXSTRING];
-    char savedchar = 0x00;
+static WCHAR *WCMD_expand_envvar(WCHAR *start) {
+    WCHAR *endOfVar = NULL, *s;
+    WCHAR *colonpos = NULL;
+    WCHAR thisVar[MAXSTRING];
+    WCHAR thisVarContents[MAXSTRING];
+    WCHAR savedWCHAR = 0x00;
     int len;
 
+    const WCHAR ErrorLvl[]  = {'E','R','R','O','R','L','E','V','E','L','\0'};
+    const WCHAR ErrorLvlP[] = {'%','E','R','R','O','R','L','E','V','E','L','%','\0'};
+    const WCHAR Date[]      = {'D','A','T','E','\0'};
+    const WCHAR DateP[]     = {'%','D','A','T','E','%','\0'};
+    const WCHAR Time[]      = {'T','I','M','E','\0'};
+    const WCHAR TimeP[]     = {'%','T','I','M','E','%','\0'};
+    const WCHAR Cd[]        = {'C','D','\0'};
+    const WCHAR CdP[]       = {'%','C','D','%','\0'};
+    const WCHAR Random[]    = {'R','A','N','D','O','M','\0'};
+    const WCHAR RandomP[]   = {'%','R','A','N','D','O','M','%','\0'};
+
     /* Find the end of the environment variable, and extract name */
-    endOfVar = strchr(start+1, '%');
+    endOfVar = strchrW(start+1, '%');
     if (endOfVar == NULL) {
-      /* FIXME: Some special conditions here depending opn whether
+      /* FIXME: Some special conditions here depending on whether
          in batch, complex or not, and whether env var exists or not! */
       return start+1;
     }
-    strncpy(thisVar, start, (endOfVar - start)+1);
-    thisVar[(endOfVar - start)+1] = 0x00;
-    colonpos = strchr(thisVar+1, ':');
+    lstrcpynW(thisVar, start, (endOfVar - start)+2); /* (lstrcpynW inserts null when truncating) */
+    colonpos = strchrW(thisVar+1, ':');
 
     /* If there's complex substitution, just need %var% for now
        to get the expanded data to play with                    */
     if (colonpos) {
         *colonpos = '%';
-        savedchar = *(colonpos+1);
+        savedWCHAR = *(colonpos+1);
         *(colonpos+1) = 0x00;
     }
 
+    WINE_TRACE("Retrieving contents of %s\n", wine_dbgstr_w(thisVar));
+
     /* Expand to contents, if unchanged, return */
     /* Handle DATE, TIME, ERRORLEVEL and CD replacements allowing */
     /* override if existing env var called that name              */
     if ((CompareString (LOCALE_USER_DEFAULT,
                         NORM_IGNORECASE | SORT_STRINGSORT,
-                        thisVar, 12, "%ERRORLEVEL%", -1) == 2) &&
-                (GetEnvironmentVariable("ERRORLEVEL", thisVarContents, 1) == 0) &&
+                        thisVar, 12, ErrorLvlP, -1) == 2) &&
+                (GetEnvironmentVariable(ErrorLvl, thisVarContents, 1) == 0) &&
                 (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) {
-      sprintf(thisVarContents, "%d", errorlevel);
-      len = strlen(thisVarContents);
+      const WCHAR fmt[] = {'%','d','\0'};
+      wsprintf(thisVarContents, fmt, errorlevel);
+      len = strlenW(thisVarContents);
 
     } else if ((CompareString (LOCALE_USER_DEFAULT,
                                NORM_IGNORECASE | SORT_STRINGSORT,
-                               thisVar, 6, "%DATE%", -1) == 2) &&
-                (GetEnvironmentVariable("DATE", thisVarContents, 1) == 0) &&
+                               thisVar, 6, DateP, -1) == 2) &&
+                (GetEnvironmentVariable(Date, thisVarContents, 1) == 0) &&
                 (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) {
 
       GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL,
                     NULL, thisVarContents, MAXSTRING);
-      len = strlen(thisVarContents);
+      len = strlenW(thisVarContents);
 
     } else if ((CompareString (LOCALE_USER_DEFAULT,
                                NORM_IGNORECASE | SORT_STRINGSORT,
-                               thisVar, 6, "%TIME%", -1) == 2) &&
-                (GetEnvironmentVariable("TIME", thisVarContents, 1) == 0) &&
+                               thisVar, 6, TimeP, -1) == 2) &&
+                (GetEnvironmentVariable(Time, thisVarContents, 1) == 0) &&
                 (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) {
       GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, NULL,
                         NULL, thisVarContents, MAXSTRING);
-      len = strlen(thisVarContents);
+      len = strlenW(thisVarContents);
 
     } else if ((CompareString (LOCALE_USER_DEFAULT,
                                NORM_IGNORECASE | SORT_STRINGSORT,
-                               thisVar, 4, "%CD%", -1) == 2) &&
-                (GetEnvironmentVariable("CD", thisVarContents, 1) == 0) &&
+                               thisVar, 4, CdP, -1) == 2) &&
+                (GetEnvironmentVariable(Cd, thisVarContents, 1) == 0) &&
                 (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) {
       GetCurrentDirectory (MAXSTRING, thisVarContents);
-      len = strlen(thisVarContents);
+      len = strlenW(thisVarContents);
 
     } else if ((CompareString (LOCALE_USER_DEFAULT,
                                NORM_IGNORECASE | SORT_STRINGSORT,
-                               thisVar, 8, "%RANDOM%", -1) == 2) &&
-                (GetEnvironmentVariable("RANDOM", thisVarContents, 1) == 0) &&
+                               thisVar, 8, RandomP, -1) == 2) &&
+                (GetEnvironmentVariable(Random, thisVarContents, 1) == 0) &&
                 (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) {
-      sprintf(thisVarContents, "%d", rand() % 32768);
-      len = strlen(thisVarContents);
+      const WCHAR fmt[] = {'%','d','\0'};
+      wsprintf(thisVarContents, fmt, rand() % 32768);
+      len = strlenW(thisVarContents);
 
     } else {
 
       len = ExpandEnvironmentStrings(thisVar, thisVarContents,
-                                      sizeof(thisVarContents));
+                               sizeof(thisVarContents)/sizeof(WCHAR));
     }
 
     if (len == 0)
@@ -1480,33 +1612,33 @@ static char *WCMD_expand_envvar(char *start) {
          note syntax %garbage:1,3% results in anything after the ':'
          except the %
        From the command line, you just get back what you entered      */
-    if (lstrcmpi(thisVar, thisVarContents) == 0) {
+    if (lstrcmpiW(thisVar, thisVarContents) == 0) {
 
       /* Restore the complex part after the compare */
       if (colonpos) {
         *colonpos = ':';
-        *(colonpos+1) = savedchar;
+        *(colonpos+1) = savedWCHAR;
       }
 
-      s = strdup (endOfVar + 1);
+      s = WCMD_strdupW(endOfVar + 1);
 
       /* Command line - just ignore this */
       if (context == NULL) return endOfVar+1;
 
       /* Batch - replace unknown env var with nothing */
       if (colonpos == NULL) {
-        strcpy (start, s);
+        strcpyW (start, s);
 
       } else {
-        len = strlen(thisVar);
+        len = strlenW(thisVar);
         thisVar[len-1] = 0x00;
         /* If %:...% supplied, : is retained */
         if (colonpos == thisVar+1) {
-          strcpy (start, colonpos);
+          strcpyW (start, colonpos);
         } else {
-          strcpy (start, colonpos+1);
+          strcpyW (start, colonpos+1);
         }
-        strcat (start, s);
+        strcatW (start, s);
       }
       free (s);
       return start;
@@ -1516,38 +1648,38 @@ static char *WCMD_expand_envvar(char *start) {
     /* See if we need to do complex substitution (any ':'s), if not
        then our work here is done                                  */
     if (colonpos == NULL) {
-      s = strdup (endOfVar + 1);
-      strcpy (start, thisVarContents);
-      strcat (start, s);
+      s = WCMD_strdupW(endOfVar + 1);
+      strcpyW (start, thisVarContents);
+      strcatW (start, s);
       free(s);
       return start;
     }
 
     /* Restore complex bit */
     *colonpos = ':';
-    *(colonpos+1) = savedchar;
+    *(colonpos+1) = savedWCHAR;
 
     /*
         Handle complex substitutions:
            xxx=yyy    (replace xxx with yyy)
            *xxx=yyy   (replace up to and including xxx with yyy)
-           ~x         (from x chars in)
-           ~-x        (from x chars from the end)
-           ~x,y       (from x chars in for y characters)
-           ~x,-y      (from x chars in until y characters from the end)
+           ~x         (from x WCHARs in)
+           ~-x        (from x WCHARs from the end)
+           ~x,y       (from x WCHARs in for y WCHARacters)
+           ~x,-y      (from x WCHARs in until y WCHARacters from the end)
      */
 
     /* ~ is substring manipulation */
-    if (savedchar == '~') {
+    if (savedWCHAR == '~') {
 
-      int   substrposition, substrlength = 0;
-      char *commapos = strchr(colonpos+2, ',');
-      char *startCopy;
+      int   substrposition, substrlenWgth = 0;
+      WCHAR *commapos = strchrW(colonpos+2, ',');
+      WCHAR *startCopy;
 
-      substrposition = atol(colonpos+2);
-      if (commapos) substrlength = atol(commapos+1);
+      substrposition = atolW(colonpos+2);
+      if (commapos) substrlenWgth = atolW(commapos+1);
 
-      s = strdup (endOfVar + 1);
+      s = WCMD_strdupW(endOfVar + 1);
 
       /* Check bounds */
       if (substrposition >= 0) {
@@ -1557,81 +1689,79 @@ static char *WCMD_expand_envvar(char *start) {
       }
 
       if (commapos == NULL) {
-        strcpy (start, startCopy); /* Copy the lot */
-      } else if (substrlength < 0) {
+        strcpyW (start, startCopy); /* Copy the lot */
+      } else if (substrlenWgth < 0) {
 
-        int copybytes = (len+substrlength-1)-(startCopy-thisVarContents);
+        int copybytes = (len+substrlenWgth-1)-(startCopy-thisVarContents);
         if (copybytes > len) copybytes = len;
         else if (copybytes < 0) copybytes = 0;
-        strncpy (start, startCopy, copybytes); /* Copy the lot */
-        start[copybytes] = 0x00;
+        lstrcpynW (start, startCopy, copybytes+1); /* Copy the lot (lstrcpynW inserts null when truncating) */
       } else {
-        strncpy (start, startCopy, substrlength); /* Copy the lot */
-        start[substrlength] = 0x00;
+        lstrcpynW (start, startCopy, substrlenWgth+1); /* Copy the lot (lstrcpynW inserts null when truncating) */
+        start[substrlenWgth] = 0x00;
       }
 
-      strcat (start, s);
+      strcatW (start, s);
       free(s);
       return start;
 
     /* search and replace manipulation */
     } else {
-      char *equalspos = strstr(colonpos, "=");
-      char *replacewith = equalspos+1;
-      char *found       = NULL;
-      char *searchIn;
-      char *searchFor;
+      WCHAR *equalspos = strstrW(colonpos, equalsW);
+      WCHAR *replacewith = equalspos+1;
+      WCHAR *found       = NULL;
+      WCHAR *searchIn;
+      WCHAR *searchFor;
 
-      s = strdup (endOfVar + 1);
+      s = WCMD_strdupW(endOfVar + 1);
       if (equalspos == NULL) return start+1;
 
       /* Null terminate both strings */
-      thisVar[strlen(thisVar)-1] = 0x00;
+      thisVar[strlenW(thisVar)-1] = 0x00;
       *equalspos = 0x00;
 
       /* Since we need to be case insensitive, copy the 2 buffers */
-      searchIn  = strdup(thisVarContents);
-      CharUpperBuff(searchIn, strlen(thisVarContents));
-      searchFor = strdup(colonpos+1);
-      CharUpperBuff(searchFor, strlen(colonpos+1));
+      searchIn  = WCMD_strdupW(thisVarContents);
+      CharUpperBuff(searchIn, strlenW(thisVarContents));
+      searchFor = WCMD_strdupW(colonpos+1);
+      CharUpperBuff(searchFor, strlenW(colonpos+1));
 
 
       /* Handle wildcard case */
       if (*(colonpos+1) == '*') {
         /* Search for string to replace */
-        found = strstr(searchIn, searchFor+1);
+        found = strstrW(searchIn, searchFor+1);
 
         if (found) {
           /* Do replacement */
-          strcpy(start, replacewith);
-          strcat(start, thisVarContents + (found-searchIn) + strlen(searchFor+1));
-          strcat(start, s);
+          strcpyW(start, replacewith);
+          strcatW(start, thisVarContents + (found-searchIn) + strlenW(searchFor+1));
+          strcatW(start, s);
           free(s);
         } else {
           /* Copy as it */
-          strcpy(start, thisVarContents);
-          strcat(start, s);
+          strcpyW(start, thisVarContents);
+          strcatW(start, s);
         }
 
       } else {
         /* Loop replacing all instances */
-        char *lastFound = searchIn;
-        char *outputposn = start;
+        WCHAR *lastFound = searchIn;
+        WCHAR *outputposn = start;
 
         *start = 0x00;
-        while ((found = strstr(lastFound, searchFor))) {
-            strncpy(outputposn,
+        while ((found = strstrW(lastFound, searchFor))) {
+            lstrcpynW(outputposn,
                     thisVarContents + (lastFound-searchIn),
-                    (found - lastFound));
+                    (found - lastFound)+1);
             outputposn  = outputposn + (found - lastFound);
-            *outputposn = 0x00;
-            strcat(outputposn, replacewith);
-            outputposn = outputposn + strlen(replacewith);
-            lastFound = found + strlen(searchFor);
+            strcatW(outputposn, replacewith);
+            outputposn = outputposn + strlenW(replacewith);
+            lastFound = found + strlenW(searchFor);
         }
-        strcat(outputposn,
+        strcatW(outputposn,
                 thisVarContents + (lastFound-searchIn));
-        strcat(outputposn, s);
+        strcatW(outputposn, s);
       }
       free(searchIn);
       free(searchFor);
@@ -1645,13 +1775,66 @@ static char *WCMD_expand_envvar(char *start) {
  *    Load a string from the resource file, handling any error
  *    Returns string retrieved from resource file
  */
-char *WCMD_LoadMessage(UINT id) {
-    static char msg[2048];
-    const char failedMsg[]  = "Failed!";
+WCHAR *WCMD_LoadMessage(UINT id) {
+    static WCHAR msg[2048];
+    const WCHAR failedMsg[]  = {'F','a','i','l','e','d','!','\0'};
 
-    if (!LoadString(GetModuleHandle(NULL), id, msg, sizeof(msg))) {
+    if (!LoadString(GetModuleHandle(NULL), id, msg, sizeof(msg)/sizeof(WCHAR))) {
        WINE_FIXME("LoadString failed with %d\n", GetLastError());
-       lstrcpy(msg, failedMsg);
+       strcpyW(msg, failedMsg);
     }
     return msg;
 }
+
+/*************************************************************************
+ * WCMD_strdupW
+ *    A wide version of strdup as its missing from unicode.h
+ */
+WCHAR *WCMD_strdupW(WCHAR *input) {
+   int len=strlenW(input)+1;
+   /* Note: Use malloc not HeapAlloc to emulate strdup */
+   WCHAR *result = malloc(len * sizeof(WCHAR));
+   memcpy(result, input, len * sizeof(WCHAR));
+   result[len-1] = 0x00;
+   return result;
+}
+
+/***************************************************************************
+ * WCMD_Readfile
+ *
+ *	Read characters in from a console/file, returning result in Unicode
+ *      with signature identical to ReadFile
+ */
+BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars,
+                          LPDWORD charsRead, const LPOVERLAPPED unused) {
+
+    BOOL   res;
+
+    /* Try to read from console as Unicode */
+    res = ReadConsoleW(hIn, intoBuf, maxChars, charsRead, NULL);
+
+    /* If reading from console has failed we assume its file
+       i/o so read in and convert from OEM codepage               */
+    if (!res) {
+
+        DWORD numRead;
+        /*
+         * Allocate buffer to use when reading from file. Not freed
+         */
+        if (!output_bufA) output_bufA = HeapAlloc(GetProcessHeap(), 0,
+                                                  MAX_WRITECONSOLE_SIZE);
+        if (!output_bufA) {
+          WINE_FIXME("Out of memory - could not allocate ansi 64K buffer\n");
+          return 0;
+        }
+
+        /* Read from file (assume OEM codepage) */
+        res = ReadFile(hIn, output_bufA, maxChars, &numRead, unused);
+
+        /* Convert from OEM */
+        *charsRead = MultiByteToWideChar(GetConsoleCP(), 0, output_bufA, numRead,
+                         intoBuf, maxChars);
+
+    }
+    return res;
+}
-- 
1.5.0




More information about the wine-patches mailing list