Commit b8aa5fc5 authored by Jason Edmeades's avatar Jason Edmeades Committed by Alexandre Julliard

cmd.exe: Convert cmd to Unicode.

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