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