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