cmd.exe: Convert cmd to Unicode.
diff --git a/programs/cmd/Cs.rc b/programs/cmd/Cs.rc index 82bf49b..302659f 100644 --- a/programs/cmd/Cs.rc +++ b/programs/cmd/Cs.rc
@@ -263,4 +263,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/De.rc b/programs/cmd/De.rc index 7f02f6a..55799ea 100644 --- a/programs/cmd/De.rc +++ b/programs/cmd/De.rc
@@ -287,4 +287,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/En.rc b/programs/cmd/En.rc index 132938a..6f384ca 100644 --- a/programs/cmd/En.rc +++ b/programs/cmd/En.rc
@@ -267,4 +267,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Es.rc b/programs/cmd/Es.rc index 7363f94..02bd865 100644 --- a/programs/cmd/Es.rc +++ b/programs/cmd/Es.rc
@@ -284,4 +284,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Fr.rc b/programs/cmd/Fr.rc index 78b39de..0e3dcc7 100644 --- a/programs/cmd/Fr.rc +++ b/programs/cmd/Fr.rc
@@ -257,4 +257,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Ja.rc b/programs/cmd/Ja.rc index 5cbd119..b09715a 100644 --- a/programs/cmd/Ja.rc +++ b/programs/cmd/Ja.rc
@@ -261,4 +261,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Ko.rc b/programs/cmd/Ko.rc index 43395b9..fd568d2 100644 --- a/programs/cmd/Ko.rc +++ b/programs/cmd/Ko.rc
@@ -259,4 +259,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Makefile.in b/programs/cmd/Makefile.in index 3a81838..c383344 100644 --- a/programs/cmd/Makefile.in +++ b/programs/cmd/Makefile.in
@@ -4,6 +4,7 @@ VPATH = @srcdir@ MODULE = cmd.exe APPMODE = -mconsole +EXTRADEFS = -DUNICODE IMPORTS = shell32 user32 advapi32 kernel32 C_SRCS = \
diff --git a/programs/cmd/Nl.rc b/programs/cmd/Nl.rc index 5a12123..b06651a 100644 --- a/programs/cmd/Nl.rc +++ b/programs/cmd/Nl.rc
@@ -260,4 +260,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/No.rc b/programs/cmd/No.rc index e4e7c5c..571cc47 100644 --- a/programs/cmd/No.rc +++ b/programs/cmd/No.rc
@@ -265,4 +265,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Pl.rc b/programs/cmd/Pl.rc index 67c659c..6d56af1 100644 --- a/programs/cmd/Pl.rc +++ b/programs/cmd/Pl.rc
@@ -262,4 +262,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Pt.rc b/programs/cmd/Pt.rc index 17090dd..808bd11 100644 --- a/programs/cmd/Pt.rc +++ b/programs/cmd/Pt.rc
@@ -470,4 +470,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Ru.rc b/programs/cmd/Ru.rc index d3860c4..852f9ff 100644 --- a/programs/cmd/Ru.rc +++ b/programs/cmd/Ru.rc
@@ -273,4 +273,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Si.rc b/programs/cmd/Si.rc index 8060fad..e2243f5 100644 --- a/programs/cmd/Si.rc +++ b/programs/cmd/Si.rc
@@ -259,4 +259,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/Tr.rc b/programs/cmd/Tr.rc index 69e707e..e14c2a7 100644 --- a/programs/cmd/Tr.rc +++ b/programs/cmd/Tr.rc
@@ -261,4 +261,8 @@ WCMD_ARGERR, "Parameter error\n" WCMD_VOLUMEDETAIL, "Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n" WCMD_VOLUMEPROMPT, "Volume label (11 characters, ENTER for none)?" + WCMD_NOPATH, "PATH not found\n" + WCMD_ANYKEY,"Press Return key to continue: " + WCMD_CONSTITLE,"Wine Command Prompt" + WCMD_VERSION,"CMD Version %s\n\n" }
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 9824fe5..c301bcc 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c
@@ -21,7 +21,7 @@ #include "wcmd.h" extern int echo_mode; -extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; +extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; extern BATCH_CONTEXT *context; extern DWORD errorlevel; @@ -41,30 +41,31 @@ * 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 @@ /* If processing a call :label, 'goto' the label in question */ if (startLabel) { - strcpy(param1, startLabel); + strcpyW(param1, startLabel); WCMD_goto(); } @@ -105,7 +106,7 @@ */ 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 @@ * 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 @@ * 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 @@ * 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 @@ * 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 @@ 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 @@ /* 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 @@ /* 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 @@ /* 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 @@ 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 @@ /* 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 @@ * If there is a leading ':', calls within this batch program * otherwise launches another program. */ -void WCMD_call (char *command) { +void WCMD_call (WCHAR *command) { /* Run other program if no leading ':' */ if (*command != ':') { WCMD_run_program(command, 1); } else { - char gotoLabel[MAX_PATH]; + WCHAR gotoLabel[MAX_PATH]; - strcpy(gotoLabel, param1); + strcpyW(gotoLabel, param1); if (context) {
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 5c6510f..b73e318 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c
@@ -40,19 +40,29 @@ WINE_DEFAULT_DEBUG_CHANNEL(cmd); -void WCMD_execute (char *orig_command, char *parameter, char *substitution); +void WCMD_execute (WCHAR *orig_command, WCHAR *parameter, WCHAR *substitution); struct env_stack *saved_environment; struct env_stack *pushd_directories; extern HINSTANCE hinst; -extern char *inbuilt[]; +extern WCHAR *inbuilt[]; extern int echo_mode, verify_mode, defaultColor; -extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; +extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; extern BATCH_CONTEXT *context; extern DWORD errorlevel; - +static const WCHAR dotW[] = {'.','\0'}; +static const WCHAR dotdotW[] = {'.','.','\0'}; +static const WCHAR slashW[] = {'\\','\0'}; +static const WCHAR starW[] = {'*','\0'}; +static const WCHAR equalW[] = {'=','\0'}; +static const WCHAR fslashW[] = {'/','\0'}; +static const WCHAR onW[] = {'O','N','\0'}; +static const WCHAR offW[] = {'O','F','F','\0'}; +static const WCHAR parmY[] = {'/','Y','\0'}; +static const WCHAR parmNoY[] = {'/','-','Y','\0'}; +static const WCHAR nullW[] = {'\0'}; /**************************************************************************** * WCMD_clear_screen @@ -105,55 +115,56 @@ 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 @@ * 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 @@ 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 @@ * 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 @@ } /* 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 @@ } 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 @@ 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 @@ /* 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 @@ } /* 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 @@ 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 @@ 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 @@ * 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 @@ } 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 @@ * 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 @@ 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 @@ * 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 @@ * 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_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 @@ 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 @@ * 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 @@ } /* 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 @@ * 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; + 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 (!lstrcmpi (param1, "not")) { + 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 @@ return; } if (test != negate) { - command = strdup (command); + command = WCMD_strdupW(command); WCMD_process_command (command); free (command); } @@ -821,12 +853,12 @@ 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 @@ /* 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 @@ 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_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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ } /* 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 @@ } /* 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 @@ 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 @@ 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 @@ * 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 @@ } /***************************************************************************** - * 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ *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 @@ } /* 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 @@ /* 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 @@ /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_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 @@ 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 @@ * 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 @@ * 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 @@ /* 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 @@ } *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 @@ * 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_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_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 @@ * 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 @@ * * Set the console title */ -void WCMD_title (char *command) { +void WCMD_title (WCHAR *command) { SetConsoleTitle(command); } @@ -1742,10 +1787,10 @@ * 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 @@ /* 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 @@ 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 @@ * 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ * 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 @@ 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 @@ 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 @@ * 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 @@ * 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 @@ /* 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 @@ 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 @@ /* 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ if (param1[0] == 0x00) { color = defaultColor; } else { - color = strtoul(param1, NULL, 16); + color = strtoulW(param1, NULL, 16); } /* Fail if fg == bg color */
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c index 49c2c1a..e9c413a 100644 --- a/programs/cmd/directory.c +++ b/programs/cmd/directory.c
@@ -33,13 +33,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(cmd); int WCMD_dir_sort (const void *a, const void *b); -char * WCMD_filesize64 (ULONGLONG free); -char * WCMD_strrev (char *buff); -static void WCMD_getfileowner(char *filename, char *owner, int ownerlen); -static void WCMD_dir_trailer(char drive); +WCHAR * WCMD_filesize64 (ULONGLONG free); +WCHAR * WCMD_strrev (WCHAR *buff); +static void WCMD_getfileowner(WCHAR *filename, WCHAR *owner, int ownerlen); +static void WCMD_dir_trailer(WCHAR drive); extern int echo_mode; -extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; +extern WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; extern DWORD errorlevel; typedef enum _DISPLAYTIME @@ -67,6 +67,12 @@ static BOOL 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 @@ * */ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ } } } 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ } /* 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 @@ 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 @@ /* /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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /***************************************************************************** * 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 @@ /***************************************************************************** * 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 @@ /* 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 @@ /* 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 @@ /***************************************************************************** * 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 @@ /* 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 @@ * * 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)); } } }
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index ab13595..9fe729d 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h
@@ -28,71 +28,74 @@ #include <ctype.h> #include <wine/unicode.h> -void WCMD_assoc (char *, BOOL); -void WCMD_batch (char *, char *, int, char *, HANDLE); -void WCMD_call (char *command); +void WCMD_assoc (WCHAR *, BOOL); +void WCMD_batch (WCHAR *, WCHAR *, int, WCHAR *, HANDLE); +void WCMD_call (WCHAR *command); void WCMD_change_tty (void); void WCMD_clear_screen (void); void WCMD_color (void); void WCMD_copy (void); void WCMD_create_dir (void); -BOOL WCMD_delete (char *, BOOL); -void WCMD_directory (char *); -void WCMD_echo (const char *); +BOOL WCMD_delete (WCHAR *, BOOL); +void WCMD_directory (WCHAR *); +void WCMD_echo (const WCHAR *); void WCMD_endlocal (void); -void WCMD_enter_paged_mode(const char *); +void WCMD_enter_paged_mode(const WCHAR *); void WCMD_exit (void); -void WCMD_for (char *); -void WCMD_give_help (char *command); +void WCMD_for (WCHAR *); +void WCMD_give_help (WCHAR *command); void WCMD_goto (void); -void WCMD_if (char *); +void WCMD_if (WCHAR *); void WCMD_leave_paged_mode(void); -void WCMD_more (char *); +void WCMD_more (WCHAR *); void WCMD_move (void); -void WCMD_output (const char *format, ...); -void WCMD_output_asis (const char *message); -void WCMD_parse (char *s, char *q, char *p1, char *p2); +void WCMD_output (const WCHAR *format, ...); +void WCMD_output_asis (const WCHAR *message); +void WCMD_parse (WCHAR *s, WCHAR *q, WCHAR *p1, WCHAR *p2); void WCMD_pause (void); -void WCMD_pipe (char *command); +void WCMD_pipe (WCHAR *command); void WCMD_popd (void); void WCMD_print_error (void); -void WCMD_process_command (char *command); -void WCMD_pushd (char *); -int WCMD_read_console (char *string, int str_len); -void WCMD_remove_dir (char *command); +void WCMD_process_command (WCHAR *command); +void WCMD_pushd (WCHAR *); +int WCMD_read_console (WCHAR *string, int str_len); +void WCMD_remove_dir (WCHAR *command); void WCMD_rename (void); -void WCMD_run_program (char *command, int called); -void WCMD_setlocal (const char *command); +void WCMD_run_program (WCHAR *command, int called); +void WCMD_setlocal (const WCHAR *command); void WCMD_setshow_attrib (void); void WCMD_setshow_date (void); -void WCMD_setshow_default (char *command); -void WCMD_setshow_env (char *command); -void WCMD_setshow_path (char *command); +void WCMD_setshow_default (WCHAR *command); +void WCMD_setshow_env (WCHAR *command); +void WCMD_setshow_path (WCHAR *command); void WCMD_setshow_prompt (void); void WCMD_setshow_time (void); -void WCMD_shift (char *command); +void WCMD_shift (WCHAR *command); void WCMD_show_prompt (void); -void WCMD_title (char *); -void WCMD_type (char *); -void WCMD_verify (char *command); +void WCMD_title (WCHAR *); +void WCMD_type (WCHAR *); +void WCMD_verify (WCHAR *command); void WCMD_version (void); -int WCMD_volume (int mode, char *command); +int WCMD_volume (int mode, WCHAR *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); +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 CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext); -char *WCMD_LoadMessage(UINT id); +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 *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 @@ 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 @@ #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 @@ #define WCMD_ARGERR 1027 #define WCMD_VOLUMEDETAIL 1028 #define WCMD_VOLUMEPROMPT 1029 +#define WCMD_NOPATH 1030 +#define WCMD_ANYKEY 1031 +#define WCMD_CONSTITLE 1032 +#define WCMD_VERSION 1033 + /* msdn specified max for Win XP */ #define MAXSTRING 8192
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 85fe005..ae27415 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c
@@ -30,27 +30,70 @@ WINE_DEFAULT_DEBUG_CHANNEL(cmd); -const char * const inbuilt[] = {"ATTRIB", "CALL", "CD", "CHDIR", "CLS", "COPY", "CTTY", - "DATE", "DEL", "DIR", "ECHO", "ERASE", "FOR", "GOTO", - "HELP", "IF", "LABEL", "MD", "MKDIR", "MOVE", "PATH", "PAUSE", - "PROMPT", "REM", "REN", "RENAME", "RD", "RMDIR", "SET", "SHIFT", - "TIME", "TITLE", "TYPE", "VERIFY", "VER", "VOL", - "ENDLOCAL", "SETLOCAL", "PUSHD", "POPD", "ASSOC", "COLOR", "FTYPE", - "MORE", "EXIT" }; +const WCHAR inbuilt[][10] = { + {'A','T','T','R','I','B','\0'}, + {'C','A','L','L','\0'}, + {'C','D','\0'}, + {'C','H','D','I','R','\0'}, + {'C','L','S','\0'}, + {'C','O','P','Y','\0'}, + {'C','T','T','Y','\0'}, + {'D','A','T','E','\0'}, + {'D','E','L','\0'}, + {'D','I','R','\0'}, + {'E','C','H','O','\0'}, + {'E','R','A','S','E','\0'}, + {'F','O','R','\0'}, + {'G','O','T','O','\0'}, + {'H','E','L','P','\0'}, + {'I','F','\0'}, + {'L','A','B','E','L','\0'}, + {'M','D','\0'}, + {'M','K','D','I','R','\0'}, + {'M','O','V','E','\0'}, + {'P','A','T','H','\0'}, + {'P','A','U','S','E','\0'}, + {'P','R','O','M','P','T','\0'}, + {'R','E','M','\0'}, + {'R','E','N','\0'}, + {'R','E','N','A','M','E','\0'}, + {'R','D','\0'}, + {'R','M','D','I','R','\0'}, + {'S','E','T','\0'}, + {'S','H','I','F','T','\0'}, + {'T','I','M','E','\0'}, + {'T','I','T','L','E','\0'}, + {'T','Y','P','E','\0'}, + {'V','E','R','I','F','Y','\0'}, + {'V','E','R','\0'}, + {'V','O','L','\0'}, + {'E','N','D','L','O','C','A','L','\0'}, + {'S','E','T','L','O','C','A','L','\0'}, + {'P','U','S','H','D','\0'}, + {'P','O','P','D','\0'}, + {'A','S','S','O','C','\0'}, + {'C','O','L','O','R','\0'}, + {'F','T','Y','P','E','\0'}, + {'M','O','R','E','\0'}, + {'E','X','I','T','\0'} +}; HINSTANCE hinst; DWORD errorlevel; int echo_mode = 1, verify_mode = 0, defaultColor = 7; static int opt_c, opt_k, opt_s; -const char newline[] = "\n"; -const char version_string[] = "CMD Version " PACKAGE_VERSION "\n\n"; -const char anykey[] = "Press Return key to continue: "; -char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; +const WCHAR newline[] = {'\n','\0'}; +static const WCHAR equalsW[] = {'=','\0'}; +WCHAR anykey[100]; +WCHAR version_string[100]; +WCHAR quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH]; BATCH_CONTEXT *context = NULL; extern struct env_stack *pushd_directories; -static const char *pagedMessage = NULL; +static const WCHAR *pagedMessage = NULL; +static char *output_bufA = NULL; +#define MAX_WRITECONSOLE_SIZE 65535 -static char *WCMD_expand_envvar(char *start); +static WCHAR *WCMD_expand_envvar(WCHAR *start); /***************************************************************************** * Main entry point. This is a console application so we have a main() not a @@ -61,14 +104,22 @@ { 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 @@ } 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 @@ } } - 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 @@ *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 @@ * 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 @@ 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 @@ /* 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 @@ 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 @@ */ -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 @@ 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 @@ /* 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 @@ /* 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 @@ /* 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 @@ * 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 @@ * 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 @@ /* 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 @@ 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 @@ 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 @@ * 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 @@ 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 @@ * 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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_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 @@ *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 @@ 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 @@ * 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 @@ /******************************************************************* * 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 @@ * */ -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 @@ * 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 @@ * 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 @@ * 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 @@ /************************************************************************* * 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 @@ * Handle pipes within a command - the DOS way using temporary files. */ -void WCMD_pipe (char *command) { +void WCMD_pipe (WCHAR *command) { - char *p; - char temp_path[MAX_PATH], temp_file[MAX_PATH], temp_file2[MAX_PATH], temp_cmd[1024]; + 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'}; - 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 @@ /************************************************************************* * 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 @@ *(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 @@ 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 @@ *(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 @@ /* 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 @@ 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 @@ } 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 @@ * 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; +}