mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[CMD] Add support for the NT CHOICE command syntax (#9284)
This makes our built-in choice command compatible with how choice is implemented on NT5.2+ (it isn't included in Windows XP and below), while retaining compatibility with how it worked in DOS/9x. - Changes /C and /T to also support the NT syntax. - Adds the /CS, /D and /M switches. This makes it easy for JIRA issue CORE-20043 to use this code to create a proper choice.exe
This commit is contained in:
+78
-28
@@ -103,12 +103,13 @@ CommandChoice (LPTSTR param)
|
||||
{
|
||||
LPTSTR lpOptions;
|
||||
TCHAR Options[6];
|
||||
LPTSTR lpText = NULL;
|
||||
LPTSTR lpText = NULL, lpTextParam = NULL;
|
||||
UINT iSkipTextIndex = 0, iTextIndex;
|
||||
BOOL bNoPrompt = FALSE;
|
||||
BOOL bCaseSensitive = FALSE;
|
||||
BOOL bTimeout = FALSE;
|
||||
INT nTimeout = 0;
|
||||
TCHAR cDefault = _T('\0');
|
||||
TCHAR cDefault = _T('\0'), cDefParam = _T('\0');
|
||||
INPUT_RECORD ir;
|
||||
LPTSTR p, np;
|
||||
LPTSTR *arg;
|
||||
@@ -129,25 +130,6 @@ CommandChoice (LPTSTR param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* retrieve text */
|
||||
p = param;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (*p == _T('\0'))
|
||||
break;
|
||||
|
||||
if (*p != _T('/'))
|
||||
{
|
||||
lpText = p;
|
||||
break;
|
||||
}
|
||||
np = _tcschr (p, _T(' '));
|
||||
if (!np)
|
||||
break;
|
||||
p = np + 1;
|
||||
}
|
||||
|
||||
/* build parameter array */
|
||||
arg = split (param, &argc, FALSE, FALSE);
|
||||
|
||||
@@ -159,28 +141,54 @@ CommandChoice (LPTSTR param)
|
||||
if (_tcsnicmp (arg[i], _T("/c"), 2) == 0)
|
||||
{
|
||||
if (arg[i][2] == _T(':'))
|
||||
lpOptions = &arg[i][3];
|
||||
else
|
||||
lpOptions = &arg[i][2];
|
||||
lpOptions = &arg[i][3]; /* "/c:XYZ" (DOS and NT) */
|
||||
else if (arg[i][2])
|
||||
lpOptions = &arg[i][2]; /* "/cXYZ" (DOS) */
|
||||
else if (i + 1 < argc && *arg[i + 1] != _T('/'))
|
||||
lpOptions = arg[iSkipTextIndex = ++i]; /* "/c XYZ" (NT) */
|
||||
|
||||
if (_tcslen (lpOptions) == 0)
|
||||
if (!*lpOptions)
|
||||
{
|
||||
ConErrResPuts(STRING_CHOICE_ERROR);
|
||||
freep(arg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (_tcsnicmp (arg[i], _T("/m"), 2) == 0) /* "/m msg" (NT) */
|
||||
{
|
||||
lpText = lpTextParam = arg[++i];
|
||||
if (i >= argc || *lpTextParam == _T('/'))
|
||||
{
|
||||
ConErrResPrintf(STRING_CHOICE_ERROR_OPTION, arg[--i]);
|
||||
freep(arg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (_tcsnicmp (arg[i], _T("/n"), 2) == 0)
|
||||
{
|
||||
bNoPrompt = TRUE;
|
||||
}
|
||||
else if (_tcsnicmp (arg[i], _T("/s"), 2) == 0)
|
||||
else if (_tcsnicmp (arg[i], _T("/s"), 2) == 0) /* DOS */
|
||||
{
|
||||
bCaseSensitive = TRUE;
|
||||
}
|
||||
else if (_tcsnicmp (arg[i], _T("/cs"), 3) == 0) /* NT */
|
||||
{
|
||||
bCaseSensitive = TRUE;
|
||||
}
|
||||
else if (_tcsnicmp (arg[i], _T("/d"), 2) == 0) /* "/d:X" and "/d X" (NT) */
|
||||
{
|
||||
if (arg[i][2] == _T(':'))
|
||||
cDefault = cDefParam = arg[i][3];
|
||||
else if (i + 1 < argc)
|
||||
cDefault = cDefParam = arg[iSkipTextIndex = ++i][0];
|
||||
else
|
||||
goto invalid_parameter_format;
|
||||
}
|
||||
else if (_tcsnicmp (arg[i], _T("/t"), 2) == 0)
|
||||
{
|
||||
LPTSTR s;
|
||||
LPTSTR s, end;
|
||||
TCHAR cSaveDefault = cDefault;
|
||||
|
||||
if (arg[i][2] == _T(':'))
|
||||
{
|
||||
@@ -195,17 +203,31 @@ CommandChoice (LPTSTR param)
|
||||
|
||||
if (*s != _T(','))
|
||||
{
|
||||
/* Just a number (NT syntax) */
|
||||
cDefault = cSaveDefault;
|
||||
if (arg[i][2] == _T(':'))
|
||||
s = &arg[i][3];
|
||||
else if (i + 1 < argc)
|
||||
s = arg[iSkipTextIndex = ++i];
|
||||
|
||||
_tcstol(s, &end, 10);
|
||||
if (end > s && !*end)
|
||||
goto parse_timeout_seconds;
|
||||
|
||||
failed_parse_timeout:
|
||||
ConErrResPuts(STRING_CHOICE_ERROR_TXT);
|
||||
freep (arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
s++;
|
||||
parse_timeout_seconds:
|
||||
nTimeout = _ttoi(s);
|
||||
bTimeout = TRUE;
|
||||
}
|
||||
else if (arg[i][0] == _T('/'))
|
||||
{
|
||||
invalid_parameter_format:
|
||||
ConErrResPrintf(STRING_CHOICE_ERROR_OPTION, arg[i]);
|
||||
freep (arg);
|
||||
return 1;
|
||||
@@ -213,6 +235,33 @@ CommandChoice (LPTSTR param)
|
||||
}
|
||||
}
|
||||
|
||||
if (bTimeout)
|
||||
{
|
||||
if (!cDefault) /* NT /t synax used without /d */
|
||||
goto failed_parse_timeout;
|
||||
if (nTimeout < 0 || (cDefParam && nTimeout > 9999)) /* DOS seems to be limited to 99, no ">" validation */
|
||||
goto failed_parse_timeout;
|
||||
if (IsKeyInString(lpOptions, cDefault, bCaseSensitive) < 0) /* The default must exist in the list of options */
|
||||
goto failed_parse_timeout;
|
||||
}
|
||||
|
||||
/* retrieve text */
|
||||
for (p = param, iTextIndex = 0; !lpTextParam; ++iTextIndex)
|
||||
{
|
||||
if (*p == _T('\0'))
|
||||
break;
|
||||
|
||||
if (*p != _T('/') && (!iSkipTextIndex || iTextIndex > iSkipTextIndex))
|
||||
{
|
||||
lpText = p;
|
||||
break;
|
||||
}
|
||||
np = _tcschr (p, _T(' '));
|
||||
if (!np)
|
||||
break;
|
||||
p = np + 1;
|
||||
}
|
||||
|
||||
/* print text */
|
||||
if (lpText)
|
||||
ConOutPrintf (_T("%s"), lpText);
|
||||
@@ -220,7 +269,8 @@ CommandChoice (LPTSTR param)
|
||||
/* print options */
|
||||
if (bNoPrompt == FALSE)
|
||||
{
|
||||
ConOutPrintf (_T("[%c"), lpOptions[0]);
|
||||
LPCTSTR prefix = lpText && lpText == lpTextParam ? _T(" ") : _T("");
|
||||
ConOutPrintf (_T("%s[%c"), prefix, lpOptions[0]);
|
||||
|
||||
for (i = 1; (unsigned)i < _tcslen (lpOptions); i++)
|
||||
ConOutPrintf (_T(",%c"), lpOptions[i]);
|
||||
|
||||
Reference in New Issue
Block a user