263 lines
6.9 KiB
C
263 lines
6.9 KiB
C
// 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);
|
|
}
|