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:
+79
-29
@@ -103,12 +103,13 @@ CommandChoice (LPTSTR param)
|
|||||||
{
|
{
|
||||||
LPTSTR lpOptions;
|
LPTSTR lpOptions;
|
||||||
TCHAR Options[6];
|
TCHAR Options[6];
|
||||||
LPTSTR lpText = NULL;
|
LPTSTR lpText = NULL, lpTextParam = NULL;
|
||||||
|
UINT iSkipTextIndex = 0, iTextIndex;
|
||||||
BOOL bNoPrompt = FALSE;
|
BOOL bNoPrompt = FALSE;
|
||||||
BOOL bCaseSensitive = FALSE;
|
BOOL bCaseSensitive = FALSE;
|
||||||
BOOL bTimeout = FALSE;
|
BOOL bTimeout = FALSE;
|
||||||
INT nTimeout = 0;
|
INT nTimeout = 0;
|
||||||
TCHAR cDefault = _T('\0');
|
TCHAR cDefault = _T('\0'), cDefParam = _T('\0');
|
||||||
INPUT_RECORD ir;
|
INPUT_RECORD ir;
|
||||||
LPTSTR p, np;
|
LPTSTR p, np;
|
||||||
LPTSTR *arg;
|
LPTSTR *arg;
|
||||||
@@ -129,25 +130,6 @@ CommandChoice (LPTSTR param)
|
|||||||
return 0;
|
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 */
|
/* build parameter array */
|
||||||
arg = split (param, &argc, FALSE, FALSE);
|
arg = split (param, &argc, FALSE, FALSE);
|
||||||
|
|
||||||
@@ -159,14 +141,26 @@ CommandChoice (LPTSTR param)
|
|||||||
if (_tcsnicmp (arg[i], _T("/c"), 2) == 0)
|
if (_tcsnicmp (arg[i], _T("/c"), 2) == 0)
|
||||||
{
|
{
|
||||||
if (arg[i][2] == _T(':'))
|
if (arg[i][2] == _T(':'))
|
||||||
lpOptions = &arg[i][3];
|
lpOptions = &arg[i][3]; /* "/c:XYZ" (DOS and NT) */
|
||||||
else
|
else if (arg[i][2])
|
||||||
lpOptions = &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);
|
ConErrResPuts(STRING_CHOICE_ERROR);
|
||||||
freep (arg);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,13 +168,27 @@ CommandChoice (LPTSTR param)
|
|||||||
{
|
{
|
||||||
bNoPrompt = TRUE;
|
bNoPrompt = TRUE;
|
||||||
}
|
}
|
||||||
else if (_tcsnicmp (arg[i], _T("/s"), 2) == 0)
|
else if (_tcsnicmp (arg[i], _T("/s"), 2) == 0) /* DOS */
|
||||||
{
|
{
|
||||||
bCaseSensitive = TRUE;
|
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)
|
else if (_tcsnicmp (arg[i], _T("/t"), 2) == 0)
|
||||||
{
|
{
|
||||||
LPTSTR s;
|
LPTSTR s, end;
|
||||||
|
TCHAR cSaveDefault = cDefault;
|
||||||
|
|
||||||
if (arg[i][2] == _T(':'))
|
if (arg[i][2] == _T(':'))
|
||||||
{
|
{
|
||||||
@@ -195,17 +203,31 @@ CommandChoice (LPTSTR param)
|
|||||||
|
|
||||||
if (*s != _T(','))
|
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);
|
ConErrResPuts(STRING_CHOICE_ERROR_TXT);
|
||||||
freep (arg);
|
freep (arg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s++;
|
s++;
|
||||||
|
parse_timeout_seconds:
|
||||||
nTimeout = _ttoi(s);
|
nTimeout = _ttoi(s);
|
||||||
bTimeout = TRUE;
|
bTimeout = TRUE;
|
||||||
}
|
}
|
||||||
else if (arg[i][0] == _T('/'))
|
else if (arg[i][0] == _T('/'))
|
||||||
{
|
{
|
||||||
|
invalid_parameter_format:
|
||||||
ConErrResPrintf(STRING_CHOICE_ERROR_OPTION, arg[i]);
|
ConErrResPrintf(STRING_CHOICE_ERROR_OPTION, arg[i]);
|
||||||
freep (arg);
|
freep (arg);
|
||||||
return 1;
|
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 */
|
/* print text */
|
||||||
if (lpText)
|
if (lpText)
|
||||||
ConOutPrintf (_T("%s"), lpText);
|
ConOutPrintf (_T("%s"), lpText);
|
||||||
@@ -220,7 +269,8 @@ CommandChoice (LPTSTR param)
|
|||||||
/* print options */
|
/* print options */
|
||||||
if (bNoPrompt == FALSE)
|
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++)
|
for (i = 1; (unsigned)i < _tcslen (lpOptions); i++)
|
||||||
ConOutPrintf (_T(",%c"), lpOptions[i]);
|
ConOutPrintf (_T(",%c"), lpOptions[i]);
|
||||||
|
|||||||
Reference in New Issue
Block a user