// 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 #include /* * 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); }