windows-nt/Source/XPSP1/NT/termsrv/admtools/utilsub/toolinit.c

263 lines
6.9 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
// Copyright (c) 1998-1999 Microsoft Corporation
/*
*
* Module Name:
*
* toolinit.c
*
* Abstract:
*
* This file contains initialization code that is shared among all
* the command line tools.
*
* Author:
*
* Breen Hagan (BreenH) Dec-16-98
*
* Environment:
*
* User Mode
*/
#include <windows.h>
#include <printfoa.h>
/*
* Function Implementations.
*/
/*
* MassageCommandLine()
*
* Obtains the command line, parses it as a UNICODE string, and returns
* it in the ANSI argv style.
*
* Parameters:
* IN DWORD dwArgC: The number of arguments on the command line.
*
* Return Values:
* Returns a WCHAR array (WCHAR **), or NULL if an error occurs.
* Extended error information is available from GetLastError().
*
*/
WCHAR**
MassageCommandLine(
IN DWORD dwArgC
)
{
BOOL fInQuotes = FALSE, fInWord = TRUE;
DWORD i, j, k, l;
WCHAR *CmdLine;
WCHAR **ArgVW;
/*
* argv can't be used because its always ANSI.
*/
CmdLine = GetCommandLineW();
/*
* Convert from OEM character set to ANSI.
*/
//OEM2ANSIW(CmdLine, (USHORT)wcslen(CmdLine));
/*
* Massage the new command line to look like an argv type
* because ParseCommandLine() depends on this format
*/
ArgVW = (WCHAR **)LocalAlloc(
LPTR,
(dwArgC + 1) * (sizeof(WCHAR *))
);
if(ArgVW == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(NULL);
}
/*
* Parse CmdLine by spaces (or tabs), ignoring spaces inside double quotes;
* i.e. "1 2" is one argument, but cannot contain the double quotes
* after parsing. Also, multiple spaces inside quotes are maintained,
* while multiple spaces outside of quotes are condensed. Example:
*
* test.exe 1 "2 3" 4"5 6"7 8 '9 10'
* will have as arguments:
*
* 0: test.exe
* 1: 1
* 2: 2 3
* 3: 45 67
* 4: 8
* 5: '9
* 6: 10'
*/
i = j = k = 0;
while (CmdLine[i] != (WCHAR)NULL) {
if (CmdLine[i] == L' '||CmdLine[i] == L'\t') {
if (!fInQuotes) {
fInWord = FALSE;
if (i != k) {
CmdLine[i] = (WCHAR)NULL;
ArgVW[j] = (WCHAR *)LocalAlloc(
LPTR,
(i - k + 1) * (sizeof(WCHAR))
);
if (ArgVW[j] != NULL) {
wcscpy(ArgVW[j], &(CmdLine[k]));
k = i + 1;
j++;
if (j > dwArgC) {
SetLastError(ERROR_INVALID_PARAMETER);
goto CleanUp;
}
} else {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto CleanUp;
}
} else {
k = i + 1;
}
}
} else if (CmdLine[i] == L'\"') {
DWORD dwLen = wcslen(&(CmdLine[i]));
//Added by a-skuzin
//case when we need to have quota inside parameter and use " \" "
if(i && (CmdLine[i-1] == L'\\')) {
MoveMemory(
&(CmdLine[i-1]),
&(CmdLine[i]),
(dwLen+1) * sizeof(WCHAR) // drop 1 char, add NULL
);
i--;
fInWord = TRUE;
goto increment;
}
//end of "added by a-skuzin"
// Special case a double quote by itself or at the end of the line
if (fInQuotes && (l == i)) {
if ((dwLen == 1) || (CmdLine[i + 1] == L' ') || (CmdLine[i + 1] == L'\t')) {
k = i;
CmdLine[k] = (WCHAR)NULL;
fInQuotes = FALSE;
goto increment;
}
}
if (fInQuotes && fInWord) {
if ((dwLen == 2) && (CmdLine[i + 1] == L'\"')) {
MoveMemory(
&(CmdLine[i]),
&(CmdLine[i + 1]),
dwLen * sizeof(WCHAR) // drop 1 char, add NULL
);
goto increment;
}
if ((dwLen >= 3) &&
(CmdLine[i + 1] == L'\"') &&
(CmdLine[i + 2] != L' ') &&
(CmdLine[i + 2] != L'\t')) {
fInQuotes = FALSE;
MoveMemory(
&(CmdLine[i]),
&(CmdLine[i + 1]),
dwLen * sizeof(WCHAR) // drop 1 char, add NULL
);
goto increment;
}
if ((dwLen >= 3) &&
(CmdLine[i + 1] == L'\"') &&
(CmdLine[i + 2] == L' ') &&
(CmdLine[i + 2] == L'\t')) {
goto increment;
}
}
if (!fInQuotes && fInWord && (dwLen == 1) && (j == 0)) {
goto increment;
}
fInQuotes = !fInQuotes;
if (fInQuotes && !fInWord) {
fInWord = TRUE;
l = i;
}
MoveMemory(
&(CmdLine[i]),
&(CmdLine[i + 1]),
dwLen * sizeof(WCHAR) // drop 1 char, add NULL
);
i--;
} else {
fInWord = TRUE;
}
increment:
i++;
}
if (i != k) {
if (j >= dwArgC) {
SetLastError(ERROR_INVALID_PARAMETER);
goto CleanUp;
}
ArgVW[j] = (WCHAR *)LocalAlloc(
LPTR,
(i - k + 1) * (sizeof(WCHAR))
);
if (ArgVW[j] != NULL) {
wcscpy(ArgVW[j], &(CmdLine[k]));
} else {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto CleanUp;
}
} else if (fInQuotes && (l == i)) {
if (j >= dwArgC) {
SetLastError(ERROR_INVALID_PARAMETER);
goto CleanUp;
}
ArgVW[j] = (WCHAR *)LocalAlloc(
LPTR,
(i - k + 1) * (sizeof(WCHAR))
);
if (ArgVW[j] != NULL) {
wcscpy(ArgVW[j], &(CmdLine[k]));
} else {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto CleanUp;
}
}
ArgVW[dwArgC] = (WCHAR)NULL;
return(ArgVW);
CleanUp:
for (i = 0; i < dwArgC; i++) {
if (ArgVW[i] != NULL) {
LocalFree(ArgVW[i]);
}
}
LocalFree(ArgVW);
return(NULL);
}